LangChain 表达式语言核心组合:Prompt + LLM + OutputParser

https://python.langchain.com.cn/docs/expression_language/cookbook/prompt_llm_parser

LangChain 表达式语言核心组合:Prompt + LLM + OutputParser 总结

LangChain 中最基础且高频的核心组合是 Prompt(提示)→ LLM/ChatModel(模型)→ OutputParser(输出解析器),几乎所有复杂链都基于此构建。文档围绕这一组合,从"基础用法""进阶解析""输入简化"三个维度展开,以下是详细总结。

一、基础组合:Prompt + LLM(无解析器)

核心是将"提示模板"与"模型"串联,实现"接收用户输入→填充提示→调用模型→返回原始模型输出"的流程,可灵活附加模型调用参数(如停止序列、函数调用规则)。

1. 最简实现(ChatPromptTemplate + ChatModel)

使用 ChatPromptTemplate 定义带变量的提示,搭配 ChatModel(如 ChatOpenAI),直接返回模型原生的 AIMessage 输出。

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1. 定义带变量{foo}的聊天提示模板
prompt = ChatPromptTemplate.from_template("tell me a joke about {foo}")
# 2. 初始化模型
model = ChatOpenAI()
# 3. 串联链:提示 → 模型
chain = prompt | model

# 调用:传入变量{foo}的值,返回AIMessage
result = chain.invoke({"foo": "bears"})
# 输出:AIMessage(content="为什么熊不穿鞋子?\n\n因为它们有熊脚!", ...)

2. 附加模型调用参数(用 bind 方法)

通过 model.bind(**kwargs) 为模型调用附加固定参数,无需每次调用时重复传入,常见场景包括"设置停止序列""指定函数调用"。

场景1:附加停止序列(截断模型输出)
python 复制代码
# 绑定停止序列:模型输出遇到"\n"时停止
chain = prompt | model.bind(stop=["\n"])
result = chain.invoke({"foo": "bears"})
# 输出:AIMessage(content="为什么熊从不穿鞋?", ...)(仅到换行前)
场景2:附加函数调用规则

指定模型需调用的函数结构,让模型输出符合函数参数格式的结果(而非自然语言)。

python 复制代码
# 1. 定义函数结构(如"生成笑话"的函数)
functions = [
    {
        "name": "joke",
        "description": "一个笑话",
        "parameters": {
            "type": "object",
            "properties": {
                "setup": {"type": "string", "description": "笑话的开头"},
                "punchline": {"type": "string", "description": "笑话的结尾"}
            },
            "required": ["setup", "punchline"]
        }
    }
]

# 2. 绑定函数调用参数:指定调用"joke"函数
chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions)
result = chain.invoke({"foo": "bears"})
# 输出:AIMessage(content='', additional_kwargs={'function_call': {'name': 'joke', 'arguments': '{"setup": "为什么熊不穿鞋子?", "punchline": "因为它们有熊脚!"}'}})

二、进阶组合:Prompt + LLM + OutputParser

在基础组合后添加 OutputParser,将模型原生输出(如 AIMessage、函数调用格式)转换为更易处理的格式(如字符串、JSON、指定键值),降低下游任务的处理成本。

1. 普通文本解析(StrOutputParser)

AIMessagecontent 提取为纯字符串,最常用的解析器之一。

python 复制代码
from langchain_core.output_parsers import StrOutputParser

# 串联链:提示 → 模型 → 字符串解析
chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
# 输出:"为什么熊不穿鞋子?\n\n因为它们有熊脚!"(纯字符串,无AIMessage包装)

2. 函数调用结果解析(针对函数调用场景)

当模型输出为函数调用格式时,使用专门的解析器提取结构化数据(如 JSON 整体、JSON 中的指定键)。

场景1:解析为完整 JSON(JsonOutputFunctionsParser)

提取函数调用的 arguments 部分,转换为 Python 字典。

python 复制代码
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser

# 串联链:提示 → 绑定函数调用 → 解析为JSON字典
chain = (
    prompt
    | model.bind(function_call={"name": "joke"}, functions=functions)
    | JsonOutputFunctionsParser()
)
result = chain.invoke({"foo": "bears"})
# 输出:{'setup': "为什么熊不喜欢快餐?", 'punchline': "因为它们抓不到它!"}(Python字典)
场景2:解析为 JSON 中的指定键(JsonKeyOutputFunctionsParser)

仅提取 JSON 中某个指定键的值(如仅要"笑话开头"setup)。

python 复制代码
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser

# 串联链:提示 → 绑定函数调用 → 解析指定键"setup"
chain = (
    prompt
    | model.bind(function_call={"name": "joke"}, functions=functions)
    | JsonKeyOutputFunctionsParser(key_name="setup")
)
result = chain.invoke({"foo": "bears"})
# 输出:"为什么熊不穿鞋子?"(仅提取setup键的值)

三、简化输入:用 RunnablePassthrough 减少重复传参

默认情况下,链需要传入"与提示变量匹配的字典"(如 {"foo": "bears"}),通过 RunnablePassthrough 可简化为"直接传变量值"(如 ("bears")),底层自动映射为字典。

实现方式(用字典映射简化)

通过字典定义"提示变量→输入值"的映射,RunnablePassthrough() 表示"直接传递输入值作为该变量的值"。

python 复制代码
from langchain_core.runnables import RunnablePassthrough

# 简化链:输入值→自动映射为{"foo": 输入值} → 提示 → 模型 → 解析
chain = (
    {"foo": RunnablePassthrough()}  # 输入值直接映射给变量foo
    | prompt
    | model.bind(function_call={"name": "joke"}, functions=functions)
    | JsonKeyOutputFunctionsParser(key_name="setup")
)

# 调用:直接传"bears",无需传字典
result = chain.invoke("bears")
# 输出:"为什么熊不穿鞋子?"

四、核心总结(表格对比)

组合类型 结构 输出格式 适用场景
基础 Prompt+LLM Prompt → LLM AIMessage 需保留模型原生输出(如函数调用元数据)
带普通解析 Prompt → LLM → StrOutputParser 纯字符串 下游需简单文本(如直接展示、字符串处理)
带函数结果解析(完整) Prompt→LLM.bind→JsonOutputFunctionsParser Python字典 需完整函数调用参数(如执行后续函数)
带函数结果解析(指定键) Prompt→LLM.bind→JsonKeyOutputFunctionsParser 单个值(字符串/数字) 仅需函数参数中的某个字段
简化输入版 {"var": RunnablePassthrough()} → Prompt → ... 对应解析格式 希望减少传参复杂度(直接传值而非字典)

结尾交付物提议

要不要我帮你整理一份**"Prompt+LLM+解析器"全场景代码模板**?包含基础组合、函数调用、输入简化等所有核心场景的可直接运行代码,每个示例都带注释,你替换模型或提示词就能快速适配自己的需求。

相关推荐
程序员游老板41 分钟前
基于SpringBoot3_vue3_MybatisPlus_Mysql_Maven的社区养老系统/养老院管理系统
java·spring boot·mysql·毕业设计·软件工程·信息与通信·毕设
福尔摩斯张1 小时前
C++核心特性精讲:从C语言痛点出发,掌握现代C++编程精髓(超详细)
java·linux·c语言·数据结构·c++·驱动开发·算法
@淡 定1 小时前
Spring中@Autowired注解的实现原理
java·后端·spring
时空无限1 小时前
Java Buildpack Reference
java·开发语言
爱笑的眼睛112 小时前
超越剪枝与量化:下一代AI模型压缩工具的技术演进与实践
java·人工智能·python·ai
阿里云云原生2 小时前
Android App 崩溃排查指南:阿里云 RUM 如何让你快速从告警到定位根因?
android·java
历程里程碑2 小时前
C++ 9 stack_queue:数据结构的核心奥秘
java·开发语言·数据结构·c++·windows·笔记·算法
醇氧3 小时前
【Windows】从守护到终结:解析一个 Java 服务的优雅停止脚本
java·开发语言·windows
努力发光的程序员3 小时前
互联网大厂Java求职面试实录
java·jvm·线程池·多线程·hashmap·juc·arraylist
小鹿学程序3 小时前
FileZilla连接到虚拟机
java·服务器·开发语言