Created
Aug 14, 2024 01:39 AM
Favorite
Favorite
Priority
备注
推荐
类型
模型测试
简介: 【AI大模型应用开发】【LangChain系列】1. 全面学习LangChain输入输出I/O模块:理论介绍+实战示例+细节注释
上文我们介绍过LangChain的基本框架和其中包含的主要模块。从今天开始,我们开始学习各个模块,深入了解,同时进行相应实战练习。
本文学习 LangChain 中的 模型 I/O 封装模块。
0. 模块介绍
任何AI大模型应用程序的核心元素都是大模型。LangChain提供了与各种大模型接口进行交互的封装。
这张图生动地展现了LangChain对于I/O(输入输出)的封装。
- 首先是 Format 部分,这部分的作用是组装用户输入和Prompt模板,作为大模型的输入。
- 然后是 Predict 部分,这部分就是调用大模型接口获得结果
- 最后是 Parse 部分,这部分的作用是对大模型的结果进行解析,将大模型的输出转换到要求的格式(如json)上,或者对输出进行校验等等
1. Format部分:Prompt模板封装
1.1 PromptTemplate:创建一个字符串类型的Prompt
PromptTemplate 可以在模板中自定义变量
1.2 ChatPromptTemplate:创建一个Prompt的Message数组
运行后输出结果如下,可以看到Prompt中带入了 System、Human这样的角色名,区分Prompt的来源。
1.3 FewShotPromptTemplate:给例子的Prompt模板
在之前文章Prompt优化中,我们提到Prompt中给几个例子可以让大模型更好地生成正确的结果。这个模板就是给例子的。
以上代码为FewShotPromptTemplate的使用示例,总结为以下关键点:
- 例子(few-shot)用数组表示:examples
- 用PromptTemplate表示examples中的格式:Input后跟着output,注意:input_variables中的变量与examples中每个元素的key保持一致。
- 通过 FewShotPromptTemplate 将以上元素组合起来
- 同时传入 suffix 参数,该参数是接收用户的输入,组装提问的prompt模板。
- 然后input_variables表示用户输入的参数变量名
运行结果如下:红框内是通过FewShotPromptTemplate 将examples、example_prompt、suffix组合起来后最终的给大模型的Prompt。
1.4 从文件加载Prompt模板
我们还可以将Prompt模板单独存放在一个文件中,在程序运行时通过加载文件来导入Prompt模板。
这种方式很好地实现了 Prompt 和程序的分离,使得两者可以分别单独修改。甚至你可以将Prompt单独放在一个线上服务或数据库中,单独维护。
下面来看怎么实现。
1.4.1 Prompt模板文件格式
Prompt模板文件支持两种格式:yaml格式和json格式
- yaml格式:
- json格式
1.4.2 加载文件
使用 LangChain的load_prompt进行加载。
1.4.3 更进一步:文件套文件
LangChain也允许你在Prompt文件中再套Prompt文件:将文件中的template字段单独放一个txt文件使用。拆分后文件如下:
- prompt_template_test.txt
- langchain_prompt_file_test.json
注意:json里面的template字段换成了template_path字段
1.5 其它Prompt模板
还有一些其它的Prompt模板,就不详细介绍了,都差不多。
- FewShotChatMessagePromptTemplate
- ChatMessagePromptTemplate:可以自定义Prompt的角色名,如之前的“System”、“AI”、“Human”都是角色。
- …
该部分参考:https://python.langchain.com/docs/modules/model_io/prompts/总结:把Prompt模板看作带有参数的函数
2. Predict部分:大模型接口封装
这部分主要看下LangChain对大模型的两种封装:llm 和 chat_model。
可以看到 llm 和 chat_model 的区别,一个输出字符串,一个输出message。
3. Parse部分:输出结果校验的封装
LangChain封装了一些对于大模型输出结果的约定和校验能力。下面以
PydanticOutputParser
为例演示一下Parse部分的使用方法和作用。3.1 使用步骤
(1)首先定义一个你期望返回的数据结构
下面代码中,我们定义了一个Joke数据结构,它里面包含的信息有:
- 两个变量名:setup 和 punchline,大模型的返回需要以这两个名称作为key来组织答案
- 一个自定义的校验函数:
question_ends_with_question_mark
,校验信息是否符合你的要求,如果不符合,则报错。
@validator("setup") 表示校验结果中的setup字段。也就是说,首先大模型回复的答案中,首先必须是个json结构,才能解析出setup的内容。其次,json数据结构中必须有setup的字段。最后,setup的内容必须符合函数中定义的规则。这样才算通过,否则报错。
(2)生成一个解析器的实例
(3)生成 Prompt 模板
在这个Prompt模板中:
- 通过
template
指定Prompt的框架
input_variables
指定用户输入的信息放到这个变量名中
partial_variables
是提前填充部分Prompt变量,这里通过parser.get_format_instructions()
获取PydanticOutputParser
中封住好的Prompt部分。
看下
parser.get_format_instructions()
的内容:The output should be formatted as a JSON instance that conforms to the JSON schema below.As an example, for the schema {“properties”: {“foo”: {“title”: “Foo”,“description”: “a list of strings”, “type”: “array”, “items”: {“type”:“string”}}}, “required”: [“foo”]} the object {“foo”: [“bar”, “baz”]}is a well-formatted instance of the schema. The object {“properties”:{“foo”: [“bar”, “baz”]}} is not well-formatted.Here is the output schema: ```{“properties”: {“setup”: {“title”:“Setup”, “description”: “question to set up a joke”, “type”:“string”}, “punchline”: {“title”: “Punchline”, “description”: “answerto resolve the joke”, “type”: “string”}}, “required”: [“setup”,“punchline”]} ```
可以看到,LangChain内部将咱们上面定义的Joke数据结构填到了里面,并要求大模型输出json结构。
(4)加上用户的提问,调用大模型获取回复
完整Prompt如下:
运行结果如下:
(5)校验输出结果是否符合要求
上面的结果明显符合要求,最终输出如下:
3.2 不符合要求的情况
为了看一下不符合要求时会发生什么,我在大模型返回后手动改了下结果,让它不符合要求(要求是问句结尾必须是问号,下面我将问号删掉了)。
运行结果:报错了
如果大模型返回的结果不是json结构,也会报错:
3.3 不符合要求怎么办?Auto-Fixing Parser帮你自动修复错误
基本用法如下:
为了展示它的效果,我还是手动将结果改错了。
输出结果如下:可以看到重新解析后结果正确了。
重新解析为什么就正确了?其实是OutputFixingParser内部又重新调用了一遍大模型。
3.4 完整代码
关于更多 OutputParser 的说明,可以看官方文档:https://python.langchain.com/docs/modules/model_io/output_parsers/
4. 总结
本文我们全面学习了LangChain的模型 I/O 封装模块。
- LangChain 提供了各种 PromptTemplate 类,可以自定义带变量的模板
- LangChain 统一封装了各种模型的调用接口,包括llm型和chat_model型两种,区别见上文。
- LangChain 提供了一系列输出解析器,用于将大模型的输出解析成结构化对象;额外带有自动修复功能。
如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~
大家好,我是同学小张欢迎 点赞 + 关注 👏,促使我持续学习,持续干货输出。+v: jasper_8017 一起交流💬,一起进步💪。微信公众号也可搜【同学小张】 🙏踩坑不易,感谢关注和围观
本站文章一览: