暂无图片
暂无图片
11
暂无图片
暂无图片
暂无图片

转载:23ai-数据库实现RAG

甲骨文云技术 2024-12-13
501

众所周知,特别是最新版的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_DIRas'/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 dataAS 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 500autoextend on next 500maxsize 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(50DEFAULT SYS_GUID() PRIMARY KEY,
    dataset_name VARCHAR2(50NOT NULL,
    document CLOB,
    cmetadata JSON,
    embedding VECTOR(*, FLOAT32)
);

这里使用Oracle提供的一套数据以及基于Python的API WEB工具实现数据向量化与导入(不做操作展示)。

2.4 直接LLM对话

SET SERVEROUTPUTON;

declare

    l_questionvarchar2(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_questionvarchar2(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 (selectdocument, 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 ROWS ONLYloop
        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。

编辑:殷海英

文章转载自甲骨文云技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论