本文介绍了检索增强生成(Retrieval-Augmented Generation, RAG)技术的概念,和如何搭建并使用检索增强生成RAG系统。
概念
大语言模型(LLM)在生成回复的准确性和实时性方面存在一定的局限性,因此不太适合直接应用于需要精确信息的客户服务或问答场景。为了解决这一问题,业界广泛采用了检索增强生成(Retrieval-Augmented Generation, RAG)技术,提升LLM的性能。这一技术显著提高了问答、摘要生成以及其他需要引用外部知识的自然语言处理(NLP)任务的质量。
RAG通过将大语言模型(如通义千问)与信息检索组件相结合,增强了模型生成答案的准确性和信息量。在处理用户查询时,RAG通过信息检索组件从知识库中寻找与查询相关的文档或信息片段,将这些检索到的内容与原始查询一起输入大语言模型后,模型能够利用现有的归纳生成能力,产生基于最新信息的、符合事实的回复,而无需对模型进行重新创建模型。
PolarDB部署的对话系统服务,通过集成大语言模型(LLM)和检索增强生成(RAG)技术,有效克服了LLM在准确性和实时性方面的局限,为多种问答场景提供了准确且信息丰富的响应。这种整合显著提升了自然语言处理任务的整体效能和用户体验。
RAG系统搭建流程架构图
搭建并使用检索增强生成RAG系统的整体流程示意图如下:
构建文档向量化和分词索引表
被检索的文档已存在数据库中
当需要被检索的文档已经存在数据库时,我们需要将文档向量化。
文档数据表
创建文档数据表SQL语句如下:
CREATE TABLE enterprise_context(
file_id varchar(256) COMMENT '文本溯源索引',
file_name varchar(256) COMMENT '标题中心内容',
content text COMMENT '文本内容',
category_id varchar(128) COMMENT '类目信息',
PRIMARY KEY (file_id)
);
插入文档数据
插入文档表数据的SQL语句如下:
INSERT INTO enterprise_context(file_id,file_name,content,category_id) VALUES
('doc1','PolarDB for AI简介','PolarDB for AI是基于PolarDB MySQL版的一个数据库内的分布式机器学习组件。其基于云原生的体系架构,通过SQL语句的方式提供了支持机器学习的一系列MLOps,包括:创建模型、查看模型状态、查看模型列表、模型评估和模型推理等能力;同时提供了一系列内置的机器学习和人工智能算法,包括:分类算法、回归算法和聚类算法等。基于MLOps和内置的模型,PolarDB for AI为数据驱动的智能应用提供了高效、可靠、方便的数据智能能力,打破了数据库和业务应用之间的系统墙,提供了基于数据库数据智能的一站式服务。','c1'),
('doc2','PolarDB for AI在搜索推荐中的应用','PolarDB for AI将传统的DB+AI的数据智能应用转变为一站式数据智能应用,从数据库服务于传统的数据工程师和算法工程师转变为DB+AI服务于业务工程师,直接与业务系统对接。基于PolarDB for AI的智能推荐算法和知识图谱技术,再结合阿里巴巴电商策略,为企业提供贯穿推荐能力的一站式服务,助力企业快速过渡冷启动过程。面向不同的业务场景定制个性化解决方案,持续提升核心业务能力,以实现业务营收增长。','c2')
文本转向量化模型_polar4ai_text2vec
支持将长篇文档分割成多个文本块,以便增加RAG文本检索的精确度。
文本数据需要切片处理
创建索引表
RAG索引表固定了参数名称和类型,具体表结构SQL语句如下:
/*polar4ai*/CREATE TABLE file_index_table(
chunk_id varchar(265),
chunk_content text_ik_smart,
file_id varchar(256),
file_name varchar(256),
category_id varchar(128),
vecs vector_768,
PRIMARY KEY(chunk_id)
);
RAG索引表中的参数说明如下:
参数 | 说明 | 示例值 |
chunk_id | {file_id}-{chunk_order},对每一个切片文本设置的主键id,在同一文件内按序递增。 | file1-1。 |
chunk_content | 切片文本,使用分词器进行分词,此处可使用text_ik_smart(粗粒度拆分的词) / text_ik_max_word(细粒度拆分的词) 等分词器进行分词。 | 文本内容。 |
file_id | 文件标识,用于溯源文本内容。 | xxx.docx。 |
file_name | 文件名、文件标题、与内容相关的语句(可选)。 | 中心内容。 |
category_id | 用于限定文档搜索范围,精确匹配的类目ID。 | c1。 |
vecs | 切片向量,使用_polar4ai_text2vec模型将切片文本转为向量值。 说明 _polar4ai_text2vec为文本转向量化模型,目前仅支持输出768维向量。 | [0.1, 0.2, ...]。 |
构建向量和分词索引
_polar4ai_text2vec
为文本转向量化模型,目前仅支持输出768维向量。将enterprise_context中的文档数据向量化并保存到RAG索引表中,当设置to_chunk=1
时,列chunk_id
和chunk_content
将通过切片方法生成。
/*polar4ai*/SELECT chunk_id, chunk_content, file_id, file_name, category_id FROM predict(model _polar4ai_text2vec, SELECT content, file_id, file_name, category_id FROM enterprise_context)
WITH (
x_cols='content',
primary_key='file_id',
mode='async',
vec_col='vecs',
to_chunk=1,
chunk_size=128,
chunk_overlap=16
)
INTO file_index_table;
/*polar4ai*/SHOW TASK `your-task-id`;
/*polar4ai*/SELECT * FROM file_index_table;
文本数据无需切片处理
创建索引表
RAG索引表固定了参数名称和类型,具体表结构说明如下:
/*polar4ai*/CREATE TABLE file_index_table(
file_id varchar(256),
file_name varchar(256),
chunk_content text_ik_smart,
category_id varchar(128),
vecs vector_768,
PRIMARY KEY(file_id)
);
RAG索引表中的参数说明如下:
参数 | 说明 | 示例值 |
file_id | 文件标识,用于溯源文本内容。 | xxx.docx。 |
file_name | 文件名、文件标题与内容相关的语句(可选)。 | 中心内容。 |
chunk_content | 文本内容,使用分词器进行分词,此处可使用text_ik_smart(粗粒度拆分的词) / text_ik_max_word (细粒度拆分的词)等分词器进行分词。 | 文本内容。 |
category_id | 用于限定文档搜索范围,精确匹配的类目ID。 | c1。 |
vecs | 切片向量,使用_polar4ai_text2vec模型将切片文本转为向量值。 说明
| [0.1, 0.2, ...]。 |
构建向量和分词索引
_polar4ai_text2vec
为文本转向量化模型,目前仅支持输出768维向量。将enterprise_context中的文档数据向量化并保存到RAG索引表中。
/*polar4ai*/SELECT chunk_content, file_id, file_name, category_id FROM predict(model _polar4ai_text2vec, SELECT content as chunk_content, file_id, file_name, category_id FROM enterprise_context)
WITH (
x_cols='chunk_content',
primary_key='file_id',
mode='async',
vec_col='vecs'
)
INTO file_index_table;
/*polar4ai*/SHOW TASK `your-task-id`;
/*polar4ai*/SELECT * FROM file_index_table;
文本数据向量化,更多详细过程请参见:案例二:搭建文档检索系统。
被检索的文档不存在数据库中
被检索的文档不在数据库中,我们会先将文档上传到数据库,并解析文档内容,再做文本向量化的工作。
创建文档知识库
上传文档数据
上传文档至数据库存储的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='{}' );
WITH()
中的参数说明如下:说明src_file_location示例文档请参见Polar4AI-Introduction.docx。
参数
说明
示例值
file_id
文件主键(不可重复)。
'Polar4AI'。
file_type
文件类型。
'.docx'。
src_file_location
文件URL地址。
'https://xxx.aliyuncs.com/Polar4AI-Introduction.docx'。
dest_file_name
目标文件名(可重复,不支持存储路径/)。
'Polar4AI-Introduction'。
metadata
元数据,暂时保留。
'{}'。
查看已上传的文档
查看已上传的文档的SQL语法如下,其中
unique_file_id
需替换为已通过UPLOAD FILE
上传的文件ID。/*polar4ai*/SHOW FILES; /*polar4ai*/SHOW FILE `unique_file_id`;
删除已上传的文档
删除文档的SQL语法如下:
/*polar4ai*/DROP FILE `unique_file_id`;
创建文档元数据表
在数据库中创建和更新元数据表,SQL语句如下:
CREATE TABLE file_id_list( file_id varchar(256) PRIMARY KEY, action_type varchar(10), category_id varchar(128) # any data format ... ); INSERT INTO file_id_list(file_id, action_type, category_id, ...) VALUES ('unique_file_id', 'add', 'c1', ...);
文档元数据表中参数说明如下:
参数
说明
示例值
file_id
UPLOAD FILE中指定的文件主键。
'Polar4AI'。
action_type
需要对文件做的操作,可选值包括['add', 'delete'],当action_type为'add'时,在索引表中增加该文件相关内容,并重新计算索引值。当action_type为'delete'时,在索引表中删除该文件的相关内容。
'add'
'delete'
''。
category_id
该文件的类目标识。
'c1'。
解析文件并构建向量和分词索引
创建索引表
向量和分词索引表固定了参数名称和类型,SQL语句如下:
/*polar4ai*/CREATE TABLE file_index_table( 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'。
file_name
文件名、文件标题、与内容相关的语句。
'Polar4AI-Introduction'。
chunk_content
切片文本,使用分词器进行分词,此处可使用text_ik_smart(粗粒度拆分的词) / text_ik_max_word(细粒度拆分的词)等分词器进行分词。
文档文本内容。
vecs
切片向量,使用_polar4ai_text2vec模型将切片文本转为向量。
[0.1, 0.2, ...]。
chunk_id
{file_id}-{chunk_order},对每一个chunk设置的主键id,在同一文件内按序递增。
'Polar4AI-1'。
根据文档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) WITH ( x_cols='chunk_content', primary_key='file_id', mode='async', resource='file', to_chunk=1, headers_to_split_on=-1, chunk_size=512, chunk_overlap=64, separator='' ) INTO file_index_table;
(可选)调整索引表内容。
根据文档元数据表file_id_list中的action_type,您可以指定增加或删除文档内容。将文档的类目标识category_id作为参数输入时,类目标识信息将存入向量与分词索引表,您可以通过设置RAG查询参数中的category_ids,限定文本检索的范围。示例如下:
file_id_list
中指明操作类型,添加或删除文档。/*polar4ai*/SELECT chunk_id, file_name, chunk_content, category_id FROM predict(model _polar4ai_text2vec, SELECT file_id, action_type, category_id FROM file_id_list) WITH ( x_cols='chunk_content', primary_key='file_id', mode='async', resource='file', to_chunk=1, headers_to_split_on=-1, chunk_size=512, chunk_overlap=64, separator='' ) INTO file_index_table;
_polar4ai_text2vec
为文本转向量化模型,目前仅支持输出768维向量。WITH()
中的参数说明如下:参数
说明
示例值或范围
x_cols
用于存储文本的字段。
chunk_content。
primary_key
文件列表的主键,文档ID。
id。
mode
文档数据的写入模式。目前仅支持async(异步)模式。
async。
resource
在文件解析流程中为file模型。
file。
to_chunk
文件中的文本是否进行切片。
0或1。
headers_to_split_on
to_chunk=1时按照指定标题层级进行切分
当
headers_to_split_on
值为-1时,对文件中所有层级标题进行分块。当
headers_to_split_on
值为x
时,对文件中小于等于x
层级的标题进行分块。
-1 ≤ x ≤ 6为整数值。
chunk_size
文本切分的最大长度。
chunk_size ≥ 50。
chunk_overlap
相邻两个切片之间的重叠字符数量。
chunk_overlap ≤ chunk_size。
separator
分块内切片之间的分隔符。
'' /','/','等。
展示task状态和结果
taskStatus
为finish
时表示成功完成文件解析任务,在索引表中可以查询到切片信息。/*polar4ai*/SHOW TASK `task-id`; /*polar4ai*/SELECT * FROM file_index_table LIMIT 10;
删除索引表中的记录
/*polar4ai*/DELETE FROM file_index_table WHERE file_id = 'unique_file_id';
检索增强生成RAG
您可以执行以下SQL语句在线使用RAG功能,查询返回模型生成结果、召回文本、对应文件名、向量得分、分词得分、混合得分的值:
/*polar4ai*/SELECT * FROM PREDICT(MODEL _polar4ai_rag, SELECT '问题内容') WITH (
index_name='file_index_table',
primary_key='chunk_id',
vec_top_k=5,
vec_score_threshold=0.0,
pos_top_k=3,
pos_score_threshold=0.0,
use_vec=1,
use_pos=1,
hybrid_type=0,
hybrid_score=0.8,
ranker_model='',
category_ids='',
file_id=''
);
WITH()
中的参数说明如下:
参数 | 说明 | 示例值或范围 |
index_name | 索引表名称。 | index_table。 |
primary_key | 索引表主键名称。 | chunk_id、file_id。 |
vec_top_k | 保留前K个向量检索相关度得分最高的结果。 | vec_top_k ≥ 0。 |
vec_score_threshold | 向量检索得分的阈值,去掉得分低于阈值的结果。 | vec_score_threshold ≥ 0。 |
pos_top_k | 保留前K个分词检索相关得分最高的结果。 | pos_top_k ≥ 0。 |
pos_score_threshold | 分词检索得分的阈值,去掉得分低于阈值的结果。 | pos_score_threshold ≥ 0。 |
use_vec | 是否使用向量检索,1表示是,0表示否,默认为1。 | 0或1。 |
use_pos | 是否使用分词检索,1表示是,0表示否,默认为1。 | 0或1。 |
hybrid_type | 混合得分类型: 0表示将两个结果取并集,排序得分通过hybrid_score计算。 1表示取并集,但只看位置,向量检索优先。 2表示取两个结果的交集,排序得分按hybrid_score计算。 | 0或1或2。 |
hybrid_score | 混合得分的比例为:hybrid_score*vec_score + (1-hybrid_score)*pos_score。 | 0 ≤ hybrid_score ≤ 1。 |
ranker_model | 表示创建模型后的ranker模型名称,默认为空。 | ''。 |
category_ids | 用英文逗号分隔category_id。 | 'c1, c2'。 |
file_id | 根据ID指定文件生成回答. | 'Polar4AI'。 |