ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

六、LangChain——StrOutputParser和JsonOutputParser

六、LangChain——StrOutputParser和JsonOutputParser 一、StrOutputParser1. 场景需求以第一次模型的输出结果拿去第二次询问模型fromlangchain_core.promptsimportPromptTemplatefromlangchain_ollamaimportChatOllama modelChatOllama(modelgemma4:12b)promptPromptTemplate.from_template(我是{band}乐队的粉丝帮我推荐一首音乐仅告知歌曲名称无需其他内容)chainprompt|model reschain.stream({band:Beyond})forchunkinres:print(chunk,end,flushTrue)现在需要chain prompt | model | model参与链的构建的组件完全符合要求但运行会报错ValueError: Invalid input type class langchain_core.messages.ai.AIMessageChunk. Must be a PromptValue, str, or list of BaseMessages.首先提示词模板PromptTemplate.from_template即prompt是PromptValue类型model的输入是PromptValue | str | Sequence[MessageLikeRepresentation]类型输出是AIMessage类对象故类型不对通过LangChain内置的解析器StrOutputParser字符串输出解析器完成类型转换2. StrOutputParser字符串输出解析StrOutputParser是LangChain内置的简单字符串解析器可以将AIMessage解析为简单的字符串符合了模型invoke方法要求(可传入字符串不接收AIMessage类型)是Runnable接口的子类(可以加入链)parser StrOutputParser()chain prompt | model | parser |model组件名称输入类型输出类型PromptTemplate.from_template可占位的strPromptValuemodelPromptValue \ str \ Sequence[MessageLikeRepresentation]AIMessageStrOutputParserAIMessagestr3. 完整流程chain prompt | model | parser | modelprompt --输出– PromptValue类型 - model --输出– AIMessage类型 - parser --输出– str类型 - model --输出– AIMessage类型res为AIMessage类型通过res.content()拿到模型输出的内容fromlangchain_core.output_parsersimportStrOutputParserfromlangchain_core.promptsimportPromptTemplatefromlangchain_ollamaimportChatOllama modelChatOllama(modelgemma4:12b)promptPromptTemplate.from_template(我是{band}乐队的粉丝你最喜欢的是哪首歌仅输出一首歌曲的名称即可)parserStrOutputParser()chainprompt|model|parser|model reschain.stream({band:Beyond})forchunkinres:print(chunk.content,end,flushTrue)也可以再加一个parser拿到str类型chain prompt | model | parser | model | parserres直接输出即可fromlangchain_core.output_parsersimportStrOutputParserfromlangchain_core.promptsimportPromptTemplatefromlangchain_ollamaimportChatOllama modelChatOllama(modelgemma4:12b)promptPromptTemplate.from_template(我是{band}乐队的粉丝你最喜欢的是哪首歌仅输出一首歌曲的名称即可)parserStrOutputParser()chainprompt|model|parser|model|parser reschain.stream({band:Beyond})forchunkinres:print(chunk,end,flushTrue)二、JsonOutputParser1. 问题分析StrOutputParser中有个问题直接拿模型给的结果再次喂给模型第一次模型给的数据并没有进行处理即上一个模型的输出没有被处理就输入给了下一个模型标准的做法流程如下为了符合标准做法需要加入数据处理和提示词模板功能模型输入PromptValue | str | Sequence[MessageLikeRepresentation]输出AIMessage提示词模板输入dict字典输出PromptValue数据处理将AIMessage转为dict字典输出2. 数据处理和提示词模板数据处理将AIMessage转为dict字典输出StrOutputParserAIMessage转为strJsonOutputParserAIMessage转为Dist(JSON)fromlangchain_core.output_parsersimportStrOutputParser,JsonOutputParserfromlangchain_core.promptsimportPromptTemplatefromlangchain_ollamaimportChatOllama str_parserStrOutputParser()json_parserJsonOutputParser()modelChatOllama(modelgemma4:12b)first_promptPromptTemplate.from_template(我朋友姓{lastname}刚生了一个{gender}帮我起一个名字封装到Json格式返回要求key是namevalue是你给的名字请简要回答只需要提供一个名字即可严格遵守格式要求。)second_promptPromptTemplate.from_template(姓名{name}这个名字怎么样) chain first_prompt | model | json_parser res chain.invoke({lastname:薛,gender:女}) print(res) # {name: 薛若汐} print(type(res)) #class dict chainfirst_prompt|model|json_parser|second_prompt|model|str_parser reschain.stream({lastname:薛,gender:女})forchunkinres:print(chunk,end,flushTrue)chain first_prompt | model | json_parser | second_prompt | model | str_parser三、自定义函数加入链StrOutputParserAIMessage转为strJsonOutputParserAIMessage转为Dist(JSON)LangChain还支持编写Lambda匿名函数来实现自定义逻辑的数据转换需要基于RunnableLambda类实现RunnaLambda类是LangChain内置的将普通函数等转换为Runnable接口实例方便自定义函数加入chain语法RunnableLambda(函数对象或lambda匿名函数)通过自定义函数my_func RunnableLambda(lambda ai_msg: {name: ai_msg.content})实现自定义逻辑的数据转换输入AIMessage输出strAIMessage的name所对应的内容fromlangchain_core.output_parsersimportStrOutputParserfromlangchain_core.promptsimportPromptTemplatefromlangchain_core.runnablesimportRunnableLambdafromlangchain_ollamaimportChatOllama str_parserStrOutputParser()# 输入AIMessage 输出Dict”name“:XXXmy_funcRunnableLambda(lambdaai_msg:{name:ai_msg.content})modelChatOllama(modelgemma4:12b)first_promptPromptTemplate.from_template(我朋友姓{lastname}刚生了一个{gender}帮我起一个名字封装到Json格式返回要求key是namevalue是你给的名字请简要回答只需要提供一个名字即可严格遵守格式要求。)second_promptPromptTemplate.from_template(姓名{name}这个名字怎么样) chain first_prompt | model | (lambda ai_msg:{name:ai_msg.content}) res chain.stream({lastname: 薛, gender: 女}) for chunk in res: print(chunk, end, flushTrue) chainfirst_prompt|model|my_func|second_prompt|model|str_parser reschain.stream({lastname:燕,gender:女})forchunkinres:print(chunk,end,flushTrue)chain中的或运算符是支持Callable参数的故可以提供lambda直接传入
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进