数据库管理270期 2024-12-11
数据库管理-第270期 23ai:数据库实现RAG(20241211)
作者:胖头鱼的鱼缸(尹海文)
Oracle ACE Pro: Database
PostgreSQL ACE Partner
10年数据库行业经验
拥有OCM 11g/12c/19c、MySQL 8.0 OCP、Exadata、CDP等认证
墨天轮MVP,ITPUB认证专家,数盟会长老会成员,OCM讲师,PolarDB开源社区、青学会MOP社区技术顾问,HaloDB外聘技术顾问,OceanBase观察团成员
圈内拥有“总监”称号,非著名社恐(社交恐怖分子)
公众号、墨天轮:胖头鱼的鱼缸;CSDN:胖头鱼的鱼缸(尹海文);ITPUB:yhw1809。
除授权转载并标明出处外,均为“非法”抄袭
众所周知,特别是最新版的Oracle数据库版本命名从23c(Converged)到了23ai,同时Oracle也将“以AI为中心的企业基础架构”作为核心战略目标。本期跟随总监,一起来看看如何在Oracle 23ai中实现RAG。
本次操作系统使用为OracleLinux 9.4(数据库)/8.10(LLM),数据库版本为单实例Oracle 23ai(23.5.0.24.07),LLM为通义千问2-7B(Qwen2-7B)(当然也可以使用其他的模型)。除sqlplus外,本篇文章部分展示使用最新版sqldeveloper。
1 数据库向量嵌入能力
1.1 导入向量嵌入模型
在开始基于Oracle 23ai的数据库RAG的演示之前,先演示Oracle Vector DB的库内向量嵌入能力,使用text2vec-large-chinese模型,需要将向量嵌入模型处理为标准的ONNX格式:bge-base-zh-v1.5.onnx(大小需控制在1G内),onnx文件放到oracle家目录中。
create or replace directory MODELS_DIR as '/home/oracle';
BEGIN
DBMS_VECTOR.LOAD_ONNX_MODEL(
directory => 'MODELS_DIR',
file_name => 'bge-base-zh-v1.5.onnx',
model_name => 'embedding_model'
);
END;
/
可以通过以下语句查看已导入的模型:
SELECT MODEL_NAME, MINING_FUNCTION, ALGORITHM, ALGORITHM_TYPE, MODEL_SIZE
FROM USER_MINING_MODELS;
SELECT MODEL_NAME, ATTRIBUTE_NAME, ATTRIBUTE_TYPE, DATA_TYPE,VECTOR_INFO
FROM USER_MINING_MODEL_ATTRIBUTES
WHERE MODEL_NAME = 'EMBEDDING_MODEL';
1.2 向量嵌入
SELECT VECTOR_EMBEDDING(embedding_model USING 'Hello, World' as data) AS embedding;
这里就可以看到在数据库内即可实现向量嵌入操作,当然数据库内没有GPU,其嵌入效率远不如外部使用GPU提供算力的模型。当然Oracle数据库也可以在库内直接调用外部大模型,这将在后面的RAG环境进行演示。
2 部署LLM
Ollama是一个大模型运行框架,可以非常快捷的使用无GPU环境运行大模型。这里使用Ollama来运行通义千问LLM(当然也可以直接使用Python或其他方式运行),机器IP地址为10.10.10.21。
1.1 安装Ollama
curl -fsSL https://ollama.com/install.sh | sh
1.2 启动Ollama
vim /etc/systemd/system/ollama.service
#在[Service]中添加以下内容
Environment="OLLAMA_HOST=0.0.0.0:8098"
systemctl start ollama.service
1.3 启动Qwen2-7B
OLLAMA_HOST=0.0.0.0:8098 ollama run qwen2:7b-instruct
通过该命令会直接通过网络下载通义千问LLM,也可以离线下载大模型文件运行。
1.4 测试部署
curl http://10.10.10.21:8098/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2:7b-instruct",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me something about large language models."}
]
}'
由于没有GPU,响应略慢。
3 数据库配置
数据库基本连接信息为:10.10.10.31:1521/pdbprod1(PDB)。
使用最新版的sqldeveloper做演示。
2.1 安装APEX
APEX下载地址:https://www.oracle.com/tools/downloads/apex-downloads/
unzip apex_24.1.zip
cd apex/
sqlplus / as sysdba
@apexins.sql SYSAUX SYSAUX TEMP /i/ @?/rdbms/admin/utlrp.sql
2.2 创建用户并赋权
create tablespace users datafile size 500m autoextend on next 500m maxsize unlimited;
create user llm identified by llm;
grant DB_DEVELOPER_ROLE to llm;
alter user llm default tablespace users quota unlimited on users;
2.3 导入测试数据
CREATE TABLE lab_vecstore (
id VARCHAR2(50) DEFAULT SYS_GUID() PRIMARY KEY,
dataset_name VARCHAR2(50) NOT NULL,
document CLOB,
cmetadata JSON,
embedding VECTOR(*, FLOAT32)
);
这里使用Oracle提供的一套数据以及基于Python的API WEB工具实现数据向量化与导入(不做操作展示)。
2.4 直接LLM对话
SET SERVEROUTPUT ON;
declare
l_question varchar2(500) := 'Oracle 23ai 新特性';
l_input CLOB;
l_clob CLOB;
j apex_json.t_values;
l_embedding CLOB;
l_context CLOB;
l_rag_result CLOB;
begin
apex_web_service.g_request_headers(1).name := 'Content-Type';
apex_web_service.g_request_headers(1).value := 'application/json';
l_input := '{"text": "' || l_question || '"}';
-- 第一步:提示工程:给大语言模型明确的指示
l_input := '{
"model": "qwen2:7b-instruct",
"messages": [
{"role": "system", "content": "你是一个诚实且专业的数据库知识问答助手,请回答用户提出的问题。"},
{"role": "user", "content": "' || l_question || '"}
]
}';
-- 第二步:调用大语言模型,生成结果
l_clob := apex_web_service.make_rest_request(
p_url => 'http://10.10.10.21:8098/v1/chat/completions',
p_http_method => 'POST',
p_body => l_input
);
apex_json.parse(j, l_clob);
l_rag_result := apex_json.get_varchar2(p_path => 'choices[%d].message.content', p0 => 1, p_values => j);
dbms_output.put_line('*** Result: ' || chr(10) || l_rag_result);
end;
/
这里可能会出现以下报错:
需要在CDB执行以下命令:
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('connect', 'resolve'),
principal_name => 'APEX_240100',
principal_type => xs_acl.ptype_db
)
);
END;
/
然后会继续出现以下报错:
需要在CDB执行以下命令:
grant inherit privileges on user sys to APEX_240100;
然后可以正常出结果了:
但是这里我们可以看到未使用RAG方式,大模型给出的结果非常离谱。当然也可以多次执行,结果会有所不同,但总体来说结果都比较离谱。
2.5 RAG方式与LLM对话
这里先说明一下,在10.10.10.21服务器8099端口运行了另一套基于text2vec-large-chinese的向量嵌入程序,也就是前面导入数据使用的,在使用RAG方式与LLM对话过程中会先将提问向量化后与知识库进行关联匹配。
declare
l_question varchar2(500) := 'Oracle 23ai 新特性';
l_input CLOB;
l_clob CLOB;
j apex_json.t_values;
l_embedding CLOB;
l_context CLOB;
l_rag_result CLOB;
begin
apex_web_service.g_request_headers(1).name := 'Content-Type';
apex_web_service.g_request_headers(1).value := 'application/json';
l_input := '{"text": "' || l_question || '"}';
-- 第一步:向量化用户问题
l_clob := apex_web_service.make_rest_request(
p_url => 'http://10.10.10.21:8099/workshop/embedding',
p_http_method => 'POST',
p_body => l_input
);
apex_json.parse(j, l_clob);
l_embedding := apex_json.get_varchar2(p_path => 'data.embedding', p_values => j);
-- dbms_output.put_line('*** embedding: ' || l_embedding);
-- 第二步:从向量数据库中检索出与问题相似的内容
for rec in (select document, json_value(cmetadata, '$.source') as src_file
from lab_vecstore
where dataset_name='oracledb_docs'
order by VECTOR_DISTANCE(embedding, to_vector(l_embedding))
FETCH FIRST 3 ROWS ONLY) loop
l_context := l_context || rec.document || chr(10);
end loop;
-- 第三步:提示工程:将相似内容和用户问题一起,组成大语言模型的输入
l_context := replace(replace(replace(l_context, '''', ''), '"', '\"'), chr(10), '\n');
l_input := '{
"model": "qwen2:7b-instruct",
"messages": [
{"role": "system", "content": "你是一个诚实且专业的数据库知识问答助手,请根据提供的上下文内容,回答用户的问题。\n 以下是上下文内容:' || l_context || '"},
{"role": "user", "content": "' || l_question || '(请仅根据提供的上下文内容回答,不要试图编造答案)"}
]
}';
-- 第四步:调用大语言模型,生成RAG结果
l_clob := apex_web_service.make_rest_request(
p_url => 'http://10.10.10.21:8098/v1/chat/completions',
p_http_method => 'POST',
p_body => l_input
);
apex_json.parse(j, l_clob);
l_rag_result := apex_json.get_varchar2(p_path => 'choices[%d].message.content', p0 => 1, p_values => j);
dbms_output.put_line('*** RAG Result: ' || chr(10) || l_rag_result);
end;
/
这时候我们可以看到使用RAG方式与LLM对话的结果就会准确很多。这里我们可以再执行一次:
总结
本期主要展示了Oracle 23ai的库内与库外向量嵌入能力,以及配合使用APEX可以在数据库中调用外部模型实现RAG。
老规矩,知道写了些啥。