作者:CSDN博客
随着理解的加深,后续会回来优化。
1 输出封装
LLM模型的输出通常都是字符串形式,Langchain中的输出封装OutputParser可以将其转化解析成结构化对象。简单举例如下:- from langchain_openai import ChatOpenAI
- from langchain_core.output_parsers import CommaSeparatedListOutputParser
- prompt1='说出几种常见的水果'
- prompt2="输出20以内的素数"
- llm=ChatOpenAI()
- comma_parser=CommaSeparatedListOutputParser()
- response=llm.invoke(prompt1)print("===模型原始输出===")print(response.content)print('===CommaSeparatedListOutputParser解析输出===')print(comma_parser.parse(response.content))
- response=llm.invoke(prompt2)print("===模型原始输出===")print(response.content)print('===CommaSeparatedListOutputParser解析输出===')print(comma_parser.parse(response.content))
复制代码 其输出结果如下:- ===模型原始输出===
- 苹果、香蕉、橙子、草莓、葡萄、梨、樱桃、桃子、西瓜、哈密瓜、柚子、柠檬、火龙果、李子、菠萝、榴莲等。
- ===CommaSeparatedListOutputParser解析输出===['苹果、香蕉、橙子、草莓、葡萄、梨、樱桃、桃子、西瓜、哈密瓜、柚子、柠檬、火龙果、李子、菠萝、榴莲等。']===模型原始输出===2, 3, 5, 7, 11, 13, 17, 19===CommaSeparatedListOutputParser解析输出===['2', '3', '5', '7', '11', '13', '17', '19']
复制代码 Tips:针对prompt1模型输出的结果中的没有,所以CommaSeparatedListOutputParser解析器没有正确解析出来。
本篇主要介绍langchain和langchain_core中的解析器。
1.1 langchain_core中的解析器
目前langchain_core.output_parsers中的OutputParser类主要包括以下几种(虚拟类不列出):
json类:JsonOutputParser,将结果解析成json串。list类: CommaSeparatedListOutputParser、MarkdownListOutputParser和NumberedListOutputParser,将结果解析成类似List的对象。CommaSeparatedListOutputParser其结果是对LLM模型返回的字符串使用(,)进行分割得到的List。后面两种分别采用正则表达式从LLM模型返回的字符串中提取出符合规则的部分。string类。StrOutputParser,直接输出LLM模型返回的结果。xml类。XMLOutputParser,将LLM模型返回的结果解析成xml。pydantic类。PydanticOutputParser, 第2部分介绍。openai_function和openai_tools类:这两类可以帮助提取出LLM产生的函数调用的参数。openai_function系列针对的是使用function_call字段表示函数调用的参数的情况,后者针对的使用tool_calls字段表示function call的参数的情况(GPT系列模型采用的是这种方式)。这里只介绍openai_tools类。主要包括JsonOutputKeyToolsParser、JsonOutputToolsParser和PydanticToolsParser。其用法举例如下:
- from langchain_openai import ChatOpenAI
- from langchain_core.outputs import ChatGeneration
- #注意引用方法from langchain_core.output_parsers.openai_tools import JsonOutputToolsParser
- tools=[{"type":"function","function":{"name":"sum","description":"加法器,计算一组数的和","parameters":{"type":"object","properties":{"numbers":{"type":"array","items":{"type":"number"}}}}}}]
- llm=ChatOpenAI(model_kwargs={"tools":tools})
- parser=JsonOutputToolsParser()
- response=llm.invoke("计算一组数据的和:13,49837,3489,23423")print(response)
- response=ChatGeneration(message=response)print("---解析后结果---")print(parser.parse_result([response]))
复制代码 其输出结果为:
content=‘’ additional_kwargs={‘tool_calls’: [{‘id’: ‘call_ek805JD7PATXCZ6yjNErBgpL’, ‘function’: {‘arguments’: ‘{“numbers”:[13,49837,3489,23423]}’, ‘name’: ‘sum’}, ‘type’: ‘function’}]} response_metadata={‘token_usage’: {‘completion_tokens’: 22, ‘prompt_tokens’: 68, ‘total_tokens’: 90}, ‘model_name’: ‘gpt-3.5-turbo’, ‘system_fingerprint’: ‘fp_c2295e73ad’, ‘finish_reason’: ‘tool_calls’, ‘logprobs’: None} id=‘run-ba534c13-9a3d-4e77-a056-37465fd58549-0’ tool_calls=[{‘name’: ‘sum’, ‘args’: {‘numbers’: [13, 49837, 3489, 23423]}, ‘id’: ‘call_ek805JD7PATXCZ6yjNErBgpL’}]
—解析后结果—
[{‘args’: {‘numbers’: [13, 49837, 3489, 23423]}, ‘type’: ‘sum’}]
1.2 langchain中的输出封装
目前langchain中的OutputParser类主要包括以下几种:
| 输出类型 | 类名称 | 备注 | | boolean | BooleanOutputParser | 返回True或False | | combining | CombiningOutputParser | 同时将多个输出解析成同一个格式 | | datetime | DatetimeOutputParser | 将日期转化成特定格式 | | enum | EnumOutputParser | 将LLM模型输出解析成enum | | fix | OutputFixingParser | 可以自动修复异常并重新解析 | | pandas_dataframe | PandasDataFrameOutputParser | 使用pandas.dataframe的format对LLM进行解析 | | regex | RegexParser | 使用正则表达式对LLM模型返回进行解析 | | regex_dict | RegexDictParser | 功能同上 | | retry | RetryOutputParser、RetryWithErrorOutputParser | 可以自动修复异常并重新解析 | | structured | StructuredOutputParser | 将LLM模型输出进行结构化解析 | | yaml | YamlOutputParser | 提取LLM模型输出中的YAML部分 | 虽然OutputParser可以对LLM的输出结果进行解析,但这种使用方式用户体验并不好,正如第一个案例中针对prompt1的输出结果,因为无法确定LLM模型输出的结果中是否使用,,所以解析结果无法掌控。可以使用OutputParser类的get_format_instructions()方法来调整LLM模型输出。举例如下:- from langchain.output_parsers import DatetimeOutputParser
- from langchain_openai import ChatOpenAI
- from langchain_core.prompts import PromptTemplate
- parser=DatetimeOutputParser()
- format_instruction=parser.get_format_instructions()
- llm=ChatOpenAI()
- prompt=PromptTemplate.from_template(template="计算机时间的起始时间是什么时候?{format_instruction}")
- prompt=prompt.format(format_instruction=format_instruction)
- response=llm.invoke(prompt)print(response.content)
复制代码 其输出结果如下:
0001-01-01T00:00:00.000000Z
2 PydanticOutputParser
PydanticOutputParser类可以利用Pydantic库自定义解析模型。
2.1 Pydantic基本用法
Pydantic 是Python 中一个流行的数据验证和设置库,允许自定义数据模型,并在运行时验证输入数据是否符合模型规范,确保应用程序在处理数据时的健壮性和可靠性。其用法举例如下(目前Langchain中可能只支持pydantic的v1版本,为保持一致,这里也仅使用v1版本):- from pydantic import BaseModel,Field,validator
- import re
- classFunc_Json(BaseModel):
- name:str=Field(description="函数名称,只能由字母组成并且长度不超过10")
- description:str=Field(description="函数描述")@validator("name")defvalid_name(cls,field):if re.match(r'^[a-zA-Z]+$',field)andlen(field)<10:return field
- else:raise ValueError("函数名称不符合要求")print(Func_Json(name="sum",description="求一组数据的和"))print(Func_Json(name='sum2',description="求一组数据的和"))
复制代码 其代码运行结果如下:
2.2 PydanticOutputParser基本用法
- from pydantic import BaseModel,Field,validator
- from langchain_core.output_parsers import PydanticOutputParser
- from langchain_openai import ChatOpenAI
- from typing import List
- from langchain_core.prompts import PromptTemplate
- classNew_List(BaseModel):
- item:List[str]
- llm=ChatOpenAI()
- parser=PydanticOutputParser(pydantic_object=New_List)
- prompt=PromptTemplate.from_template("请列出10种常见的水果。{format_instruction}")
- prompt=prompt.format(format_instruction=parser.get_format_instructions())
- response=llm.invoke(prompt)print(response.content)
- prompt="请列出10种常见的汽车品牌"
- new_parser=OutputFixingParser.from_llm(parser=parser,llm=ChatOpenAI())
- response=llm.invoke(prompt)print(response.content)print(new_parser.parse(response.content))
复制代码 其结果如下:
{
“item”: [“apple”, “banana”, “orange”, “strawberry”, “grape”, “watermelon”, “kiwi”, “pineapple”, “mango”, “pear”]
}
ToyotaFordChevroletHondaVolkswagenBMWMercedes-BenzAudiNissan
- Hyundai
item=[‘Toyota’, ‘Ford’, ‘Chevrolet’, ‘Honda’, ‘Volkswagen’, ‘BMW’, ‘Mercedes-Benz’, ‘Audi’, ‘Nissan’, ‘Hyundai’]
参考文献
https://blog.csdn.net/codename_cys/article/details/107675748
原文地址:https://blog.csdn.net/yeshang_lady/article/details/137936178 |