LangChain入门学习笔记(六)—— Model I/O之Output Parsers

当大模型产生输出返回后,它的内容更像是一段平铺的文字没有结构。在传给下游节点处理时可能并不能符合输入要求,LangChain提供了一套机制使得模型返回的内容可以按照开发者定义的那样结构化。

在官网文档中可以看到LangChain提供了丰富的输出解析器,涵盖了常用的一些格式。比如CSV、JSON、XML和YAML,也有一些跟模型提供商相关的特定解析工具,比如OpenAI Functions和OpenAI Tools。具体内容可以快速查看这里的表中内容。

快速开始

使用输出解析器的方法很简单,只需要两步:

  • 给出格式指令:给出语言模型输出应如何格式化的说明字符串。
  • 进行解析:对接受的字符串进行解析,成为符合某种结构的输出。

以JSON解析器(其他解析器使用方法类似,可以参看官方文档进行)为例,示例代码如下:

from langchain.output_parsers import PydanticOutputParser
from langchain_core.output_parsers import CommaSeparatedListOutputParser, JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from langchain_community.llms import Ollamamodel = Ollama(model="llama3", temperature=0.0)# 定义输出格式的字段属性。
class Joke(BaseModel):setup: str = Field(description="question to set up a joke")punchline: str = Field(description="answer to resolve the joke")# 添加自定义的格式检查。@validator("setup")def validate_question_mark(cls, field):if field[-1] != "?":raise ValueError("Badly formed question!")return field# 定义需要的输出解析器。
parser = JsonOutputParser(pydantic_object=Joke)# 通过format_instructions输入格式化的指令。
prompt = PromptTemplate(template="Answer the user query.\n{format_instructions}\n{query}\n",input_variables=["query"],partial_variables={"format_instructions": parser.get_format_instructions()},
)# LCEL组装带有输出解析器的chain,当chain被调用invoke后,parser最终按照格式解析后输出结果。
prompt_and_model = prompt | model | parser
output = prompt_and_model.invoke({"query": "Tell me a joke about bear."})
print(output)

首先,Joke类定义了输出内容的格式,其中指定了"setup"和"punchline"字段,以及提问时的格式校验。

其次,实例化JSON格式的输出解析器(JsonOutputParser)对象,指定格式为前面定义的Joke。

然后,在定义prompt时候传入format_instructions,指示后续的格式化形式。

最后,定义的chain中使用该parser。

我们可以看到输出为:

自定义输出解析器

如果觉得LangChain 提供的解析器武德不够充沛,可以自己动手打造自己专属的“武器”。LangChain提供了两种方法:

  • 使用RunnableLambda或者RunnableGenerator,这种方法简洁明了,推荐使用。
  • 从解析器基类继承编写新的类,相对比较复杂。

RunnableLambda/RunnableGenerator自定义解析

使用这个方法,我们定义自己的处理方法,接收某个输入,然后将其做对应转换后返回。以RunnableLambda为例如下:

from langchain_community.chat_models import ChatOllama
from langchain_core.messages import AIMessage
# from langchain_core.runnables import RunnableLambda# 定义自己的解析方法
def parse(ai_message: AIMessage) -> str:# 传入AIMessage类型的参数,这是Chat Model的输出return ai_message.content.swapcase()# 定义一个Chat Model
model = ChatOllama(model="llama3")# LCEL定义一个chain
chain = model | parseprint(chain.invoke("hello"))# output = model.invoke("hello")
#
# parse = RunnableLambda(parse)
# print(parse.invoke(output))

定义了自己的解析处理方法parse,注意它接受AIMessage类型的输入,这是Chat Model的输出类型,在model定义时我们使用了ChatOllama类型。它的输出给到parse解析得到最终输出,使用LCEL即是:

chain = model | parse

这里的LCEL将parse自动封装为RunnableLambda,可以理解这个操作如下面内容(注释部分):

output = model.invoke("hello")parse = RunnableLambda(parse)
print(parse.invoke(output))

最终的输出:

将语言模型的输出结果进行了大小写调换。

继承解析基类

可以通过继承一个简单的定制化解析器类BaseOutputParser来自定义自己的解析器类。只需要重写parse方法,加入自己的解析逻辑即可。_type方法返回str类型信息,主要用于日志相关功能。使用自定义的解析器类对象,解析大模型的输出。如下代码所示:

from langchain_community.llms.ollama import Ollama
from langchain_core.output_parsers import BaseOutputParser# 继承BaseOutputParser,定义parse和_type
class MyCustomOutputParser(BaseOutputParser[str]):# 自定义解析方法def parse(self, text: str) -> str:return text.swapcase()# 本自定义解析器类的type属性,用于Log。 可选。@propertydef _type(self) -> str:return "my_custom_parser"# 定义一个LLM,返回str
model = Ollama(model="llama3")# 初始化自定义的解析器对象
parser = MyCustomOutputParser()# 调用自定义解析器进行解析
print(parser.invoke(model.invoke("hello")))

该自定义解析子类的方法,得到跟前面的RunnableLambda方法一样的结果。

也可以通过继承BaseGenerationOutputParser类来自定义自己的解析类,这样能够更好和更多地控制解析输出结果,比如对模型输出里的metadata内容进行解析。使用方法上和继承BaseOutputParser的方法大致相当,只是重写的方法是parse_result。有兴趣可以参考这里,不再赘述。

通过Model I/O的介绍,大家基本上可以写个简单的LLM应用了。通过prompt输入用户的提示语,经过LLMs/ChatModel处理后,输出结果通过Output Parser解析后最终返回用户一个期望格式的内容。

当然,为了LLM应用更好的结果,我们可能还需要提供更多的内容给到底层的大模型来处理,这就是“Retrieval”相关的内容了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/860005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树-左叶子之和(easy)

目录 一、问题描述 二、解题思路 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 此题属于树遍历的简单题,用递归深度遍历的方式,当遇到左叶子结点(在递归函数中加上一个判断当前结点是左结点还是右结点的标记位),此时加上当前结点…

数字图像处理实验报告小论文(Matlab语言)

1.课题分析 在当今信息化社会,图像处理技术已成为众多领域不可或缺的一部分,从医学影像分析到安防监控,再到日常生活中的图片美化,图像处理技术都发挥着至关重要的作用。本次课题主要聚焦于图像灰度处理、图像小波变换和图像分割这…

Python基础系列教程:从零开始学习Python

Python有很多功能强大的机器学习和大数据分析包,适合对大数据和人工智能感兴趣的同学学习。要想了解一门语言,首先需要了解它的语法。本文将介绍Python的一些基础语法,包括数据类型、变量类型、条件控制、循环结构等内容。废话少说&#xff0…

第二十四节:带你梳理Vue2 : Vue具名插槽/作用域插槽/v-slot指令

1. 具名插槽 1.1 没有使用具名插槽的问题 有的时候我们在使用子组件时,在子组件模板上不同的位置插入不同的内容, 只有一个插槽显然没法满足我们的需求,看示例: 需求如下: 子组件是一篇文章的结构父组件在调用子组件是给文章插入标题,正文,时间信息 示例代码如下: <di…

【强化学习的数学原理】课程笔记--1(基本概念,贝尔曼公式)

目录 基本概念State, Action, State transitionPolicy, Reward, Trajectory, Discount ReturnEpisodeMarkov decision process 贝尔曼公式推导确定形式的贝尔曼公式推导一般形式的贝尔曼公式State ValueAction Value 一些例子贝尔曼公式的 Matric-vector form贝尔曼公式的解析解…

Elasticsearch 索引与文档操作实践指南

上节我们部署了elasticsearch8.4.1和kibana8.4.1以及ik分词器&#xff0c;本节我们来学习下elasticsearch的相关索引&#xff0c;文档操作。 首先我们kinana的主界面找到开发者工具在里面我们来编写相关操作。 标题查看集群情况 GET /_cluster/health详细解释&#xff1a; …

云计算【第一阶段(18)】磁盘管理与文件系统 分区格式挂载(一)

目录 一、磁盘基础 二、磁盘结构 2.1、机械硬盘 2.2、固态硬盘 2.3、扩展移动硬盘 2.4、机械磁盘的一些计算&#xff08;了解&#xff09; 2.5、磁盘接口类型 二、Linux 中使用的文件系统类型 2.1、磁盘分区的表示 2.1.1、主引导记录(MBR) 2.1.2、Linux中将硬盘、分…

【十二】图解 Spring 核心数据结构:BeanDefinition

图解 Spring 核心数据结构&#xff1a;BeanDefinition 简介 使用spring框架的技术人员都知道spring两个大核心技术IOC和AOP&#xff0c;随着投入更多的时间去学习spring生态&#xff0c;越发觉得spring的发展不可思议&#xff0c;一直都是引领着Java EE的技术变革&#xff0c;这…

麒麟信安系统关闭core文件操作

在使用麒麟信安系统时&#xff0c;如果应用程序运行过程中崩溃了&#xff0c;此时并不会导致内核崩溃&#xff0c;只会在tmp目录下产生崩溃数据&#xff0c;如下图 不过tmp目录下的分区容量有限&#xff0c;当崩溃的应用core文件过大时将会占用tmp空间&#xff0c;导致tmpfs分区…

Msql----表的约束

提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、表的约束 表的约束&#xff1a;表中一定要有约束&#xff0c;通过约束让插入表中的数据是符合预期的。它的本质是通过技术手段&#xff0c;让程序员插入正确的数据&#xff0c;约束的最终目标是保证…

NAPI篇【4】——NAPI应用点亮一个LED

OpenHarmony的NAPI功能为开发者提供了JS与C/C不同语言模块之间的相互访问&#xff0c;交互的能力&#xff0c;使得开发者使用C或者C语言实现应用的关键功能。如操作开发板中某个GPIO节点的状态&#xff08;OpenHarmony并没有提供直接操作GPIO口状态的API&#xff09;&#xff0…

【Flink metric(3)】chunjun是如何实现脏数据管理的

文章目录 一. 基础逻辑二. DirtyManager1. 初始化2. 收集脏数据并check3. 关闭资源 三. DirtyDataCollector1. 初始化2. 收集脏数据并check3. run&#xff1a;消费脏数据4. 释放资源 四. LogDirtyDataCollector 一. 基础逻辑 脏数据管理模块的基本逻辑是&#xff1a; 当数据消…

猫咪也怕油腻?选对猫粮是关键!福派斯鲜肉猫粮守护猫咪健康

亲爱的猫友们&#xff0c;我们都知道&#xff0c;猫咪的饮食健康是每一个铲屎官都非常关心的问题。最近&#xff0c;有些猫友向我反映&#xff0c;他们给猫主子喂食的猫粮油脂比较大&#xff0c;不禁让人担心这对猫咪是否真的好。 1️⃣ 首先&#xff0c;让我们来聊聊油脂在猫粮…

Spring Boot + Vue 全栈开发,都需要哪些前端知识?

Node.js默认安装的npm包和工具的位置&#xff1a;Node.js目录\node_modules 在这个目录下你可以看见 npm目录&#xff0c;npm本身就是被NPM包管理器管理的一个工具&#xff0c;说明 Node.js已经集成了npm工具 #在命令提示符输入 npm -v 可查看当前npm版本 npm -v 二、使用n…

代理IP超时是什么原因?

很多用户在使用代理IP进行网络访问时&#xff0c;可能会遇到代理IP超时的情况&#xff0c;也就是代理IP的延迟过高。代理IP延迟过高会影响用户的网络体验和数据获取效率。因此&#xff0c;了解代理IP延迟过高的原因很重要。以下是导致代理IP延迟过高的一些常见原因&#xff1a;…

FL Studio 21.2.3官方中文版重磅发布,手把手教你图文安装

FL Studio 21.2.3官方中文版重磅发布纯正简体中文支持&#xff0c;更快捷的音频剪辑及素材管理器&#xff0c;多样主题随心换&#xff01; 在数字音乐制作领域&#xff0c;FL Studio一直以其强大的功能和用户友好的界面而备受赞誉。随着技术的不断进步和音乐制作需求的日益增长…

Python高压电容导电体和水文椭圆微分

&#x1f3af;要点 &#x1f3af;二维热传导二阶偏微分方程 | &#x1f3af;调和函数和几何图曲率 | &#x1f3af;解潮汐波动方程 | &#x1f3af;解静止基态旋转球体流体运动函数 | &#x1f3af;水文空间插值 | &#x1f3af;流体流动模拟求解器 | &#x1f3af;随机算法解…

泰迪智能科技与成都文理学院人工智能与大数据学院开展校企合作交流

近日&#xff0c;在推动高等教育与产业深度融合的背景下&#xff0c;成都文理学院人工智能与大数据学院携手广东泰迪智能科技股份有限公司开展“专业建设交流会”。人工智能与大数据学院院长胡念青、院长助理陈坚、骨干教师刘超超、孙沛、赵杰、文运、胡斌、邹杰出席本次交流会…

vue项目中dom拖动排序功能实现

vue项目中拖动元素改变其顺序的功能实现 实现此功能&#xff0c;我利用的是SortableJs,其官网上直接介绍其为功能强大的js拖拽库&#xff0c;只需要简单的代码即可实现dom拖拽 1.下载 npm i sortablejs 2.引入 使用时&#xff0c;我们在那个页面中使用&#xff0c;就在该vue文…

【progressBar-js】优雅的 前端进度条 构建!

progressBar-js JS 前端进度条小工具 您可以通过此工具来构建一个有效的工具条&#xff0c;接下来就是一个示例&#xff01; 使用示例 引入 progressBar-js 库 直接在这里将 css 和 js 文件引入进来就算是成功导入了哦&#xff01;&#xff01;&#xff01; <link href&…