一、 content_blocks 的使用 (实现多模态输入与输出)
content_blocks 在 LangChain 中不仅在 【输入端】 扮演多模态数据(文本、图片等)自由组装 and 排版的角色,同时在 【输出端】 扮演了承载大模型返回的所有结构化"块"(如普通文本块 text、深度思考/思维链块 reasoning、工具调用块等)的角色。它是双向起作用的。
他起的核心作用是可以把图片,音频,视频,和文字混合着放,去更好的表达我们的想法
1. 输入端:多模态自由混排 (多模态提示词模板)
(1) 核心价值
- 强兼容性 :统一使用
content_blocks,可完美兼容 OpenAI、Claude、Gemini 等不同平台的多模态接口,避免使用content传图片在某些模型上报错。 - 支持模板化 :支持在
content_blocks结构中挖坑,动态传入图片数据(Base64)和文本提问变量。
(2) 多模态模板最佳实践代码
python
import base64
from langchain_core.prompts import ChatPromptTemplate
# 假设 model 已经是支持视觉的多模态大模型
# 1. 定义多模态模板(把问题和图片都做成变量)
multimodal_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个图片分析助手。"),
("human", [
{"type": "text", "text": "请仔细观察图片并回答:{question}"},
{
"type": "image",
"base64": "{base64_image}",
"mime_type": "image/png"
}
])
])
# 2. 准备图片 base64 数据
def get_image_base64(path):
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
# 3. 填入变量并调用
prompt_value = multimodal_prompt.invoke({
"question": "图里有什么?瓶盖是什么颜色?",
"base64_image": get_image_base64("image_test.png")
})
response = model.invoke(prompt_value)
print(response.content)
2. 输出端:提取结构化响应(以 DeepSeek 深度思考为例)
(1) 核心价值
- 直接读取
response.content只能拿到最终文本,会丢失模型的思考链(CoT)。 - 读取
response.content_blocks可以完整拿到包含reasoning(思考过程)和text(最终答案)的结构化列表,常用于前端分离展示(如折叠思考过程)。
(2) 提取深度思考代码示例
python
from langchain.chat_models import init_chat_model
# 假设已初始化 model 并启用了思考功能:model = init_chat_model("deepseek...", extra_body={"thinking": {"type": "enabled"}})
# 调用并输出
response = model.invoke("你好,请一句话回答")
# 1. 仅获取最终回答
print(response.content)
# 2. 结构化获取完整响应(包含思考过程)
print(response.content_blocks)
# 返回格式类似:
# [
# {'type': 'reasoning', 'reasoning': '用户要求一句话回答...'},
# {'type': 'text', 'text': '你好,有什么我可以为你做的吗?'}
# ]
二、 部分变量预填充 (partial)
1. 核心价值与痛点
- 类似于 JS 的参数默认值 :如果模板中某些变量(如系统设定的
{role}、{audience})在特定场景下是固定的,你可以使用partial预先填充并"锁定"它们,避免每次调用invoke时都重复传入。 - 分流派生子模板 :允许从一个通用的"母模板"(比如
你是{department}的{role})派生出多个具体业务场景的"子模板"(如it_template和sales_template),实现模板的高效复用。这个有点像又搞了一个子类,然后子类可以把父类一些不确定的属性确定下来一样
2. 最佳实践代码
python
from langchain_core.prompts import ChatPromptTemplate
# 1. 原始母模板:定义了三个变量
base_template = ChatPromptTemplate.from_messages([
("system", "你是{department}的{role}"),
("user", "{task}")
])
# 2. 通过 partial() 分别预填充参数(类似于参数柯里化/绑定默认值)
it_template = base_template.partial(department="IT 部门", role="技术支持")
sales_template = base_template.partial(department="销售部门", role="销售顾问")
# 3. 业务调用:此时只需要传入未被填充的 {task} 即可
# 实际执行相当于:sales_template.invoke({"department": "销售部门", "role": "销售顾问", "task": "..."})
result = sales_template.invoke({"task": "为什么年底汽车会促销?"})
print(result)
三、 消息占位符 (MessagesPlaceholder)
1. 核心价值与痛点 (一句话本质区别)
- 普通变量
{}:解决的是**"消息内部插文字 (String)"**的问题(如给用户提问动态加参数)。 - 消息占位符:解决的是**"模板内部插消息列表 (ListMessage)"**的问题(如动态插入一整段、甚至几十条多轮对话历史)。
2. 两种定义写法(完全等价)
写法 A:元组占位符 (推荐,最省事)
python
template = ChatPromptTemplate.from_messages([
("system", "我是一个AI助手"),
("placeholder", "{history}") # 占位符变量名为 history
])
写法 B:MessagesPlaceholder 类 (经典老写法)
python
from langchain_core.prompts import MessagesPlaceholder
template = ChatPromptTemplate.from_messages([
("system", "我是一个AI助手"),
MessagesPlaceholder(variable_name="history") # 效果与上面一致
])
3. 最佳实践代码 (多轮对话历史管理)
python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 假设 model 已经是初始化好的聊天模型
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一个非常友好的AI助手"),
MessagesPlaceholder(variable_name="history"), # 给历史记录占座
("human", "{question}") # 接收用户本次的新提问
])
# 调用时,直接给 history 传入多轮对话 of 列表(可以是元组列表或 Message 对象列表)
prompt_value = prompt_template.invoke({
"history": [
("human", "5 + 2 = ?"),
("ai", "5 + 2 = 7")
],
"question": "结果再乘以 4 呢?"
})
# 执行后,LangChain 会自动平铺展开历史记录:
# SystemMessage: 你是一个非常友好的AI助手
# HumanMessage: 5 + 2 = ?
# AIMessage: 5 + 2 = 7
# HumanMessage: 结果再乘以 4 呢?
# response = model.invoke(prompt_value)
四、 可复用提示词模板库 (Prompt Library)
1. 核心价值与痛点 (一句话工程化总结)
- "提示词大归类" :将项目中散落各处的所有提示词模板(
ChatPromptTemplate)统一剪切出来,集中存放于一个独立的文件(如templates.py)或专门的类中。 - 解耦降噪:实现了提示词话术与具体业务代码的"高内聚低耦合"。修改提示词文案只需要在此文件/类中修改,业务代码一字不用动,极大方便了非开发人员(PM、Prompt 工程师)的调优与协作。
2. 最佳实践代码
python
# 📂 独立文件:templates.py
from langchain_core.prompts import ChatPromptTemplate
class PromptLibrary:
"""可复用的提示词模板库 (集中式管理)"""
# 1. 翻译模板
TRANSLATOR = ChatPromptTemplate.from_messages([
("system", "你是专业翻译,精通{source_lang}和{target_lang}"),
("user", "翻译以下文本:\n{text}")
])
# 2. 摘要模板
SUMMARIZER = ChatPromptTemplate.from_messages([
("system", "你是内容摘要专家"),
("user", "将以下内容总结为{num}个要点:\n{content}")
])
# ----------------------------------------------------------------
# 📂 具体的业务逻辑代码:main.py
# from templates import PromptLibrary
# 直接点出模板对象并调用,业务代码极度干净
messages = PromptLibrary.TRANSLATOR.invoke({
"source_lang": "英语",
"target_lang": "中文",
"text": "Hello World"
})