6083 字
30 分钟
LangChain
2026-06-01
无标签

部分内容参考来自 黑马程序员2026最新版LangChain+LangGraph开发实战全套视频课程

1. 相关概念#

1.1 神经网络结构#

深度神经网络分为很多层,是神经网络基本的计算单元,分为

  • 输入层(Input Layer):入口,接收数据
  • 隐藏层(Hidden Layer):信息处理和学习。可以有很多层。
  • 输入层(Output Layer):出口,产生结果

1.2 反向传播#

反向传播(Back propagation):根据前向传播产生的预测结果与真实值之间的误差,从输出层开始,反向逐层计算每个参数(权重和偏置)对总误差的”贡献”大小(即梯度),并据此更新参数。这是一个学习过程。

来自菜鸟教程

基本流程如下:

  • 前向传播:数据逐层加工,直到输出层产出结果
  • 计算误差:计算产出结果与正确结果的误差(Loss)
  • 反向追责:倒推计算每一层的每个连接对误差的贡献
  • 调整权重:根据每个连接的误差贡献比例,调整其权重参数,使误差变小

1.3 词向量#

词向量(Word Embedding)就是把词转为多维空间向量的一种技术。

  • 将人类自然语言文字拆分为一个个片段,称为Token(词)
  • 每个Token都经过模型计算转为一个浮点数数组,作为向量坐标
  • 目标:使词向量在多维空间中的不同方向表达不同的语义

词向量预测

1.4 Transformer自注意力机制#

注意力机制(self-attention):其使得模型能够更加高效的根据上下文信息处理Token,理解Token含义。 注意力机制

1.5 MLP#

多层感知机(Multi-Layer Perceptron)是层级化、全连接的神经网络结构,层与层之间无跳过、无循环,神经元之间全连接(相邻层的任意两个神经元都有连接)

来自MLP-多层感知机-知乎-Strive

1.6 SoftMax#

归一化指数函数(SoftMax)会根据模型计算出的向量结果得出下一个token的概率分布,然后基于概率的随机采样方式挑选一个作为结果。

这个概率受模型的温度系数(Temperature)参数影响,值越大,概率分布越均匀,模型生成结果的随机性越强;反之,结果越确定

温度系数(Temperature)是控制大模型生成文本随机性和多样性的关键参数。“它通过调整模型输出的概率分布,直接影响生成结果的保守性”(值小)或“创造性”(值大)。

AI大模型的温度系数(Temperature)是指什么?

流程

1.7 大语言模型#

Transformer本来是作为翻译用的,但当模型参数规模训练数据量增突破某个临界点时,模型像是突然拥有了智能,不仅可以理解人类语言,还能推理、分析。

这种现象被称为“涌现”(Emergent Abiities)。这种超大规模的语言模型则被称为大语言模型(Large Language Model)

GPT是指

  • 生成式(Generative):根据上文预测紧跟着的下一个Token,从而形成连续的文本输出
  • 预训练(Pre-trained):通过大规模的文本数据进行训练,让大模型可以理解人类语言的语法、词性。
  • Transformer:深度学习的一种神经网络结构。多数大模型都依赖于此。

大语言模型(Large Language Model, LLM)是指模型的参数规模、训练数据量、训练成本、智能程度都远超普通模型的一种神经网络模型。

1.8 认识LangChain#

LangChain 由 Harrison Chase 创建于2022年10月,是用于开发智能体工程(Agent Engineering)的平台。

LangChain自身并不开发LLMS,它的核心理念是为各种LLMs实现通用的接口,把LLMs相关的组件“链接”在一起,简化LLMs应用的开发难度,方便开发者快速地开发复杂的LLMs应用.

主要功能:

  • Prompts:优化提示词(提示词工程)
  • Models:调用各类模型
  • History:管理会话历史记录(记忆)
  • Indexes:管理和分析各类文档
  • Chains:构建功能的执行链条
  • Agent:构建智能体

1.9 Agent#

在人工智能领域,Agent(通常翻译为智能体或代理)是指一种能够感知环境、进行推理、自主决策并采取行动以实现特定目标的智能系统。

2. 大模型API#

2.1 CURL接口调用#

2.1.1 DeepSeek#

DeepSeek文档<-点击这里

Terminal window
curl https://api.deepseek.com/chat/completions \
-H "Content-Type: application/json" \ # 请求头:告诉服务器请求体是 JSON 格式
-H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \ # 请求头:Bearer 认证,${} 表示从环境变量读取 API Key
-d '{ # -d 参数:指定要发送的 JSON 数据体
"model": "deepseek-v4-pro", # 模型名称
"messages": [ # 对话消息数组(按时间顺序排列)
{"role": "system", "content": "You are a helpful assistant."},
# system 角色:设定模型的行为、人格和回复风格(可选)
{"role": "user", "content": "Hello!"}
# user 角色:表示用户输入的内容
],
"thinking": {"type": "enabled"}, # 深度思考开关:enabled 开启后模型会先输出内部推理链
"reasoning_effort": "high", # 推理强度:指定思考深度,可选 low/medium/high(仅在 thinking 开启时生效)
"stream": false # 流式输出:false 表示一次性返回完整结果;true 表示逐字流式输出
}'

2.1.2 百炼#

百炼文档<-点击这里

Terminal window
curl -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6-plus",
"messages": [
{
"role": "user",
"content": "你是谁?"
}
]
}'
# 返回结果
{
"choices": [
{
// 消息对象:包含完整的对话内容
"message": {
"role": "assistant", // 角色:assistant 表示这是模型的回复(与 user 对应)
"content": "你好!我是Qwen..." // 实际生成的文本内容
},
"finish_reason": "stop", // 结束原因:stop 表示正常完成(未触发生成长度限制)
"index": 0, // 索引号:当一次请求生成多个回复时的序号(0 表示第一个)
"logprobs": null // 对数概率:通常为 null,需单独开启才返回 token 级别的概率信息
}
],
"object": "chat.completion", // 对象类型:固定值,表示这是一个对话补全请求的响应
// Token 使用统计:按量计费的关键数据
"usage": {
"prompt_tokens": 12, // 输入 token 数:用户发送的消息 + 系统提示词消耗的 token
"completion_tokens": 77, // 输出 token 数:模型生成回复消耗的 token
"total_tokens": 89 // token 数:12 + 77 = 89(本次 API 调用的计费依据)
},
"created": 1680300000, // 创建时间:Unix 时间戳(秒),记录本次请求的生成时间
"system_fingerprint": null, // 系统指纹:通常为 null,用于后端调试或版本追踪
"model": "qwen-plus-2025-07-28", // 实际使用的模型:确认请求时指定的模型生效
"id": "XX" // 请求唯一标识:用于排查问题和追踪调用记录
}

2.2 会话记忆#

DeepSeek多轮对话,内容来源官网

DeepSeek /chat/completions API 是一个“无状态” API,即服务端不记录用户请求的上下文,用户在每次请求时,需将之前所有对话历史拼接好后,传递给对话 API。

下面的代码以 Python 语言,展示了如何进行上下文拼接,以实现多轮对话。

from openai import OpenAI
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")
# Round 1
messages = [{"role": "user", "content": "What's the highest mountain in the world?"}]
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages
)
messages.append(response.choices[0].message)
print(f"Messages Round 1: {messages}")
# Round 2
messages.append({"role": "user", "content": "What is the second?"})
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages
)
messages.append(response.choices[0].message)
print(f"Messages Round 2: {messages}")

第一轮请求时,传递给 API 的 messages 为:

Terminal window
[
{"role": "user", "content": "What's the highest mountain in the world?"}
]

第二轮请求时:

  • 要将第一轮中模型的输出添加到 messages 末尾
  • 将新的提问添加到 messages 末尾 最终传递给 API 的 messages 为:
[
{"role": "user", "content": "What's the highest mountain in the world?"},
{"role": "assistant", "content": "The highest mountain in the world is Mount Everest."},
{"role": "user", "content": "What is the second?"}
]

2.3 客户端调用#

from dotenv import load_dotenv
import os
from openai import OpenAI
load_dotenv()
api_key = os.getenv("API_KEY")
client = OpenAI(
api_key=api_key,
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
response = client.chat.completions.create(
model="XXX",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False
)
print(response.choices[0].message.content)
# Hello! How can I assist you today?

3. LangChain使用#

3.1 Demo案例#

# uv add langchain
# uv add langchain-openai
# uv add python-dotenv
# 在.env文件中添加
# OPENAI_API_KEY=XXXXXXXXX
# OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("OPENAI_API_KEY") # 获取API KEY
# 定义工具
from langchain.tools import tool
@tool
def getWeather(location:str)->str:
"""
获取指定位置的天气信息。
参数:
location: 城市名称,如"北京"、"上海"
"""
# 模拟天气数据(实际使用中可以替换成真实API)
weather_db = {
"北京": "晴天 25°C",
"上海": "多云 28°C",
"深圳": "阵雨 30°C",
"广州": "阴天 27°C",
"杭州": "晴转多云 26°C"
}
# 查找天气
if location in weather_db:
result = f"{location}天气:{weather_db[location]}"
else:
# 默认返回通用天气
result = f"{location}天气:晴 22°C"
return result
# 创建agent
from langchain.agents import create_agent
agent = create_agent(
model="openai:qwen-plus",
tools=[getWeather]
)
# 发起调用
response = agent.invoke({
"messages": [
{"role": "user", "content": "今天深圳天气如何"},
]
})
print(response)

工作流程图

3.2 init_chat_model初始化#

init_chat_model 是 LangChain 提供的一个统一模型初始化函数,它的核心作用是:用同一套代码,无缝切换不同提供商的大语言模型。

from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
import os
# 在.env文件中添加
# OPENAI_API_KEY=XXXXXXXXX
# OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
load_dotenv()
model = init_chat_model(
model="qwen-plus-2025-07-28",
model_provider="openai", # 提供商(qwen不支持自动识别,因此伪装为openai)
temperature=0.7, # 随机性
max_tokens=1024, # 输出最大token数
timeout=10, # 请求超时秒数
max_retries=3, # 失败重试次数
top_p=0.5, # 范围 0-1,通常与 temperature 二选一调整
stop=["4.", "4)", "4、"] # 用于控制回复的结束位置
)
response = model.invoke("你好,请介绍一下自己")
print(response.content)
print(type(model))
# <class 'langchain_openai.chat_models.base.ChatOpenAI'>

3.3 调用方式#

3.3.1 invoke#

  • invoke函数是阻塞式调用,需要等待模型生成全部结果才会返回,等待时间较长
response = model.invoke("message")
response = model.invoke([
"role":"system""content":"你是一个AI助手"},
"role":"user""content":"介绍你自己"},
])

3.3.2 stream#

invoke阻塞式调用需要等待较长时间才能看到AI返回的结果,而stream则是流式调用,可以实时看到AI返回的一个个词。

stream = model.stream("你好,请介绍一下自己")
print( type(stream)) # <class 'generator'>
for chunk in stream: # 只可遍历一次即内容用完了
print(chunk.content,end="")
# 你好!我是......

4. 智能体使用模型#

4.1创建智能体#

Langchain提供了一个create_agent函数用来快速创建智能体。调用create_agent时需要指定一个模型。有两种选择:

  • 使用初始化好的模型对象
  • 使用模型名称,让Langchain自动初始化模型
from langchain.agents import create_agent
# 方法1:初始化已经定义好的model
agent = create_agent(model=model)
# 方法2:指定model名称
agent1 = create_agent("openai:qwen-plus-2025-07-28")

4.2 调用智能体#

智能体调用与模型调用类似,也支持两种方式:

  • invoke:阻塞式调用
  • stream:流式访问

但需要注意的是,智能体调用时需要传入一个dict,其中必须包含一个messages字段,也就是消息的列表。

# 方法1:invoke
response = agent1.invoke({
"messages": [{"role":"user","content":"Hi"}]
})
print(response["messages"][-1].content)
# Hello! ٩(◕‿◕。)۶ How can I assist you today?
# 方法2:stream
response = agent.stream(
{"messages": [{"role":"user","content":"Hi"}]},
stream_mode="messages"
)
for token, metadata in response:
if token.content:
print(token.content,end="",flush=True)

5. 消息#

消息(message),在LangChain中,发送给模型的消息、模型返回的消息都统一被封装为BaseMessage,并且准备了多个BaseMessage子类对应不同角色类型的消息。

  • SystemMessage -> Role: system,代表系统消息,用于设定模型角色和交互背景
  • HumanMessage -> Role: user,代表用户输入的消息
  • AIMessage -> Role: assistant,代表LLM生成的响应,包含:文本、工具调用、元数据
  • ToolMessage -> Role: tool,代表工具调用时产生的结果

我们可以直接使用这些Messages类型来发送消息,以此替代消息数组

5.1 文本消息#

'''省略部分,可参考 3.LangChain使用 - 3.1Demo案例'''
# 发起调用
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
response = agent.invoke({
"messages": [
SystemMessage("可以使用工具获取天气状态"),
HumanMessage("你好"),
AIMessage("你好我是DeepSeek,请问有什么可以帮忙的?"),
HumanMessage("香港的天气怎么样?")
]
})
print(response["messages"][-1].content)
# 香港目前天气晴朗,气温为22°C,非常舒适。建议穿着轻便衣物,适合外出活动。
for message in response["messages"]:
message.pretty_print()
'''
=== System Message ========================
可以使用工具获取天气状态
=== Human Message =========================
你好
=== Ai Message ============================
你好我是DeepSeek,请问有什么可以帮忙的?
=== Human Message =========================
今天香港天气怎么样?
===Ai Message =============================
Tool Calls:
getWeather (call_XXX)
Call ID: call_XXX
Args:
location: 香港
=== Tool Message ==========================
Name: getWeather
香港天气:晴 22°C
==== Ai Message ===========================
今天香港天气晴朗,气温为22°C。适合外出活动哦!
'''

5.2 多模态消息#

LangChain也支持向模型发送多模态消息,比如图片、音频、视频、文本等。但前提是必须是多模态模型才支持。

qwen3.5-omni-flash-2026-03-15为例子

5.2.1 在线图片#

# 发送在线图片消息,多模态
from langchain.chat_models import init_chat_model
# 初始化模型
model = init_chat_model(
model="qwen3.5-omni-flash-2026-03-15",
model_provider="openai",
temperature=0.7,
max_tokens=1024
)
# 创建agent
agent = create_agent(model=model)
# 准备多模态消息
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
message = HumanMessage(
[
{"type":"text","text":"这是谁?请通过这张图片的内容进行简要回答即可"},
{"type":"image","url":"https://......."}
]
)
# 发送请求
stream = agent.stream(
{"messages": [message]},
stream_mode="messages"
)
for token, metadata in stream:
if token.content:
print(token.content,end="",flush=True)

5.2.2 本地图片#

有时候用户会上传图片数据,而不是图片的url地址。我们需要将图片数据转换base64字符串,然后发送给模型。

使用插件模拟图片上传、转换的过程。

uv add ipywidgets

from ipywidgets import FileUpload # 导入文件上传组件
from IPython.display import display # 导入显示函数
'''
创建上传控件
1. accept='*' : 接受所有文件类型(也可以指定如 '.txt,.pdf')
2. multiple=False : 不允许同时上传多个文件(True 则允许)
'''
uploader = FileUpload(accept='*', multiple=False)
display(uploader) # 在 notebook 中显示这个控件
print (uploader.value)
# ({'name': 'OIP-C.jpeg', 'type': 'image/jpeg', 'size': 42998, 'content': <memory at 0x147d32800>, 'last_modified': datetime.datetime(2026, 1, 3, 12, 24, 29, 700000, tzinfo=datetime.timezone.utc)},)
# 读取图片,转为base64字符串
import base64
uploaded_file = uploader.value[0] # 获取第一个上传的文件
content_mv = uploaded_file["content"] # 获取其内存视图
img_bytes = bytes(content_mv) # # 转换内存视图->字节 or content_mv.tobytes()
img_b64 = base64.b64encode(img_bytes).decode( "utf-8") # base64编码
# 组织多模态消息
picture_question = HumanMessage(content=[
{
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{img_b64}"}
},
{"type":"text","text":"简要介绍这个图片里是谁"}
])
# 遍历结果
for chunk,metadata in agent.stream(
{"messages":[picture_question]},
stream_mode="messages"
):
print(chunk.content,end="",flush=True)

6. 提示词#

6.1 系统提示词#

提示词(Prompt)就是发送给模型的消息,其中SystemMessage是系统提示词(system prompt),可以给模型设定角色、聊天的背景、任务说明,对模型生成的内容有很大的影响。

通过在定义agent的过程中,利用参数system_prompt进行声明相关内容

from langchain.agents import create_agent
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
from langchain.chat_models import init_chat_model
import os
from dotenv import load_dotenv
load_dotenv()
# 创建model
model = init_chat_model(
model="qwen-plus-2025-07-28",
model_provider="openai",
temperature=0.7,
max_tokens=1024
)
# 创建agent
agent = create_agent(
model=model,
system_prompt="请你以XXX的语气并进行简短回答",
)
# 调用智能体
for token, metadata in agent.stream(
{
"messages": [HumanMessage(content="你是谁?")]
},
stream_mode="messages"
):
print(token.content,end="",flush=True)

6.2 提示词工程#

所谓提示词工程(Prompt Engineering),就是通过优化提示词使模型输出的结果更符合业务需要的过程

一般来说,系统提示词(SystemPrompt)会包含以下几个部分,通常按此顺序排序

  • 身份角色(Identity):描述AI的职责、沟通风格和总体目标。
  • 指令说明(Instructions):请指导模型如何生成所需的响应。它应该遵循哪些规则?模型应该做什么,以及模型绝对不能做什么?
  • 对话示例(Examples):提供可能的输入示例,以及模型期望的输出.
  • 背景信息(Context):向模型提供生成响应所需的任何额外信息,例如RAG的额外知识库数据,或您认为特别相关的任何其他数据。

在编写System Prompt时,您可以使用Markdown格式和XML标签的组合来帮助模型理解提示和上下文数据的逻辑边界。

  • Markdown的标题和列表有助于标记提示的不同部分,并向模型传达层级结构。它们还可以提高开发过程中提的可读性。
  • XML标签可以帮助明确区分一段内容(例如用作参考的辅助文档)的起始和结束位置。

6.2.1 设定角色和指令#

添加了指令描述,可以进一步约束模型的行为,什么能做,什么不能做

Terminal window
'''
# 身份
- 你是一个编程助手,你帮助用户编写Python代码
# 指令
- 定义变量时,使用snake case命名法,而不是camel case命名法。
- 不要返回markdown格式说明,仅仅返回代码即可。
'''

6.2.2 对话示例#

Few-shot示例是一种为模型提供多个示例的方法,以便它可以学习行为模式并生成更准确的响应。

Terminal window
'''
# 身份
- 你是一个文本分类助手
# 指令
- 请严格遵循以下示例的模式进行分类
- 只返回分类结果,不输出任何额外解释
# 示例
- 输入:"这个产品太棒了!" → 正面
- 输入:"质量很差,不推荐。" → 负面
- 输入:"还可以吧,凑合用。" → 中性
# 输出格式
- 只输出:正面 / 负面 / 中性
'''

6.2.3 结构化输出#

模型擅长自然语言交流和非结构化数据识别,但是传统程序识别结构化的数据会更加方便。所以有时候我们希望模型也能输出固定结构的内容,方便我们解析。

这可以通过系统提示词来实现,我们可以在提示词中指定模型的输出格式,从而使模型的输出更易于解析和使用。

  1. 基于提示词的结构化输出
Terminal window
'''
# 身份
- 你是一个信息提取助手,负责从用户输入中提取结构化数据
# 指令
- 严格按 JSON 格式输出
- 只输出 JSON,不输出任何额外解释或标记
- 缺失的字段用 null 填充
# 输出格式
{
"name": "姓名",
"age": "年龄(数字)",
"city": "城市",
"occupation": "职业"
}
# 示例
用户输入:"我叫张三,今年25岁,在上海做工程师"
输出:
{"name": "张三", "age": 25, "city": "上海", "occupation": "工程师"}
用户输入:"李四,北京"
输出:
{"name": "李四", "age": null, "city": "北京", "occupation": null}
'''
  1. 基于Model的结构化输出 在LangChain中,实现结构化输出会更加简单。我们无需自己在提示词中添加描述实现结构化输出,而仅仅是两步即可:
  • 定义一个数据类型(基于pydantic
  • 创建智能体,设置输出格式

在构建agent中,使用参数response_format

from pydantic import BaseModel
# 定义类,用于封装模型所需要输出的数据结构:
class CapitalInfo(BaseModel):
name: str # 城市名称
location: str # 地理位置
vibe: str # 城市特色/氛围
economy: str # 经济发展
agent = create_agent(
model = model,
system_prompt="你是一个科幻作家,根据用户的要求创建一个太空之都。",
response_format=CapitalInfo
)
response = agent.invoke(
{"messages":[HumanMessage("月球的首都在哪里?")]}
)
city = response['structured_response']
print(city) # name='月影城' location='月球静海基地' vibe='宁静而科技感十足' economy='以太空科研和氦-3能源产业为主'

7. 工具#

模型(Mode)是Agent的大脑,负责推理分析。而工具(Tools)则是Agent的手脚,负责执行任务,与外界交互。

一个完整的Agent至少要包含两个关键的部分:

  • 模型:是Agent的大脑,负责推理、分析,规划任务步骤
  • 工具:是Agent的手脚,负责执行任务,与外界交互

因此,定义带有工具的Agent的基本流程如下:

  • 定义工具
  • 初始化模型
  • 初始化Agent,绑定模型和工具

Agent调用工具

7.1 自定义工具#

所谓的工具(Tool),本质就是一个可调用的函数,但是这个函数不是我们自己去调用,而是给模型调用。因此除了定义函数外,我们还需要清晰描述这个工具,让模型知道这个工具如何使用。包括下列信息:

  • 工具名称
  • 工具的作用
  • 工具所需要的参数
  1. 基于Tool描述工具 在LangChain中,定义工具需要用到@tool装饰器,我们可以通过装饰器来定义工具名、工具的作用:
from langchain_core.tools import tool
@tool("square_tool",description="用于计算一个数的平方根值")
def square_tool(x:float)->float:
return x**2
  1. 使用函数名和文档注释描述工具

如果不使用@tool装饰器没有定义工具名和作用描述,此时:

  • 工具名:默认就是函数名
  • 工具所需的参数:默认就是函数的参数列表
  • 工具作用的描述:默认就是函数的文档注释
from langchain_core.tools import tool
@tool
def square_tool(x:float)->float:
"""用于计算一个数的平方值"""
return x**2
@tool
def get_weather(location: str, units: str = "celsius", include_forecast: bool = False) -> str:
"""
获取当前天气和可选的天气预报。
参数:
location: 城市名称或坐标
units: 温度单位
include_forecast: 是否包含天气预报
"""
temp = 22 if units == "celsius" else 72
result = f"{location}当前天气:{temp}{units[0].upper()}"
if include_forecast:
result += "\n未来5天:晴朗"
return result
get_weather.invoke({"location":"HongKong","units":"celsius","include_forecast":False})
  1. 定义PydanticModel描述参数

如果函数的参数比较多,而且比较复杂,此时建议通过pydantic model来描述参数列表。

# 通过自定义模型约束入参
from pydantic import BaseModel, Field
from typing import Literal # 枚举
# 天气查询工具的输入参数模型
class WeatherInput(BaseModel):
location: str = Field(description="城市名或坐标")
units: Literal["celsius", "fahrenheit"] = Field(
default="celsius",
description="温度单位"
)
include_forecast: bool = Field(
default=False,
description="是否包含5天预报"
)
@tool(args_schema=WeatherInput) # 参数约束 args_schema
def get_weather(location: str, units: str = "celsius", include_forecast: bool = False) -> str:
"""获取当前天气和可选的天气预报。"""
temp = 22 if units == "celsius" else 72
result = f"{location}当前天气:{temp}{units[0].upper()}"
if include_forecast:
result += "\n未来5天:晴朗"
return result

7.2 预定义工具#

Tool-LangChain官方文档

工具集成中文文档

Tavily 搜索工具相关文档

以TavilySearch为例,每月1000次免费搜索(实际情况以官网为准

  1. 初步认识工具
from langchain_tavily import TavilySearch
from dotenv import load_dotenv
import os
load_dotenv()
search_tool = TavilySearch(
max_results=5, # 最大返回结果数
topic="general", # 搜索主题:general/news/finance
# include_answer=False, # 是否包含AI生成答案
# include_raw_content=False, # 是否包含完整页面内容
# include_images=False, # 是否包含图片列表
# include_image_descriptions=False,# 是否包含图片描述
# search_depth="basic", # 搜索深度:basic/advanced
# time_range="day", # 时间过滤:day/week/month/year
# include_domains=None, # 限定域名列表
# exclude_domains=None # 排除域名列表
)
search_tool.invoke({"query": "上周热点新闻有哪些?简短回答即可"})
  1. 实践使用
使用示例
from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from langchain.messages import HumanMessage, AIMessage, SystemMessage
model = init_chat_model(
model="qwen-plus-2025-07-28",
model_provider="openai",
temperature=0.7,
max_tokens=1024
)
agent = create_agent(
model=model,
tools=[search_tool]
)
response = agent.invoke(
{"messages":[HumanMessage("上周知乎热点有哪些,简要回答列表10个即可")]}
)
print(response["messages"][-1].content)
  1. 工具优化
  • 使用 @tool 装饰器将 TavilySearch 实例包装为 LangChain 工具,使其可被 Agent 直接调用
  • 定义 AnswerInfoReference 结构化输出模型,强制 Agent 返回包含答案和引用来源的规范格式
tavily = TavilySearch(
max_results=5,
topic="general",
)
@tool
def web_search(query:str):
"""用于Web网页信息检索"""
return tavily.invoke(query)
from pydantic import BaseModel,Field
# Agent回答内容引用的网页信息
class Reference(BaseModel):
title: str = Field(description="答案中引用的网页标题")
url: str = Field(description="答案中引用的网页链接")
# Agent的回答内容
class AnswerInfo(BaseModel):
answer: str = Field(description="给用户的最终答案")
reference: list[Reference] = Field(description="答案所引用的网页")
model = init_chat_model(
model="qwen-plus-2025-07-28",
model_provider="openai",
temperature=0.7,
max_tokens=1024
)
agent = create_agent(
model=model,
tools=[web_search],
system_prompt="你是一个智能助手,用于解决用户问题",
response_format=AnswerInfo # 控制 Agent 返回结构化数据的核心参数
)
response = agent.invoke(
{"messages":[HumanMessage("知乎今日热点都有哪些?")]}
)
structured = response["structured_response"]
print("=== 答案 ===")
print(structured.answer)
print("\n=== 引用来源 ===")
for idx, ref in enumerate(structured.reference, 1):
print(f"{idx}. {ref.title}")
print(f" 链接:{ref.url}")
'''
=== 答案 ===
知乎的今日热点内容通常包括实时讨论度高的社会事件、科技动态、文化娱乐等话题。您可以通过知乎App或网页端的“今日热点”话题页(如 https://www.zhihu.com/topic/23509571)查看最新热门讨论。此外,聚合类平台如“今日热榜”(tophub.today)也提供知乎实时热点榜单,便于一站式浏览全网热点。
=== 引用来源 ===
1. 今日热点 - 知乎
链接:https://www.zhihu.com/topic/23509571
2. 真的能追溯微博、知乎等历史热门榜单吗?
链接:https://zhuanlan.zhihu.com/p/1925271264437733172
'''
LangChain
https://blog.20220509.xyz/posts/langchain/
作者
Mint
发布于
2026-06-01
许可协议
CC BY-NC-SA 4.0