之前本科毕设写过的一个项目,思维难度不大,可供参考,如有疑问或者勘误,请在评论区或者私信提问。
可以先看一下简历怎么描述这个项目的背景与功能简介,当然你可以任意换成你自己的任务(比如电商客服助手,买药小客服,java代码助手,前端页面生成器等等)
预处理(RAG)
现如今大模型的通用推理能力已经比较强了,但可能在某些特殊领域仍然匮乏,那么我们怎么提高大模型在这些领域的回答能力,有以下解决方案:
- 利用海量的私有数据进行重新训练,能够得到领域的专家大模型
- 微调 也就是fine-tune
- RAG
前两种对于一般个人开发者或者小型企业成本太高,所以我们采用RAG技术来进行构建私有知识库,来尽可能让大模型贴近我们想要的输出。
RAG:Retrieval
(检索)- Augmented
(增强)- Generation
(生成)
RAG的核心流程是:首先,将文本数据转换为嵌入向量并存储在向量数据库中;然后,当用户提出问题时,检索器会从向量数据库中检索与问题最相关的文档片段;最后,将检索到的文档片段与原始问题一起作为提示输入给LLM,LLM再基于这些信息生成最终答案。
RAG的优势在于它能够提高LLM响应的准确性、可控性和相关性。它特别适用于需要应对信息不断更新的场景,能有效减少错误信息生成和性能下降的问题。此外,RAG还支持动态更新知识库内容,可以根据企业的实际需要快速调整并反映最新情况。
我们将从几个过程的流程图来完整解释这一过程:
RAG工作流程
检索的数据源是怎么来的?
数据源可以是我们提前收集好的对应语料,比如我想做一个智能客服:我可以提前做一个文档,把所有的问题都进行收集汇总,q: 什么时间发货 ans:48小时内发货 q:这两种商品有什么区别 ans:商品1有xx功能,商品2更便宜等等…
RAG技术是怎么进行检索的?
流程图如下:
第一步用户提出问题,首先会将问题描述转为高维向量(embedding,词向量)
第二步在向量数据库中,找到相似度最高的k条内容
第三步将检索的知识文档融入到我们的prompt提示中,再向AI进行提问
其中的过程可以详细解释一下:
为什么要把用户提出的问题转为向量?
用户提的问题是一段文字,经过编码器(encoder)会转为一个向量,而且这个向量会携带原有的深层语义信息以及上下文的语境
向量数据库是怎么检索的,相似度是如何计算的?
在向量空间中,可以通过计算向量之间的相似度(如余弦相似度、欧氏距离等)来衡量文本之间的语义相似性。将问题转化为高维向量后,可以快速找到与之最相似的知识库片段,从而为后续的生成模块提供最相关的上下文信息.
同时这种检索方式要比单独对比每个字符串的重叠度要快的多,计算成本也低
我们通过这种方式费劲周章构建知识库,又检索知识库,为什么不直接通过prompt植入这些语料或者已知信息?
- 处理大规模数据:当面对海量数据时,直接在提示词中植入所有信息会导致提示词过长,影响模型性能。而构建知识库可以高效地存储和管理大规模数据,通过检索模块快速找到与问题最相关的部分。
(本质原因是在大规模数据时,植入知识会导致输入token大幅增加,提高服务成本)
动态更新知识:知识库可以方便地进行更新和维护,确保模型能够访问到最新的信息。这对于需要实时或定期更新知识的场景(如政策变化、新闻事件等)尤为重要。
减少幻觉和错误:RAG技术通过从外部知识库中检索相关信息,为模型提供准确的上下文,有助于减少模型产生不准确或幻觉性回答的可能性。
提高回答的准确性和相关性:检索到的与问题高度相关的文档片段能够为模型生成回答提供更有针对性的依据,从而提高回答的质量。
适用场景
- 直接植入信息适用场景:适用于数据量较小、信息相对固定且不需要频繁更新的情况。例如,处理一些简单的问答任务或特定领域的固定知识查询。
- RAG技术适用场景:适用于需要处理大规模动态数据、对回答准确性和时效性要求较高的场景。例如,智能客服、专业领域的知识问答系统、需要实时更新信息的分析工具等
我们通过RAG的方式在提问中植入了部分知识库,大模型在回答时优先考虑已有知识还是我们提供的知识?
在实际应用中,大模型在回答时会根据具体情况动态地平衡知识库中的知识和已有的知识。例如,当知识库中的信息与问题高度相关且准确时,模型会更倾向于参考这些信息;而当知识库中的信息不足或不明确时,模型则会更多地依赖已有的知识进行回答。
RAG中的向量数据库是怎么构建的?
我以text2SQL这个任务为例,拿了两个数据集通过将数据集进行片段划分,然后利用编码器构建向量索引
一般用什么工具来实现这一过程?
1.、基于开源知识库平台快速使用RAG
(Dify、FastGPT 等)
2、基于LLM应用框架来上手RAG
(OpenAI SDK、Langchain、LlamaIndex、Vercel AI SDK)
下游任务
以2个功能为例解释一下我之前调用AI大模型生成回答的过程:text2sql和sql2text
text2sql
生成流程:
- 用户提问,LLM大模型生成初步需求
- 检索向量数据库
- 第二次提问时 prompt + 检索块
- 此处分成两部分:1. 创建表,生成指定格式的配置;2. 对表的增删改查,直接生成代码
为什么要有第一次提问?
这一步作用主要是为了让用户提问的问题更精细或者标准化,方便更好的生成高质量回答;另外是之前的大模型并没有思维链(thinking)的过程,这一步的作用也是为了大模型先进行推理得到一个初步思考过程
创建表的特殊处理,为什么要生成一个指定json格式的配置?而不是直接生成代码?
指定ts格式如下:
interface field{
ids?: number;
id?: number;
autoIncrement?:boolean,//是否自增
comment?: string, // 字段描述
fieldName: string, // 字段名
fieldType: string, // 字段类型
mockParams?: string, // 模拟参数
mockType?: string, // 模拟数据的类型
notNull: boolean, // 是否可以为空
primaryKey: boolean, // 是否主键
defalutValue?: string, // 默认值
}
interface tableData{
id: number,
tableName: string, // 表名
comment?: string, // 表注释
fieldList: field[], // 字段列表
dbName?: string, // 数据库名
mockNum: number // 模拟生成的数据个数
}
举一个具体例子:
{
"tableData": {
"id": 1,
"tableName": "users",
"comment": "用户表",
"fieldList": [
{
"ids": 101,
"id": 1,
"autoIncrement": true,
"comment": "用户唯一标识",
"fieldName": "user_id",
"fieldType": "INT",
"notNull": true,
"primaryKey": true
},
{
"id": 2,
"autoIncrement": false,
"comment": "用户姓名",
"fieldName": "user_name",
"fieldType": "VARCHAR(50)",
"notNull": true,
"primaryKey": false,
"defalutValue": "unknown"
},
{
"id": 3,
"autoIncrement": false,
"comment": "用户邮箱",
"fieldName": "email",
"fieldType": "VARCHAR(100)",
"notNull": false,
"primaryKey": false,
"defalutValue": null
},
{
"id": 4,
"autoIncrement": false,
"comment": "用户注册时间",
"fieldName": "register_time",
"fieldType": "DATETIME",
"notNull": true,
"primaryKey": false,
"defalutValue": "CURRENT_TIMESTAMP"
}
],
"dbName": "my_database",
"mockNum": 100
}
}
假如我们让AI输出的是这样的一个json片段,那么我们可以通过这个json片段来适配其他输出语言,想生成Java的orm语句,ts的interface类型,原生sql的建表语句等等都可以方便通过一个template转换实现
CREATE TABLE users (
user_id INT NOT NULL AUTO_INCREMENT COMMENT '用户唯一标识',
user_name VARCHAR(50) NOT NULL DEFAULT 'unknown' COMMENT '用户姓名',
email VARCHAR(100) DEFAULT NULL COMMENT '用户邮箱',
register_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '用户注册时间',
PRIMARY KEY (user_id)
) COMMENT='用户表';
怎么限定AI输出指定格式?
使用特定的prompt + openai中的json-schema来限定输出格式
(之前这种方式调用的输出并不稳定,直到后面大模型出了function-call的调用方式,才能够稳定输出指定格式的内容)
另外这里面还可以想象更多事情,比如AI生成PPT,AI生成流程图,AI生成数据图表这些的生成原理;因为调用大模型一般只能输出文本,没办法得到这种复杂的内容,那么我可以通过预设好的模版配置,将AI生成的文本填入到各个配置指定的地方,从而通过渲染引擎来制作不同的下游输出。
sql2text
这一部分就比较简单,只是拿AI输出的内容做一个前端下载导出按钮的展示。
流程图如下:
其他功能
网页在线执行SQL
这一部分做的比较简陋,很多安全漏洞都没考虑,主打能用就行。
SQL在线练习功能,主要使用的技术方案为文件型db,以此来隔离不同用户的操作。主要使用SQLite 数据库实现了网页上的SQL在线运行功能,基本原理是在用户创建时,于服务器内部指定文件夹为该用户创建一个指定的.db文件,例如${id}.db,或者可以使用一些uuid和密钥的加密来加密一下文件名;在用户登录执行SQL时,后端可以直接对该数据库进行操作。