1. 背景
大语言模型(LLM)在生成回复的准确性和实时性方面存在一定的局限性,因此不太适合直接应用于需要精确信息的客户服务或问答场景。为了解决这一问题,业界广泛采用了检索增强生成
(Retrieval-Augmented Generation, RAG)技术,提升LLM的性能。这一技术显著提高了问答、摘要生成以及其他需要引用外部知识的自然语言处理(NLP)任务的质量。RAG通过将大语言模型(如通义千问)与信息检索组件相结合,增强了模型生成答案的准确性和信息量。在处理用户查询时,RAG通过信息检索组件从知识库中寻找与查询相关的文档或信息片段,将这些检索到的内容与原始查询一起输入大语言模型后,模型能够利用现有的归纳生成能力,产生基于最新信息的、符合事实的回复,而无需对模型进行重新创建模型。
阿里云瑶池旗下的云原生数据库PolarDB目前已完全支持MySQL 9.0原生向量检索语法(The Vector Type[1],Vector Functions[2]),并可以通过列存索引IMCI的向量化执行和并行扫描加速KNN检索。开发者可以将PolarDB IMCI作为信息检索组件,并利用PolarDB for AI(集成的通义千问模型)提供的归纳生成能力,快速搭建一个RAG系统,有效克服了LLM在准确性和实时性方面的局限,为多种问答场景提供了准确且信息丰富的响应。
[1] https://dev.mysql.com/doc/refman/9.0/en/vector.html
[2] https://dev.mysql.com/doc/refman/9.0/en/vector-functions.html
2. RAG系统搭建架构图
基于PolarDB IMCI和PolarDB for AI搭建并使用RAG系统的整体流程示意图如下:
3. RAG系统搭建流程
离线构建向量索引
▶︎ 创建文档知识库
开发者需要先将文档上传到数据库,并解析文档内容,再做文本向量化的工作。
上传文档数据
上传文档至数据库存储的SQL语句如下:
/*polar4ai*/UPLOAD FILE docfile WITH ( file_id = 'unique_file_id', file_type = '.docx', src_file_location = 'your_file_url', dest_file_name = 'your_file_name.docx', metadata = '{}', overwritten = 1 );
WITH() 中的参数说明如下:
创建文档元数据表
在数据库中创建和更新元数据表,SQL语句如下:
CREATE TABLE file_id_list_rag ( file_id varchar(256) PRIMARY KEY ); INSERT INTO file_id_list_rag(file_id) VALUES ('unique_file_id');
文档元数据表中参数说明如下:
▶︎ 文档切片和向量化
创建临时表
存储文本转向量模型得到的切片和向量的临时表固定了参数名称和类型,SQL语句如下:
/*polar4ai*/CREATE TABLE file_index_table_rag( chunk_id varchar(265), chunk_content text_ik_smart, file_id varchar(256), file_name varchar(256), vecs vector_768, PRIMARY KEY(chunk_id));
临时表中参数说明如下:
文本转向量
从文档元数据表中选取需要进行分词和向量化的file_id,解析文档内容并使用_polar4ai_text2vec模型的predict方法将文档切片转为向量:
/*polar4ai*/SELECT chunk_id, file_id, file_name, chunk_content FROM predict(model _polar4ai_text2vec, SELECT file_id FROM file_id_list_rag) WITH ( x_cols='chunk_content', primary_key='file_id', resource='file', mode='async', to_chunk=1, headers_to_split_on=2, chunk_size=1024, chunk_overlap=64, separator='')INTO file_index_table_rag;
_polar4ai_text2vec 为文本转向量模型,目前仅支持输出768维向量。 WITH() 中的参数说明如下:
▶︎ 构建PolarDB IMCI向量索引
创建向量索引表
使用MySQL原生的向量类型和语法创建向量索引表,同时构建列存索引:
create table vector_index ( chunk_id varchar(265), chunk_content text, file_id varchar(256), file_name varchar(256), vecs vector(768), PRIMARY KEY(chunk_id)) COMMENT 'columnar=1';
构建向量索引
首先需要从上一节的临时表中查询切片和向量的中间结果:
/*polar4ai*/select * from file_index_table_rag;
将中间结果通过 string_to_vector 表达式写入向量索引表:
insert into vector_index (file_name,file_id,vecs,chunk_content,chunk_id)values ("file_name","file_id",string_to_vector("[...]"),'chunk_content',"chunk_id");
在线RAG查询
▶︎ 问题向量化
将问题文本进行在线向量化的SQL语句如下:
/*polar4ai*/SELECT * FROM predict(model _polar4ai_text2vec, SELECT 'question') with();
▶︎ PolarDB IMCI向量召回
使用 distance 表达式并借助IMCI加速KNN向量检索,召回相似度最高的K个向量和文本切片:
select /*+ SET_VAR(use_imci_engine=forced) */ file_name,chunk_content, distance(string_to_vector("[...]"), vecs, "COSINE") as d from vector_index order by d limit 5;
▶︎ LLM基于Prompt生成回答
将问题和召回的文本切片组成Prompt,调用PolarDB for AI内置的通义千问模型进行在线推理,生成回答:
"/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_tongyi, SELECT 'prompt') with ()"
4. RAG系统示例
参照上述流程,开发者可以借助PolarDB IMCI和PolarDB for AI快速搭建一个RAG系统,本文的附录中提供了一个简单示例的代码。这个示例对IMCI的一些官方文档创建一个文档知识库,并在PolarDB IMCI上构建向量索引,然后利用PolarDB for AI集成的通义千问模型搭建出一个RAG系统,同时提供一个简单的Web服务作为问答交互。借助这个RAG系统,LLM也可以正确回答IMCI相关的领域内问题。
运行RAG系统
在ECS上根据requirements.txt正确安装python环境后,如下图所示依次运行:
- 1_upload_file.py 创建文档知识库
- 2_vectorization.py 对文档切片并向量化,并在PolarDB IMCI上构建向量索引
- 3_rag.py启动RAG 系统的Web服务
问答示例
hashmatch是IMCI专有的一个算子,对于问题“imci中的hashmatch是什么”,RAG系统可以从PolarDB IMCI中召回相似文档切片,并作为Prompt提供给LLM,使LLM也能正确回答有关hashmatch的问题。
附录
▶︎ RAG系统示例代码
复制下方链接至浏览器即可获取:
🔗 https://github.com/nanlongyu/rag_service_demo
▶︎ 运行环境
运行该示例需要开发者拥有下列资源:
- 包含列存节点和AI节点的PolarDB集群:版本为8.0.2.2.27
- ECS:系统镜像为Alibaba Cloud Linux 3.2104 LTS 64位,Python版本为3.9.20
- OSS
其中列存节点用于构建向量索引,AI节点提供文本转向量和LLM能力,ECS用于运行RAG系统和部署Web服务,OSS用于上传知识库文档。除PolarDB集群和OSS为必须外,开发者也可以在其他合适的环境中运行RAG系统和部署Web服务。
开发者需要将上述资源的相关访问配置更新到 1_upload_file.py, 2_vectorization.py 和 3_rag.py 中,然后参照RAG系统示例这一章节运行RAG系统。