Administrator
发布于 2026-04-16 / 6 阅读
0

chapter 2 LangChain核心组件实操

本章节主要聚集于一些核心插件的运用,主要是用在输入和输出环节。
输入对示例进行管理:

  • PromptTemplate:通过参数化设计实现提示词的规范与复用,降低重复开发成本

  • FewShotPromptTemplate:通过动态示例选择与批量管理,适配复杂业务场景,提升提示词效率

输出把大模型生成的非结构化文本转换成更加常见方便的各种结构化或者半结构化数据:

  • OutputParser:将非结构化输出转化为结构化数据,打通大模型输出与后续业务逻辑的衔接

LLM VS ChatModel

LLM :是更加底层的文本生成模型,一般都是文本输入输出,不会有什么特别处理
ChatModel :输入输出采用消息列表,每个消息有角色(user/assistant/system)和内容,会有一些“对话协议”,跟会跟你聊天

# 导入必要的模块

from langchain_openai import ChatOpenAI  # OpenAI对话模型的统一接口
from dotenv import load_dotenv
import os

# 加载API密钥(和上一章一样,从.env文件读取)
load_dotenv()
  
API_KEY = os.getenv("API_KEY")
BASE_URL = os.getenv("BASE_URL")  # 从环境变量读取,未配置时默认为None(使用OpenAI官方地址)

if not API_KEY:

    raise ValueError("未检测到 API_KEY,请检查 .env 文件是否配置正确")

# 1. 初始化对话模型
# 不管是哪个厂商的ChatModel,初始化参数都类似(model、temperature等)
chat_model = ChatOpenAI(
    api_key=API_KEY,
    base_url=BASE_URL,
    model="gpt-5.4",  # 选择对话模型
    temperature=0.3,        # 随机性:0-1,越小越严谨,越大越有创造力
    max_tokens=200          # 最大生成 tokens 数,避免生成过长内容
)

# 2. 构造对话消息
# ChatModel需要接收的是“消息列表”,每个消息有角色(user/assistant/system)和内容
messages = [
    # system消息:给助手设定身份和行为准则,会影响后续所有回复
    {"role": "system", "content": "你是一个耐心的AI学习助手,回复简洁易懂,适合高校学生理解。"},
    # user消息:用户的问题
    {"role": "user", "content": "3句话解释什么是LangChain?"}
]

# 3. 调用模型生成结果
# 统一调用方法:invoke(),传入消息列表
result = chat_model.invoke(messages)

# 4. 输出结果
# 结果是一个ChatMessage对象,content属性是回复内容
print("ChatModel回复:")
print(result.content)
ChatModel回复:
LangChain 是一个用于构建基于大语言模型(LLM)应用的开发框架,能把模型、提示词、工具、数据库和外部 API 连接起来。  
它的核心作用是帮助开发者把“模型会聊天”升级成“模型能完成复杂任务”,比如检索知识、调用工具、执行多步流程。  
简单说,LangChain 就像大模型应用的“搭积木工具箱”,方便你快速开发智能问答、Agent、RAG 等应用。

roles之间的区别

我们输出给模型的消息中,会发现存在角色信息:systemuser 和 assistant等,这些信息可以理解成不同级别的约束。

system

system 用来放全局行为约束身份设定输出风格安全规则任务边界
设定身份

  • 你是翻译器

  • 你是法律助理

  • 你是面试官
    设定风格

  • 用中文回答

  • 回答简洁

  • 用表格总结
    设定约束

  • 不要编造信息

  • 不要输出危险内容

  • 遇到不确定时明确说明
    设定任务框架

  • 先分析需求,再给代码

  • 每次回答分三步:概念、示例、注意事

user

user 表示用户当前输入的真实请求

  • 提问题

  • 补充条件

  • 修改需求

  • 给数据、代码、文本让模型处理

assistant

assistant 表示模型之前已经说过的话

  • 保持上下文连续

  • 保持回答风格一致

  • 避免自相矛盾

测试demo

【第一轮回复】:
LangChain 是一个帮助开发者构建基于大语言模型(LLM)应用的开发框架。  
它把提示词管理、模型调用、知识检索、记忆、工具使用等能力串联起来,让开发流程更方便。  
简单来说,LangChain 就像是大模型应用的“积木工具箱”,适合用来开发聊天机器人、智能问答和自动化助手。

【第二轮回复】:
LangChain 的核心组件通常可以概括为这几类:

1. **Models(模型)**:负责调用大语言模型、聊天模型或文本嵌入模型。  
2. **Prompts(提示模板)**:用于规范输入内容,让模型按预期格式回答。  
3. **Chains(链)**:把多个步骤串起来,比如“提问 → 检索资料 → 生成回答”。  
4. **Memory(记忆)**:让系统保留上下文,适合多轮对话场景。  
5. **Tools(工具)**:让模型可以调用外部能力,比如搜索、计算器、数据库、API。  
6. **Agents(智能体)**:根据任务动态决定调用哪些工具、按什么步骤执行。  
7. **Retrievers / Vector Stores(检索器 / 向量库)**:用于从外部知识库中查找相关信息,常用于 RAG 应用。  

如果你愿意,我也可以继续用一个“聊天机器人例子”帮你把这些组件串起来理解。

【第三轮回复】:
一个很典型的简单场景是:**“基于企业文档的智能问答机器人”**。  

比如你把公司的员工手册、报销制度、请假流程等文档接入 LangChain,用户提问“出差报销上限是多少?”,系统会先用 **Retriever** 从文档中找相关内容,再把结果连同问题交给 **LLM** 生成自然语言回答。  

这里会用到的核心组件包括:**向量库/检索器**(找资料)、**Prompt**(组织提问方式)、**Model**(生成答案),如果是多轮对话还可以加上 **Memory** 来记住上下文。

PromptTemplate

提示词模板(PromptTemplate):让提示更规范、可复用,主要就是把“固定的提示文本”和“动态的参数”分离开,让提示词更规范、可复用。

关键词的替换

# 1. 定义提示词模板
# input_variables:动态参数列表(这里是user_role和subject)
# template:提示词模板字符串,用{参数名}表示动态参数
prompt_template = PromptTemplate(
    input_variables=["user_role", "subject"],
    template="请给{user_role}写一段50字左右的{subject}学习建议,语言简洁实用,分2个小要点。"
)

# 2. 格式化模板(传入具体参数,生成完整提示词)
# 给“高校学生”生成“LangChain”学习建议
formatted_prompt = prompt_template.format(
    user_role="高校学生",
    subject="LangChain"
)
print("格式化后的提示词:")
print(formatted_prompt)

# 3. 调用模型生成结果
result = chat_model.invoke([{"role": "user", "content": formatted_prompt}])
格式化后的提示词:
请给高校学生写一段50字左右的LangChain学习建议,语言简洁实用,分2个小要点。

生成的学习建议:
- 先用官方文档跑通 `Prompt`、`Chain`、`Memory` 示例,理解调用流程,再自己改一个小项目。
- 边学边练 `RAG` 与工具调用,记录报错和调试方法,重点培养排查与落地能力。

然后我们可以通过套换变量完成提示词的更改(有点像写作套板子,只是换一下主题词,但是限制和修饰不变)

user_role="程序员", subject="AI Agent"
格式化后的提示词:
请给程序员写一段50字左右的AI Agent学习建议,语言简洁实用,分2个小要点。

生成的学习建议:
- 先学会把任务拆小,给Agent清晰目标、约束和验收标准;先做能验证的小流程。
- 多记录提示词、失败案例和改法,持续复盘;先提效代码、测试、文档等高频场景。

少样本提示模板(FewShotPromptTemplate)

这个通过给示例,给模型大概的一个出发点,就像别人叫你写作文,然后扔几篇范文让你自己学,然后你看了之后,恍然大悟原来大家喜欢这样的写作风格,然后你学习这种风格写出一篇文章。

# 1. 定义示例(少样本的核心:给模型看的参考案例)
examples = [
    {
        "subject": "Python编程",
        "method": "核心目标:掌握基础语法和常用库;学习步骤:1. 学习变量、函数等基础语法 2. 实操小项目(如计算器) 3. 学习Pandas、Matplotlib库;注意事项:多动手实操,遇到错误及时调试。"
    },
    {
        "subject": "机器学习",
        "method": "核心目标:理解基础算法原理和应用场景;学习步骤:1. 复习数学基础(线性代数、概率) 2. 学习经典算法(线性回归、决策树) 3. 用Scikit-learn实操;注意事项:先理解原理,再动手实现,避免死记硬背。"
    }
]

# 2. 定义示例模板(告诉模型如何解析示例)
example_template = """
学科:{subject}
学习方法:{method}
"""
example_prompt = PromptTemplate(
    input_variables=["subject", "method"],
    template=example_template
)

# 3. 定义最终的提示词模板(包含示例和用户需求)
few_shot_prompt = FewShotPromptTemplate(
    examples=examples,                # 传入示例
    example_prompt=example_prompt,    # 示例模板
    suffix="学科:{new_subject}\n学习方法:",  # 最终给用户的提示(在示例之后)
    input_variables=["new_subject"]   # 动态参数:用户要查询的新学科
)

# 4. 格式化模板(传入新学科:LangChain)
formatted_prompt = few_shot_prompt.format(new_subject="LangChain")
print("少样本提示词:")
print(formatted_prompt)

# 5. 调用模型生成结果
result = chat_model.invoke([{"role": "user", "content": formatted_prompt}])
生成的LangChain学习方法:
学科:LangChain
学习方法:核心目标:掌握基于大语言模型的应用开发流程,能够用 LangChain 搭建简单问答、检索增强生成(RAG)和工具调用应用;学习步骤:1. 先了解大语言模型基础、Prompt 设计、Embedding 和向量数据库等相关概念 2. 学习 LangChain 的核心组件,如 `PromptTemplate`、`LLM`、`Chain`、`Memory`、`Retriever` 和 `Agent` 3. 结合官方文档实操小项目,例如文档问答机器人、网页内容总结工具或本地知识库检索系统;注意事项:优先理解各组件之间的调用关系与适用场景,关注版本更新带来的接口变化,多通过实际项目加深理解。

工程化场景中使用少样本模板的常见问题对应方案

  • 示例过多导致提示词冗长:使用ExampleSelector动态筛选相关示例,避免冗余

  • 示例维护困难将示例存储在文件(JSON/CSV)中,批量加载与更新

  • 不同场景需要不同示例按输入参数匹配示例类型,实现场景化示例分发

ExampleSelector动态筛选

LangChain提供ExampleSelector组件,能根据输入的动态参数(如主题难度、输入长度)筛选最相关的示例,减少提示词体积,提升模型响应效率。

需要创建一个名为 learning_method_examples.json 的文件

[
{"subject": "Python编程(入门)", "difficulty": "easy", "method": "核心目标:掌握基础语法;学习步骤:1.变量与数据类型 2.条件语句;注意事项:边学边练"},
{"subject": "Python编程(进阶)", "difficulty": "hard", "method": "核心目标:掌握面向对象与库开发;学习步骤:1.类与对象 2.模块开发;注意事项:参与开源项目"},
{"subject": "机器学习(入门)", "difficulty": "easy", "method": "核心目标:理解基础概念;学习步骤:1.数据预处理 2.简单模型;注意事项:用Excel辅助理解"},
{"subject": "机器学习(进阶)", "difficulty": "hard", "method": "核心目标:掌握模型优化;学习步骤:1.特征工程 2.超参数调优;注意事项:研读论文复现实验"}
]

两类ExampleSelector筛选方法
第一类就是简单的示例累加,到了提示词上限就截断。

example_selector = LengthBasedExampleSelector( # 按长度筛选示例(控制提示词总长度)
	examples=examples, 
	example_prompt=PromptTemplate( 
		input_variables=["subject", "difficulty", "method"], 
		template="学科:{subject}\n难度:{difficulty}\n学习方法:{method}\n" 
	), 
	max_length=150, # 控制示例总长度,避免提示词过长 
	get_text_length=lambda x: len(x) # 长度计算函数 # 
)

第二类就是根据用户输入的特征,这里采用的是难度(eazyhard)来匹配示例

#自定义ExampleSelector按难度筛选示例
# 当需要根据用户输入的特征(如难度)精准匹配示例时,可自定义ExampleSelector
class DifficultyExampleSelector(BaseExampleSelector):
    """根据用户输入的 difficulty 字段筛选样本"""
    def __init__(self, examples: List[Dict[str, str]]):
        self.examples = examples

    def add_example(self, example: Dict[str, str]) -> None:
        self.examples.append(example)

    def select_examples(self, input_variables: Dict[str, str]) -> List[Dict]:
        # 获取用户输入的难度等级,如果没有提供则默认为 'easy'
        target_difficulty = input_variables.get("difficulty", "easy")
        # 过滤出匹配难度的所有示例
        return [ex for ex in self.examples if ex.get("difficulty") == target_difficulty]

example_selector = DifficultyExampleSelector(examples=examples)
# 5. 构建工程化少样本模板
few_shot_prompt = FewShotPromptTemplate(
    example_selector=example_selector,  # 替换固定examples为动态选择器
    example_prompt=PromptTemplate(
        input_variables=["subject", "difficulty", "method"],
        template="学科:{subject}\n难度:{difficulty}\n学习方法:{method}\n"
    ),
    example_separator="\n", # 控制examples示例之间的分隔方式
    prefix="少样本提示:",
    suffix="参考以上示例,回答:\n学科:{new_subject}\n难度:{difficulty}\n学习方法:",
    input_variables=["new_subject", "difficulty"]  # 新增难度参数
)
# 6. 动态生成不同难度的提示词
# 场景1:生成入门级LangChain学习方法
formatted_prompt_easy = few_shot_prompt.format(
    new_subject="LangChain",
    difficulty="easy"
)
print("入门级少样本提示词:")
print(formatted_prompt_easy)
result_easy = chat_model.invoke([{"role": "user", "content": formatted_prompt_easy}])
print("\n入门级学习方法:")
print(result_easy.content)

输出

入门级少样本提示词:
少样本提示:
学科:Python编程(入门)
难度:easy
学习方法:核心目标:掌握基础语法;学习步骤:1.变量与数据类型 2.条件语句;注意事项:边学边练

学科:机器学习(入门)
难度:easy
学习方法:核心目标:理解基础概念;学习步骤:1.数据预处理 2.简单模型;注意事项:用Excel辅助理解

参考以上示例,回答:
学科:LangChain
难度:easy
学习方法:

入门级学习方法:
核心目标:了解 LangChain 的基本作用与常见组成;学习步骤:1.认识 LLM、Prompt、Chain 的关系 2.动手搭建一个简单问答流程;注意事项:先理解流程,再尝试调用实际模型接口,边学边练
# 场景2:生成进阶级LangChain学习方法
formatted_prompt_hard = few_shot_prompt.format(
    new_subject="LangChain",
    difficulty="hard"
)
print("\n进阶级少样本提示词:")
print(formatted_prompt_hard)
result_hard = chat_model.invoke([{"role": "user", "content": formatted_prompt_hard}])
print("\n进阶级学习方法:")
print(result_hard.content)

输出

进阶级少样本提示词:
少样本提示:
学科:Python编程(进阶)
难度:hard
学习方法:核心目标:掌握面向对象与库开发;学习步骤:1.类与对象 2.模块开发;注意事项:参与开源项目

学科:机器学习(进阶)
难度:hard
学习方法:核心目标:掌握模型优化;学习步骤:1.特征工程 2.超参数调优;注意事项:研读论文复现实验

参考以上示例,回答:
学科:LangChain
难度:hard
学习方法:

进阶级学习方法:
学科:LangChain(进阶)
难度:hard
学习方法:核心目标:掌握基于大语言模型的应用链路设计与智能体开发;学习步骤:1.理解 Prompt、LLM、Output Parser、Chain 等核心组件 2.掌握 Memory、Retriever、Tools、Agent 等高级能力并完成项目实战;注意事项:结合官方文档与源码学习,重点关注版本变化,动手搭建 RAG 与 Agent 项目并持续调试优化

这份代码实现了上面的三个问题的解决方面:

  • 示例存储:优先使用JSON/CSV文件或数据库管理示例,避免代码冗余

  • 动态筛选:必用ExampleSelector组件,按输入特征(长度、难度、类型)匹配示例

  • 性能优化:控制示例总长度,结合模型token限制设计max_length参数

输出解析

将大模型返回的非结构化自然语言,转化为程序可直接处理的结构化数据,这样做方便存储,然后二次调用,也更符合一些业务系统。

没有解析器时,大模型输出存在两大问题:

  • 格式不固定:同一需求可能返回段落、分点、表格等多种格式,代码难以适配

  • 无法直接使用:非结构化文本需要手动写正则、字符串分割等逻辑提取信息,开发效率低且易出错

课程主要介绍了三类:

  • StrOutputParser:仅需要纯文本输出,不要求结构化数据,但希望将大模型输出统一为标准字符串类型(str)

  • JsonOutputParser:核心是自动引导模型输出 JSON 格式,并转化为 Python 字典

  • PydanticOutputParser:核心是通过 Pydantic 定义数据模型,解析器自动校验输出格式,不符合模型的输出会直接报错,提前规避风险。

上面都是基于父类BaseOutputParser进一步为了需求而构建出来,如果有更加灵活的需求的话,可以自己定义解析器。