【AI】三.LCEL表达式和输出解析器多案例实战 小滴课堂讲师 2025年09月17日 ai大模型, aigc 预计阅读 15 分钟 #### LangChain链和LLMChain链案例实战 ##### 什么是Chain链 * 是构建语言模型应用的核心组件,用于将多个模块(如模型调用、提示模板、记忆系统等)组合成可复用的工作流程。 * 本质:将多个处理单元(模型/工具/逻辑)按特定顺序连接起来,形成完整的任务处理流程 * 想象Java中的责任链模式或工作流引擎中的步骤串联。 ```java // 传统Java责任链模式(对比理解) public interface Handler { void handle(Request request); } class ValidationHandler implements Handler { /* 验证逻辑 */ } class LLMProcessingHandler implements Handler { /* 大模型处理 */ } class DatabaseSaveHandler implements Handler { /* 存储结果 */ } // 构建处理链 List chain = Arrays.asList( new ValidationHandler(), new LLMProcessingHandler(), new DatabaseSaveHandler() ); // 执行链式处理 for (Handler handler : chain) { handler.handle(request); } ``` ##### 常见类说明 * LLMChain类详解(最基础的链,少用仍保留,推荐用 LCEL) * 是最基础的Chain,负责结合**提示模板**和**LLM模型**,生成并执行模型的调用流程 * 专门用于与大语言模型(如ChatGPT)交互的标准化处理单元 * 核心功能: * 提示模板:将用户输入动态填充到预设的模板中,生成模型的输入文本。 * 模型调用:将模板生成的文本传递给LLM,返回生成结果。 * 输出解析(可选):对模型输出进行后处理(如JSON解析) * 核心参数 | 参数 | 类比Java场景 | 示例值 | | :-----------: | :-------------------------------: | :-------------------------------------: | | llm | 依赖注入的模型对象 | new OpenAI() | | prompt | 预定义的提示词模板 | PromptTemplate("回答用户问题: {input}") | | output_parser | 结果解析器(类似Jackson处理JSON) | new CommaSeparatedListOutputParser() | ##### 代码示例 ```python from langchain_openai import ChatOpenAI from langchain.chains import LLMChain from langchain_core.prompts import PromptTemplate # 创建提示词模板(类似Java的String.format()) prompt_template = PromptTemplate( input_variables=["product"], template="你是文案高手,列举三个{product}的卖点:" ) # #模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) # 创建LLMChain(类似构建一个Service类) # llm_chain = LLMChain( # llm=model, # prompt=prompt_template # ) # LLMChain 类在 LangChain 0.1.17 中已被弃用,建议使用 RunnableSequence(如 prompt | llm) llm_chain = prompt_template | model # 执行调用(类似service.execute(input)),run方法被淘汰了,统一invoke方法调用 result = llm_chain.invoke("智能手机") print(result) # 输出:"1. 高清OLED屏幕 2. 5000mAh大电池 3. 旗舰级处理器" ``` * 其他常见的Chain,比如 `SequentialChain、TransformChain、RouterChain、RetrievalChain` 部分已经淘汰 #### 新版LCEL表达式讲解和案例实战 ##### 什么是LCEL(LangChain Expression Language) * 是 LangChain 0.3+ 推出的**声明式编程语言**,用于简化 AI 流程编排,核心思想是**用管道符 `|` 连接组件**。 * 优势: * 代码简洁,支持流式响应(如 ChatGPT 逐字输出) * 标准化接口, 所有组件输入为 `Dict`,输出为 `Dict`,支持无缝连接 * 所有组件实现 `Runnable` 协议, 兼容同步/异步调用 * 内置调试、重试、并行等高级功能 * 版本对比 | 特性 | 0.2 版本 | 0.3+ 版本 | | :----------: | :-------------------: | :-------------------------------: | | **构建方式** | 类继承 (`Chain` 子类) | LCEL 表达式语法 (`Runnable` 接口) | | **组合方法** | `SequentialChain` 类 | 管道操作符 ` | | **执行模式** | 同步为主 | 原生支持 Async / Stream | | **核心模块** | `langchain.chains` | `langchain_core.runnables` | ##### 语法与结构 - **LLMChain(旧版)** - 基于类的封装,通过组合`PromptTemplate`、`LLM`和`OutputParser`等组件构建链式调用。 - 需要显式定义每个组件并手动传递输入 - **适用场景** - 简单问答、单步生成任务(如生成公司名称、翻译句子)。 - 快速原型开发,无需复杂配置 ```python chain = LLMChain(llm=model, prompt=prompt) result = chain.invoke({"text": "Hello"}) ``` - **LCEL** - 采用声明式管道语法(`|`操作符),允许更直观的链式组合 - 通过管道连接组件,代码更简洁且逻辑清晰 - **适用场景** - 复杂工作流(如多模型协作、动态路由、实时流式交互)。 - 生产级应用开发,需高并发、稳定性和可观察性(如集成LangSmith跟踪) ```python chain = prompt | model | output_parser result = chain.invoke({"text": "Hello"}) ``` ##### LCEL 核心语法 * 作用:将左侧组件的输出传递给右侧组件作为输入,构建了类似Unix管道运算符的设计 * 语法规则:`chain = component_a | component_b | component_c ` * 案例实战:构建一个简单的问答链 ```python from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser # 定义组件 prompt = ChatPromptTemplate.from_template("回答这个问题:{question}") # #模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) parser = StrOutputParser() # 构建 LCEL 链 chain = prompt | model | parser # 调用 result = chain.invoke({"question": "如何学习AI大模型?"}) print(result) ``` ```python # 旧版本的写法, 创建LLMChain(类似构建一个Service类) chain = LLMChain( llm=model, prompt=prompt_template ) # 执行调用(类似service.execute(input)),run方法被淘汰了,统一invoke方法调用 result = chain.invoke("智能手机") print(result) # 输出:"1. 高清OLED屏幕 2. 5000mAh大电池 3. 旗舰级处理器" ``` #### LLM大模型Stream流式输出实战 ##### Stream流式响应实战 * 前面我们的大模型输出都是一次性响应,这个容易造成体验不好 * 支持流式响应(Streaming Response),能够显著提升应用的响应速度和用户体验。 * 流式响应的核心在于逐步生成和返回数据,而不是等待整个结果生成后再一次性返回 ##### 案例实战:故事小助手 ```python from langchain_openai import ChatOpenAI # #模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) for chunk in model.stream("讲一个翠花的故事。"): print(chunk.content, end="", flush=True) ``` ##### 案例实战:科普助手(采用LCEL表达式进行) ```python from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser # 1. 定义提示词模版 prompt = ChatPromptTemplate.from_template("用100字解释以下知识点:{concept}") # 2. 创建模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7, streaming=True # 启用流式 ) # 使用 LCEL 语法 streaming_chain = prompt | model | StrOutputParser() # 2. 执行流式调用 for chunk in streaming_chain.stream({"concept": "小滴课堂"}): print(chunk, end="", flush=True) # 逐词输出 ``` ##### 流式响应的优势与限制 * 优势 * 提升用户体验:用户可以看到实时的生成过程,避免长时间等待。 * 节省内存:逐步生成和返回数据,避免一次性加载大量数据。 * 灵活性高:支持同步、异步和事件驱动的流式响应,适用于多种场景29。 * 限制 * 等待时间较长:涉及大语言模型的节点可能需要较长时间才能返回完整结果。 * 复杂性较高:事件驱动的流式响应需要精细的控制和管理 #### 输出解析器OutputParse实战和原理讲解 ##### 为什么需要输出解析OutputParse * 大模型原始输出通常是**非结构化文本** * 实际需要: * 将大模型的自由文本转为结构化数据(类似Java的JSON/XML解析) * 自动处理模型输出的格式错误  ##### 解析器工作原理 * `输入文本 → LLM 生成 → 解析器 → 结构化数据` * 工作原理: - 在提示模板中预留一个占位符变量,由输出解析器负责填充。 - 当 LLM 按照输出要求返回文本答案后,该答案会被传递给输出解析器,解析为预期的数据结构。 - **通俗来说:就是在prompt结尾追加,告诉大模型应该返回怎样的格式** * 解析器核心接口 * `parse()`:解析原始文本为结构化数据。 * `parse_with_prompt()`:结合上下文提示词解析(处理多轮对话场景)。 * `get_format_instructions()`:生成提示词模板,指导 LLM 输出格式。 * 文档地址:https://python.langchain.com/docs/concepts/output_parsers/ ##### 输出解析器基础结构三要素 ```python from langchain.output_parsers import XxxParser # 要素1:创建解析器(类似Java的Gson实例) parser = XxxParser() # 要素2:构建提示词模板(注意{format_instructions}占位符) prompt = PromptTemplate( template="请生成用户信息,按格式:{format_instructions}\n输入:{input}", input_variables=["input"], partial_variables={"format_instructions": parser.get_format_instructions()} ) # 要素3:组合成链(类似Java的责任链模式) chain = prompt | model | parser ``` * 测试查看 多个解析器prompt提示词 ```python from langchain_core.output_parsers import JsonOutputParser,CommaSeparatedListOutputParser from langchain_core.prompts import ChatPromptTemplate #parser = JsonOutputParser() parser = CommaSeparatedListOutputParser() # 获取格式指令 format_instructions = parser.get_format_instructions() # 定义提示词 prompt = ChatPromptTemplate.from_template(""" 分析以下商品评论,按指定格式返回结果: 评论内容:{review} 格式要求: {format_instructions} """) # 注入格式指令 final_prompt = prompt.partial(format_instructions=format_instructions) print(final_prompt.format_prompt(review="这个手机超级好用,超级流畅")) ``` ##### 案例实战 ```python from langchain_core.output_parsers import CommaSeparatedListOutputParser from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI # 1. 实例化一个 CommaSeparatedListOutputParser对象,将逗号分隔文本转为列表 output_parser = CommaSeparatedListOutputParser() format_instructions = output_parser.get_format_instructions() # 2. 创建一个 prompt template,将 output_parser.get_format_instructions()追加到的prompt里面 prompt = PromptTemplate( template="列举多个常见的 {subject}.{format_instructions}", input_variables=["subject"], partial_variables={"format_instructions": format_instructions}, ) #3. 创建模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) # 4. 构建链 chain = prompt | model | output_parser print(chain.invoke({"subject": "水果"})) ``` * !!!注意!!!! * 虽然有解析器,但是存在大模型返回内容不符合格式要求,则一样会报错 * 本质解析器还是Prompt提示词内容,如果有报错则可以让大模型重试 #### LangChain字符串和列表输出解析器实战 ##### 需求 * 课程讲常见的解析器,其他的可以自行拓展 * 掌握字符串和列表输出解析器 * 掌握解析器源码流程 ##### StrOutputParser * **功能**:将模型输出直接解析为字符串,保留原始文本输出,不做处理(默认行为) * **适用场景**:无需结构化处理,直接返回原始文本 ```python from langchain_core.output_parsers import StrOutputParser from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate # 定义链 prompt = ChatPromptTemplate.from_template("写一首关于{topic}的诗") #创建模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) # 创建解析器 parser = StrOutputParser() chain = prompt | model | parser # 调用 result = chain.invoke({"topic": "秋天"}) print(result) # 输出:秋天的落叶轻轻飘落... ``` ##### CommaSeparatedListOutputParser * **功能**:将逗号分隔的文本解析为列表。 * **适用场景**:模型生成多个选项或标签。 ```python from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import CommaSeparatedListOutputParser from langchain_openai import ChatOpenAI parser = CommaSeparatedListOutputParser() prompt = ChatPromptTemplate.from_template("列出3个与{topic}相关的关键词:") #创建模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) chain = prompt | model | parser # 调用 result = chain.invoke({"topic": "Java"}) print(result) # 输出:["机器学习", "深度学习", "神经网络"] ``` #### Json输出解析器和问答系统答案提取实战 ##### JsonOutputParser * **功能**:将模型输出解析为 JSON 对象。 * **适用场景**:需要模型返回结构化数据(如 API 响应),**多数要结合Pydantic进行使用** ```python from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import JsonOutputParser prompt = ChatPromptTemplate.from_template( "返回JSON:{{'name': '姓名', 'age': 年龄}},输入:{input}" ) #创建模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) chain = prompt | model | JsonOutputParser() result = chain.invoke({"input": "张三今年30岁,准备结婚后学AI大模型课程"}) print(result) # 输出:{"name": "张三", "age": 30} ``` ##### 案例实战:问答系统答案提取 * 目标:从模型回答中提取答案和置信度。 ```python from langchain_core.output_parsers import JsonOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI # 定义 JSON 格式要求 prompt = ChatPromptTemplate.from_template(""" 回答以下问题,返回 JSON 格式: {{ "answer": "答案文本", "confidence": 置信度(0-1) }} 问题:{question} """) #创建模型 model = ChatOpenAI( model_name = "qwen-plus", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-005c3c25f6d042848b29d75f2f020f08", temperature=0.7 ) parser = JsonOutputParser() chain = prompt | model | parser # 调用 result = chain.invoke({"question": "地球的半径是多少?"}) print(result) #{'answer': '地球的平均半径约为6,371公里。', 'confidence': 0.95} print(f"答案:{result['answer']},置信度:{result['confidence']}") #答案:地球的平均半径约为6,371公里。,置信度:0.95 ```
评论区