第二天 LangChain核心组件上
第二天 LangChain核心组件上
本日学习目标
- 理解提示词为什么会直接决定模型输出质量。
- 掌握
PromptTemplate、ChatPromptTemplate的基本用法。 - 掌握模型参数
temperature、max_tokens、top_p的作用。 - 学会用输出解析器拿到结构化结果。
- 能把“模板 + 模型 + 解析器”组合成一个简单应用。
1. 今天的核心主线
第二天开始正式进入 LangChain 的“组件化”思维。
Prompt想清楚 -> 用模板参数化 -> 调模型生成 -> 用解析器拿结果 -> 组合成应用如果你觉得 LangChain 难,往往不是代码难,而是没有把这条链路想明白。
2. 提示词工程基础
前言
2.1 什么是 Prompt

Prompt 就是你发给模型的指令。模型能不能把任务做好,很大程度上取决于你的表达是否清晰。
一个好的提示词,不是“话多”,而是“信息完整、目标明确、边界清楚”。
2.2 好提示词的四个基本元素
最常用的结构可以记成下面这四项:
角色:你希望模型以什么身份工作。任务:具体让它做什么。要求:有哪些限制条件。输出格式:希望它按什么格式返回。
示例对比:
不好的写法:
写一篇关于AI的文章更好的写法:
你是一名科普老师。
请写一篇关于人工智能的短文。
要求:
1. 面向高职学生
2. 语言通俗
3. 200字左右
4. 结尾给出一个生活中的应用例子2.3 为什么结构化提示词更稳定
大模型对prompt开头和结尾的内容更加敏感
先定义角色,其实在开头把问题域收窄,减少二义性,然后再给出任务描述,这样就不会出现「你是一个yyy」这种二义性问题了。
因为模型擅长根据上下文做概率预测。上下文越清楚,它越容易往你想要的方向生成。
模糊输入 -> 模型自由发挥空间很大 -> 输出不稳定
结构化输入 -> 模型约束更明确 -> 输出更可控2.4 常见提示词技巧
1. 角色设定
你是一名资深客服专员,请用礼貌、专业、简洁的语气回答用户问题。2. 少样本提示 Few-shot
给模型几个示例,它更容易学会你想要的风格或格式。
示例1:
输入:苹果
输出:一种常见水果,口感脆甜,富含维生素。
示例2:
输入:香蕉
输出:一种常见热带水果,口感软糯,适合补充能量。
请按照上面的风格介绍:橙子3. 思维链提示 CoT
思维链是大模型涌现出来的一种神奇能力
- 它是偶然被「发现」的 (OpenAl的人在训练时没想过会这样)
- 有人在提问时以「Let's think step by step」开头,结果发现 AI 会把问题分解成多个步骤,然后逐步解决,使得输出的结果更加准确。

思维链的原理:
- 让 AI生成更多相关的内容,构成更丰富的「上文」,从而提升「下文」
- 对涉及计算和逻辑推理等复杂问题,尤为有效
当任务涉及推理时,可以让模型“分步骤思考”。
请分步骤分析这道题,并在最后给出答案。注意
在正式产品中,不是每一次都要显式要求“输出完整思维过程”。很多时候只需要“先分析,再给结论”即可,避免输出冗长、成本增加。
3. PromptTemplate 基础
前言
3.1 为什么需要模板
如果你每次都手写完整提示词,不但重复,而且容易出错。模板的作用就是把“固定部分”和“变化部分”拆开。
固定任务描述 + 动态变量 -> 组成最终提示词3.2 基础示例:翻译模板
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate.from_template(
"请把下面这句话翻译成{target_lang}:\n{content}"
)
result = prompt.invoke({
"target_lang": "英文",
"content": "今天天气很好,我们去图书馆学习。"
})
print(result.text)请把下面这句话翻译成英文:
今天天气很好,我们去图书馆学习。你要理解:
{target_lang}和{content}是变量。invoke()是把变量填进去,生成最终提示词。- 此时还没有调用模型,只是生成了可发送给模型的文本。
3.3 多变量模板
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
template="""
请为下面的产品生成一段宣传文案。
产品名称:{name}
产品特点:{features}
目标用户:{target_user}
要求:
1. 语言简洁
2. 突出卖点
3. 控制在100字以内
""".strip(),
input_variables=["name", "features", "target_user"]
)
final_prompt = prompt.invoke({
"name": "智能保温杯",
"features": "恒温显示、长续航、便携轻巧",
"target_user": "大学生"
})
print(final_prompt.text)输出结果:
请为下面的产品生成一段宣传文案。
产品名称:智能保温杯
产品特点:恒温显示、长续航、便携轻巧
目标用户:大学生
要求:
1. 语言简洁
2. 突出卖点
3. 控制在100字以内3.4 模板的价值
模板最重要的意义不是“少打字”,而是:
- 便于复用
- 便于统一风格
- 便于和代码参数结合
- 便于后期做批量处理
总结
结合之前的模型,结合提示词模版
4. 进阶提示词模板
前言
4.1 FewShotPromptTemplate
当你希望模型模仿某种输出风格时,少样本模板非常好用。
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
examples = [
{"question": "太阳从哪边升起?", "answer": "太阳从东方升起。"},
{"question": "一年有几个月?", "answer": "一年有12个月。"}
]
example_prompt = PromptTemplate.from_template(
"问题:{question}\n回答:{answer}"
)
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="请参考下面示例的回答风格。",
suffix="问题:{input}\n回答:",
input_variables=["input"]
)
result = few_shot_prompt.invoke({"input": "一周有几天?"})
print(result.text)输出结果:
请参考下面示例的回答风格。
问题:太阳从哪边升起?
回答:太阳从东方升起。
问题:一年有几个月?
回答:一年有12个月。
问题:一周有几天?
回答:4.2 ChatPromptTemplate
聊天模型的提示词往往不是一整段纯文本,而是多条消息组成的。
LangChain 对话消息 4 巨头
HumanMessage 用户说的话(你现在用的)
AIMessage AI 回复的话(模型返回)
SystemMessage 系统提示词 / 角色设定(超级重要!)
ToolMessage 工具调用返回的消息(高级功能,前期不用讲)

但是如果使用ChatPromptTemplate,就需要用到消息角色:
system:系统设定,定义角色和总规则。human:用户输入。ai:历史回复,常用于多轮对话。
案例代码如下:
from langchain_core.prompts import ChatPromptTemplate
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
load_dotenv()
model = ChatOpenAI(
model=os.getenv("OPENAI_MODEL"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=0.7
)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一名耐心的 Python 助教。"),
("human", "请用初学者能听懂的方式解释:什么是列表?")
])
#大模型调用这个prompt
#固定写法
# response = model.invoke(prompt.format_prompt())
# print(response.content)
#管道写法:LCEL 管道,LangChain 1.x 标准 推荐 推荐这样写
chain = prompt | model
response = chain.invoke({})
print(response.content)运行结果:
你好呀!欢迎来到 Python 的世界。我是你的助教,别担心,我们今天不背枯燥的概念,我用一个生活中的小例子来给你讲讲什么是**列表(List)**。
### 🚂 想象一列“神奇的小火车”
在 Python 里,**列表就像是一列可以装载各种货物的小火车**。
1. **它能装很多东西**:你可以把很多数据(比如名字、分数、物品)放进这列火车里。
2. **每节车厢都有编号**:为了找到特定的货物,每节车厢都有一个专属的编号。
3. **它能装各种类型的货物**:这列火车很神奇,第一节车厢可以装“苹果”,第二节可以装“数字 100”,第三节甚至可以装“另一列小火车”!
4. **它可以随时变形**:你可以随时给它加挂新车厢,或者卸下一节车厢。
。。。。4.4 为什么聊天模板很重要
因为实际开发里,大多数模型应用都不是“单段文本生成”,而是“有角色、有历史、有当前问题”的消息式输入。
5. 大模型调用详解
前言
5.1 LLM 与 ChatModel 的区别
可以简单这样理解:
LLM:偏向“文本输入 -> 文本输出”。ChatModel:偏向“消息输入 -> 消息输出”。
现在实际项目中更常用的是 ChatModel。
5.2 初始化模型
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
model = ChatOpenAI(
model=os.getenv("OPENAI_MODEL", "qwen-plus"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=0.2
)5.3 常见参数说明
1. temperature
控制生成随机性。
- 值越低,回答越稳定、越保守。
- 值越高,回答越发散、越有创造性。
建议:
- 翻译、信息抽取、分类:
0到0.3 - 文案、故事、诗歌:
0.7左右
2. max_tokens
限制最大输出长度。太小会截断,太大可能浪费成本。
3. top_p
也是控制采样范围的参数。新手学习阶段,一般先重点掌握 temperature 即可。
5.4 体验参数差异
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
load_dotenv()
model_low = ChatOpenAI(
model=os.getenv("OPENAI_MODEL"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=0
)
model_high = ChatOpenAI(
model=os.getenv("OPENAI_MODEL"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=1
)
prompt = [HumanMessage(content="请写一句关于夏天的文案。")]
print("低温度:", model_low.invoke(prompt).content)
print("高温度:", model_high.invoke(prompt).content)运行结果:
低温度: 冰镇汽水的冒泡声,树荫下斑驳的光影,还有傍晚六点半的橘色晚霞,夏天把世间所有的美好,都揉进了这热烈的时光里。
高温度: “想把冰镇西瓜的清甜与橘子味的晚霞,一起揉进夏天温柔的晚风里。”
*(如果你需要其他风格,这里还有几句备选:)*
* **青春热烈**:“阳光被树叶剪碎,蝉鸣在枝头回荡,所有的美好都在夏日里热烈地生长。”
* **治愈清新**:“夏天的风带着海盐汽水的味道,吹散了心头的烦躁,也吹来了傍晚的满天繁星。”
* **简短高级**:“夏日迟迟,万物热烈。”可以发现:低温度保守,高温度发散,具有创造性
6. 输出解析器
前言
6.1 为什么需要输出解析器
天气接口:http://t.weather.sojson.com/api/weather/city/101030100
{
"message": "success感谢又拍云(upyun.com)提供CDN赞助",
"status": 200,
"date": "20260604",
"time": "2026-06-04 22:26:05",
"cityInfo": {
"city": "天津市",
"citykey": "101030100",
"parent": "天津",
"updateTime": "21:52"
},
"data": {
"shidu": "72%",
"pm25": 3,
"pm10": 8,
"quality": "优",
"wendu": "14.1",
"ganmao": "各类人群可自由活动"
}
}因为模型默认返回自然语言,而程序往往需要结构化数据。
例如:
- 你想拿到
标题、摘要、关键词 - 你想拿到
name、price、features - 你想拿到一个列表或 JSON
如果没有解析器,后续代码很难处理。👈 👈 👈
6.2 字符串解析器
最简单的情况,只需要纯文本:
import os
from dotenv import load_dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
load_dotenv()
model = ChatOpenAI(
model=os.getenv("OPENAI_MODEL"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=0.7
)
# ✅ 正确:必须用 ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("human", "请写一句关于夏天的文案。")
])
parser = StrOutputParser() # 字符串解析器
# ✅ 管道链
chain = prompt | model | parser
# 调用
result = chain.invoke({})
print(result)纯字符串输出:
为您写了一句关于夏天的文案:
**“夏天的风,带着西瓜的清甜与晚霞的橘色,把每一个平凡的日子都吹得闪闪发光。”**
***
如果您需要不同风格的表达,这里还有几个备选:
* **文艺清新**:“收集了一整春的温柔,只为在夏天和橘子味的晚风撞个满怀。”
* **俏皮可爱**:“我的快乐很简单,是空调、WiFi,还有冰镇西瓜最中间的那一勺。”
* **热烈青春**:“那就祝我们,都能在阵阵蝉鸣中,热烈、自由且无畏地长大。”
* **浪漫治愈**:“所有的美好都发生在夏天,比如微风,比如繁星,比如你。”
您可以根据发朋友圈或配图的氛围,挑选最喜欢的一句!6.3 Pydantic 结构化输出
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
load_dotenv()
# 结构(必须用英文!)
class SummerEssay(BaseModel):
title: str = Field(description="文案标题")
content: str = Field(description="正文内容")
emotion: str = Field(description="情感风格")
model = ChatOpenAI(
model=os.getenv("OPENAI_MODEL"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=0.7
)
# ================= 关键修复:强制输出英文KEY =================
prompt = ChatPromptTemplate.from_messages([
("human", """
请按照JSON格式输出夏天文案,**严格使用英文key:title, content, emotion**
不要返回中文key!
""")
])
parser = PydanticOutputParser(pydantic_object=SummerEssay) # Pydantic解析器
# 管道链
chain = prompt | model | parser
result = chain.invoke({})
print("标题:", result.title)
print("内容:", result.content)
print("情感:", result.emotion)
# 打印JSON格式数据
print(result.model_dump_json())输出结果:
标题: 夏日出逃计划
内容: 把烦恼扔进橘子味的汽水里,和晚风一起私奔到没有天花板的夏天。
情感: 自由与清新
{"title":"夏日出逃计划","content":"把烦恼扔进橘子味的汽水里,和晚风一起私奔到没有天花板的夏天。","emotion":"自由与清新"}从这一刻开始,你写的不是“聊天脚本”,而是“能被程序处理的数据流”。
7. 组件组合:模板 + 模型 + 解析器
前言
7.1 管道符 |
在 LangChain 中,可以把多个组件串起来:
PromptTemplate -> ChatModel -> OutputParser代码写法:
chain = prompt | model | parser这就像流水线一样。前一个组件的输出,会成为后一个组件的输入。
7.2 案例:新闻摘要器
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
load_dotenv()
class NewsResult(BaseModel):
title: str = Field(description="新闻标题")
summary: str = Field(description="一句话摘要")
keywords: list[str] = Field(description="关键词列表")
model = ChatOpenAI(
model=os.getenv("OPENAI_MODEL", "qwen-plus"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
temperature=0
)
parser = PydanticOutputParser(pydantic_object=NewsResult)
prompt = PromptTemplate(
template="""
请阅读下面新闻内容,并完成信息提取:
新闻内容:
{content}
请严格按照下面格式输出:
{format_instructions}
""".strip(),
input_variables=["content"],
partial_variables={
"format_instructions": parser.get_format_instructions()
}
)
chain = prompt | model | parser
result = chain.invoke({
"content": "某高校近日举办人工智能技能节,学生围绕AIGC、机器人和数据分析等主题进行了作品展示。"
})
print(result)运行结果:
title='某高校举办人工智能技能节' summary='某高校近日举办人工智能技能节,学生围绕AIGC、机器人和数据分析等主题进行了作品展示。' keywords=['人工智能', '技能节', 'AIGC', '机器人', '数据分析']7.3 你要能自己说清楚这条链
原始新闻文本 -> 提示词模板组织任务 -> 模型生成结构化内容 -> 解析器转换成程序可用对象如果你能自己把这句话讲明白,说明你已经开始真正理解 LangChain 了。
