数据库管理-第270期 23ai:数据库实现RAG(20241211)

来源:这里教程网 时间:2026-03-03 21:00:44 作者:

数据库管理-第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。 除授权转载并标明出处外,均为“非法”抄袭

演示文稿1_01.png 众所周知,特别是最新版的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';

image.png image.png

1.2 向量嵌入

SELECT VECTOR_EMBEDDING(embedding_model USING 'Hello, World' as data) AS embedding;

image.png 这里就可以看到在数据库内即可实现向量嵌入操作,当然数据库内没有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

image.png

1.2 启动Ollama

vim /etc/systemd/system/ollama.service#在[Service]中添加以下内容
Environment="OLLAMA_HOST=0.0.0.0:8098"

image.png

systemctl start ollama.service

image.png

1.3 启动Qwen2-7B

OLLAMA_HOST=0.0.0.0:8098 ollama run qwen2:7b-instruct

通过该命令会直接通过网络下载通义千问LLM,也可以离线下载大模型文件运行。

image.png

1.4 测试部署

image.png

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."}
        ]
    }'

image.png 由于没有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.zipcd 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工具实现数据向量化与导入(不做操作展示)。 image.png

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;
/

这里可能会出现以下报错: image.png 需要在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;
/

然后会继续出现以下报错: image.png 需要在CDB执行以下命令:

grant inherit privileges on user sys to APEX_240100;

然后可以正常出结果了: image.png 但是这里我们可以看到未使用RAG方式,大模型给出的结果非常离谱。当然也可以多次执行,结果会有所不同,但总体来说结果都比较离谱。 image.png

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;
/

image.png

这时候我们可以看到使用RAG方式与LLM对话的结果就会准确很多。这里我们可以再执行一次: image.png

总结

本期主要展示了Oracle 23ai的库内与库外向量嵌入能力,以及配合使用APEX可以在数据库中调用外部模型实现RAG。 老规矩,知道写了些啥。

相关推荐