0 引言
引言
术语
AGI
:通用人工智能AIGC:人工智能生成LLM
:大语言模型,ChatGPT、llama、千问、文心一言、KIMI都是大语言模型。langchain:一个对AI基础功能进行抽象的开发平台。作为一款先进的语言模型应用开发框架,可以让我们从基础、重复的代码中脱离。RAG
:检索增强生成。Fine-Tunning
:微调,让LLM学习我们整理好的知识,大多是专业细分领域的私有化数据集。
1 概述
关键技术:RAG/检索增强生成
定义与意义
-
Retrieval Augmented Generation
/检索增强生成。 -
它的主要作用是生成(最终的答案),但是它先做了对现有文档的检索,而不是任由LLM(各大语言模型)来发挥。
优化/解决LLM胡说八道的问题
- 最通俗的解释:LLM都是自己的内容的时间限制,RAG则是添加一个私密的、专业的外挂知识集。
例如,ChatGPT 3.5,知识更新到2021年9月,在这之后的知识他并不了解。同时,一些非网络公开的知识(如企业自己的知识库)也是学习不到的。
为了解决这个问题,我们可以将企业的厚厚的《业务操作指南》交给LLM,让LLM去查询这本《业务操作指南》,并且认真阅读掌握业务方法。
当然,如果他碰到的业务知识比较复杂,他就需要自己去综合这本书上面的多个章节的内容,并融会贯通。
最后,用这本《业务操作指南》中的内容来回来我的问题。
简单来说:就是给LLM我们自己的知识内容,让LLM根据我们给出的知识去回答问题!
-
那为什么不自己去看?
有时候内容非常多,上百万字,自己去找十分困难。而LLM可以理解知识,并给出符合 我们要求的答案。 -
和Fine-Tunning有什么不一样?
- Fine-Tunning(微调)其实是在修改模型,给模型增加了新内容,但越是微调,专用性越强,通用性越弱。
- 微调的内容其实是一问一答,即一个明确的问题有确定的回答,避免回答的随机性。
- 即然是一问一答,直接检索就可以了,为什么还是fine-tunning?
因为
LLM
可以将相似的问题语义表述,认定为同一个问题用这一个答案来回答,这是检索不具备的。
- 如:1、我今天吃了火锅有一些窜稀
- 如:2、我今天吃了火锅有一些拉肚子
这在LLM里已经处理为相同的事情了,而如果检索就需要我们自己对输入的内容进行分析。简单说,fine-tunning帮我们将“相同的语义”但不同的“语言表达”归为相同的答案。
而RAG
相当于是给LLM
加了一个外挂,即我们的知识库,LLM
本身并没有变化,只是在回答问题时,从知识库中摘取内容进行回答。
- 怎么才能把我们的知识给LLM?
这就是
RAG
技术。具体的有如下的几个步骤:
- 文档加载 → 文档分割 → 文档嵌入 → 向量化存储 → 文档检索 → 生成回答。
过程看着比较多,有个印象即可。每一步也有自己的优化点,这需要我们动手尝试,并不断的思考优化才能取得可用于生产的效果。
RAG的组成
- 事实上,一个典型的 RAG 框架可以分为:
- 检索器(Retriever)
检索过程包括:
- 为数据(如 Documents)做切分
- 嵌入向量(Embedding)
- 并构建索引(Chunks Vectors)
- 再通过向量检索,以召回相关结果
- 生成器(Generator)
- 生成过程,则是利用基于检索结果(Context)增强的 Prompt 来激活 LLM 以生成回答(Result)。
案例:用KIMI体验文档检索与知识抽取的便捷
-
在我们正式开始
RAG
的编码之前,我们先来使用KIMI
(https://kimi.moonshot.cn/)这个工具来体验一个用LLM
进行检索的乐趣。 -
进入KIMI,登陆一个账号,就可以开始进行对话了,但今天的重点是文件解析。
例如,将一个PDF的招标书上传到KIMI
然后输入我的提示词:
你看,非常快捷的就把内容给精准的提炼了出来。你也可以快速的用手头的文档来练练手。这里要注意我们的提示词。
- 提示词:LLM的角色 + 角色要求 + 我的目标 + 期望的输出 + 输出格式
具体到上述的问题:
“
kimi你好,这是我司的合同,你作为一个分析师,请你仔细的阅读文档内容。然后帮我分析一下我的下述几个属性:行业属性、产品属性、合同规模属性。行业属性,请你回答“行业:***”
只展示一个行业属性。产品属性请你回答“产品:**”,只展示一个产品属性。合同规模属性,请你回答“规模:**”。
”
我们进行一下拆解:
- LLM的角色 : kimi你好,这是我司的合同,你作为一个分析师
- 角色要求 : 请你仔细的阅读文档内容。
- 期望的输出 : 然后帮我分析一下我的下述几个属性:行业属性、产品属性、合同规模属性。
- 输出格式 : 行业属性,请你回答“行业:”,只展示一个行业属性。产品属性请你回答“产品:”,只展示一个产品属性。合同规模属性,请你回答“规模:*”。”
然后我们继续:
KIMI一样能给出不错的回答。LLM设计之初就更像一个文科生,对于文本的处理能力很强。
当然,处理数学问题比较差,毕竟这是理科问题。
想象一下,当我们有大量的知识后,我们是希望像以前一些通过关键词检索,亦或是一篇篇的查找,还是希望这样快捷的、对话式的获得知识??
关键技术:Ollama(LLM私有部署与运行环境框架)
Ollama
是大语言模型的运行环境,LLM
并不是一个可执行文件,需要依托于一个运行环境才可以使用。
可百度搜索 Ollama 下载。
Ollama
本身就200M+
的大小,任何电脑都可以安装。
Ollama没有
GUI
,需要我们在CMD
中运行。
关键技术:LangChain(LLM编程框架)
- `LangChain·: 一个 LLM 编程框架、AI编程框架————其将基础的功能已经整合进来封装,减少我们的工作量。
但
langchain
本身并不是LLM
,需要我们安装好LLM
,或使用在线api
。
你想开发一个基于 LLM 应用,需要什么组件它都有,直接使用就行;
甚至针对常规的应用流程,它利用链(LangChain中Chain的由来)这个概念已经内置标准化方案了。
LangChain
的几大模块:
- 提示模板
- 示例选择器
- 聊天模型
- LLMs
- 输出解析器
- 文档加载器
- 文本拆分器
- 嵌入模型
- 向量存储
- 检索器
- 索引
- 工具
- 代理
- 多模态
- 回调
看起来很多,但是你会发现,langchain已经将我们需要四处寻找的工具,都整合了进来,这样会节省我们大量的时间。
案例:基于 Lang Chain 完成一个最简单的代码任务
- 为了实现这个目标,我们需要先进行如下的准备,然后才能开始进行代码的编写:
- 1、使用
ollama
,在本地配置一个LLM;- 2、配置好
PyCharm
的环境;- 3、
langchain
等依赖库的安装。
Step1 安装本地部署与运行环境: Ollama
我们选择了自己部署,而自己私有化本地部署的一个工具就是
Ollama
,它可以在本地部署好我们的LLM
,如llama
`qwen等,
Ollama`是这些LLM的运行环境。
完成安装后,输入
ollama -v
,能看到version就非常OK!
Step2 安装大语言模型/LLM : QWen2
但这只是一个空的运行环境,接下来要去安装一个LLM,这里我选择阿里的
QWEN2
。
回到官网,点击页面右上角的"model",找到QWEN2。
点击进去后,这里可以在旁边看到安装的命令。
ollama run qwen2
- 如果你的电脑性能一般,
ollama
的运行会比较慢。
Ollama
对电脑的最低要求包括至少8GB的内存以流畅运行7B模型,而14B模型则需要至少16GB内存,72B模型则需要至少64GB内存。
- 回到
CMD
中,输入上述命令。
看到开始安装。需要多长时间看自己的网速。
- 完成后,回到
CMD
,输入ollama run qwen2
,就可以运行大模型,并与其对话了。
有了这个模型后,我们可以安装一个webui
,这样就可以像chatGPT
一样在网页中对话。但我们今天的任务是使用代码进行对话,这样才能将整个过程结合到我们的业务中。
Ollama
的接口服务器占用11434
端口。所以,我们可以先在浏览器中查看此服务是否可用。
你自己也可以安装一些其它的模型来体验。
Step4 安装Python集成开发环境: PyCharm,并配置 LangChain
- PyCharm我就不多说了,相信来学习Python、AI的都会使用,这里只给出我们需要在编码前,完成的一些依赖库安装。
如果你的
pip
版本老了,先升级一下。
python.exe -m pip install --upgrade pip
然后,执行下面的命令,安装langchain
pip install langchain
pip install langchain-community
pip install beautifulsoup4
- 先放下
langchain
是什么的好奇心。现在,在我们完成Ollama
及llm
,以后Python
运行环境的准备后,我们输入这段代码:
def chat():prompt = ChatPromptTemplate.from_messages([("system", "{parser_instructions}"),("human", "列出{cityName}的{viewPointNum}个著名景点。")])model = Ollama(model="qwen2")output_parser = CommaSeparatedListOutputParser()parser_instructions = output_parser.get_format_instructions()# 查看解析器的指令内容print("----- 解析器 -----")print(parser_instructions)final_prompt = prompt.invoke({"cityName": "成都", "viewPointNum": 4, "parser_instructions": parser_instructions})response = model.invoke(final_prompt)print("----- response -----")print(response)ret = output_parser.invoke(response)print("------ret-----")print(ret);
运行后得到了结果:
运行时长依你的电脑配置而定,我的几秒,现在我们来解释一下代码。
- 感受完了,小结一下————langchain最有价值的是组件
用于处理语言模型的抽象概念,以及每个抽象概念的实现集合。
无论你是否使用LangChain框架的其他部分,组件都是模块化的,易于使用。
现成的链:用于完成特定高级任务的组件的结构化组合。现成的链使人容易上手。
对于更复杂的应用和细微的用例,组件使得定制现有链或建立新链变得容易。
这些概念性的知识在实际运用前都是难以理解的,让我们直接开始看代码吧。
- 从我们最直观的感受上来说,一个Chat的过程肯定是:
** 准备好提示词 -> 输入给LLM -> LLM => 反馈**
prompt = ChatPromptTemplate.from_messages([("system", "{parser_instructions}"),("human", "列出{cityName}的{viewPointNum}个著名景点。")])
### 这里是使用了langchain的提示词模板,system中的
### parser_instructions是对于输出的要求
### human中的cityName和viewPointNum是我们的问题中动态输入的参数。
然后下一段
model = Ollama(model="qwen2")
### 定义了我们要使用的LLM,这里我使用了“千问”output_parser = CommaSeparatedListOutputParser()
parser_instructions = output_parser.get_format_instructions()
### 这里定义了输出的解析方式 CommaSeparatedListOutputParser
### 除此之外,还有 DatetimeOutputParser、EnumOutputParser 等多种解析器
完成了提示词、大模型选择、输出定义后,但并没有运行起来。需要我们在后面的代码中,使用invoke
。
final_prompt = prompt.invoke({"cityName": "成都", "viewPointNum": 4, "parser_instructions": parser_instructions})###对prompt使用invoke,将我们的输入绑定到提示词模板,形成final_prompt response = model.invoke(final_prompt)print("----- response -----")print(response)### 对model使用invoke,将final_prompt提交给LLM,也就是qwen2,### 最后得到一个response,这是一个message,需要解析成我们需要的格式。ret = output_parser.invoke(response)print("------ret-----")print(ret);### 将response提交给output_parser,得到分隔开的一个字段串数组类型的输出。
- 怎么样!是不是十分的简单。在这段代理里使用了提示词模板、模型、输出解析器。但前面提到的最重要的链好像并没有用到。
- langchain使用了LCEL表达语言,我们可以将上述的运行部分用这样的方式来替代,一样可以得到结果。
chain = prompt | llm | output_parse
rrrr = chain.invoke({"cityName": "成都", "viewPointNum": 4, "parser_instructions": parser_instructions})
- 这就是langchain的链的表达,虽然这只是一个最简单的链,但我们已经初步的感受到,链就是一个工作流,将我们的工作串起来,避免了Invoke满天飞。
- 在langchain中,实际上已经定义了很多的chain,当我们更加的熟悉后,我们可以使用现有的链。
X 参考文献
- 【五天入门RAG】第一天:使用KIMI体验大模型的文本处理 - Weixin/AIGC中文站 2024.07.19
- 【五天入门RAG】第二天:使用langchain完成一个最简单的代码任务 - Weixin/ 2024.07.20
- 【LLM大模型】大模型之RAG,LLM性能的提升,RAG与Fine-Tune我们该如何选择? - CSDN