Hcc的Blog

嵌入式 · AI · 折腾不止

0%

LangChain 学习(1) 环境安装及初体验

安装环境

  首先在电脑上安装 python,打开命令行终端,输入

1
pip install langchain langchain-openai python-dotenv

  接下来在文件夹新建 .env 文件,写入大模型平台的 api_key 以及 Base_url,然后新建 py 文件写入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

load_dotenv()

api_key = os.getenv("BAILIAN_API_KEY")
base_url = os.getenv("BASE_URL")


llm = ChatOpenAI(
model="qwen-plus",
openai_api_key= api_key,
openai_api_base= base_url,
temperature=0.7,
max_tokens=1024
)

response = llm.invoke("你好,请做一个简短的自我介绍。")
print(response.content)

  运行该程序,可以看到大模型给出了回答。接下来我们来检查 LangChain 是否安装成功

1
2
3
4
5
try:
import langchain
print(f"langchain 版本: {langchain.__version__}")
except ImportError:
print("错误:langchain 未安装,请运行 pip install langchain")

  运行该程序,若出现版本号则已安装成功。

第一个 LangChain Agent

  Agent 是 LangChain 最核心的概念,它能让 AI 自动判断何时需要调用工具,并在获取工具结果后继续思考,直到完成任务。

  普通模型的调用是一问一答,Agent 则不一样,它进入一个 思考-行动-观察 循环:模型判断需要调用某个工具 → 执行工具并拿到结果 → 模型根据结果继续思考 → 可能再调用工具 → 直到得出最终答案。举个例子,如果你问”今天杭州天气怎么样?”,普通模型只能回答训练数据中的天气(可能是几个月前的)。而 Agent 会主动调用天气查询工具获取实时数据,然后基于真实数据回答你。

步骤一:定义工具函数

  使用 @tool 装饰器,把普通的 Python 函数变成 Agent 可以调用的工具,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from langchain.tools import tool

@tool
def get_weather(city: str) -> str:
"""查询指定城市的天气情况。

Args:
city: 城市名称,如 "杭州"、"北京"
"""
weather_data = {
"杭州": "晴,25°C,湿度50%",
"北京": "多云,18°C,湿度 45%",
"上海": "小雨,22°C,湿度 80%",
}
return weather_data.get(city, f"未找到 {city} 数据")

@tool
def calculate(expression: str) -> str:
"""执行数学计算。支持加减乘除等基本运算。

Args:
expression: 数学表达式,如 "3 * 7 + 2"
"""
try:
# 安全地计算数学表达式
result = eval(expression, {"__builtins__": {}}, {})
return f"计算结果: {expression} = {result}"
except Exception as e:
return f"计算错误: {e}"

步骤二:创建 Agent

  使用 Langchain 内置的函数创建一个 Agent。代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 步骤 2:创建 Agent
import os
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv

load_dotenv()

api_key = os.getenv("BAILIAN_API_KEY")
base_url = os.getenv("BASE_URL")

# 初始化模型
model = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key = api_key,
base_url = base_url
)

# 创建 Agent,传入模型和工具列表
agent = create_agent(
model=model,
tools=[get_weather, calculate],
system_prompt="你是一个乐于助人的助手,会使用工具来回答问题。",
)

步骤三:运行 Agent

  使用 LangChain 的 Message 构建消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 步骤 3:运行 Agent

# 构建输入消息
# 消息列表中的第一条通常是 HumanMessage(用户消息)
from langchain.messages import HumanMessage

inputs = {"messages": [HumanMessage(content="杭州今天天气怎么样?")]}

# invoke() 运行 Agent,返回最终状态
result = agent.invoke(inputs)

# 查看消息历史(包含 AI 的工具调用和工具返回结果)
print("=== 完整消息历史 ===")
for msg in result["messages"]:
print(f"[{msg.type}] {msg.content[:100]}") # 截取前 100 字符

print("\n=== 最终回复 ===")
# 最后一条 AI 消息就是最终答案
print(result["messages"][-1].content)

  运行,可以看到 Agent 调用了工具并给出了答案。

同步与异步运行

  Agent 支持异步模式,适合在 Web 服务等异步环境中使用:

1
2
3
4
5
6
7
8
9
import asyncio
from langchain.messages import HumanMessage
async def main():
# ainvoke() 是 invoke() 的异步版本
inputs = {"messages": [HumanMessage(content="杭州天气怎么样?")]}
result = await agent.ainvoke(inputs)
print(result["messages"][-1].content)
# 运行异步函数
asyncio.run(main())

  到这里已经学习了 LangChain 中最核心的几个用法:

  • @tool 装饰器把 Python 函数变成工具。
  • create_agent() 创建能自动调用工具的 Agent。
  • agent.invoke() 运行 Agent 并取得结果。

LangChain 模型调用 – init_chat_model() 函数

  LangChain init_chat_model() 是 LangChain 中最常用的函数之一,它让你用统一的方式连接 20 多种模型提供商,不需要记忆每个提供商的类名和参数差异。该函数的语法如下

1
2
3
4
5
6
7
8
9
10
11
from langchain.chat_models import init_chat_model

# 完整语法
model = init_chat_model(
model, # str | None:模型名称(provider:model 格式)
*,
model_provider=None, # str | None:单独的模型提供商
configurable_fields=None, # None | "any" | list[str]:可运行时修改的字段
config_prefix=None, # str | None:配置键前缀
**kwargs, # 模型特定参数(temperature、max_tokens 等)
)

  我们来详解以下各个参数:
  model 参数格式为 提供商:模型名,如下

1
2
3
4
5
model = init_chat_model("deepseek:deepseek-v4-flash")
model = init_chat_model("anthropic:claude-sonnet-4-5-20250929")
model = init_chat_model("deepseek:deepseek-chat")
model = init_chat_model("ollama:llama3.2")
model = init_chat_model("groq:llama-3.3-70b")

  也可以通过手动指定 model_provider 参数,其效果等价于 provider:model 格式,实例如下:

1
2
model = init_chat_model("claude-sonnet-4-5", model_provider="anthropic")
model = init_chat_model("anthropic:claude-sonnet-4-5")

  此外,还有一些常用的 kwargs 参数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
model = init_chat_model(
"deepseek:deepseek-v4-flash",

# 控制输出随机性(0~2),值越小输出越稳定
temperature=0.3,

# 限制输出最大 token 数(控制成本)
max_tokens=200,

# 请求超时时间(秒)
timeout=30,

# 失败重试次数
max_retries=2,

# 自定义 API 地址(代理/中转场景)
# base_url="https://your-proxy.com/v1",

# 速率限制器(控制请求频率)
# rate_limiter=MyRateLimiter(requests_per_second=5),
)

一些工具的用法

  我们可以通过 bind_tools() 函数来绑定模型和工具,通过 with_structured_output() 函数来实现结构化输出。这两个函数是 Agent 和 结构化数据提取的基础。

bind_tools() —— 让模型直到可以使用哪些工具

  普通模型只能生成文本。但调用 bind_tools() 后,模型能在回复中返回 tool_call,告诉程序”我需要调用这个工具”。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
# 用字典描述工具(OpenAI function calling 格式)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如 杭州、北京"
}
},
"required": ["city"]
}
}
}
]
# bind_tools() 将工具绑定到模型
# 模型现在"知道"有 get_weather 这个工具可用
model_with_tools = model.bind_tools(tools)

用 Pydantic 模型描述工具

  对于复杂工具,使用 Pydantic 模型定义参数结构比手写字典更清晰,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model

# 用 Pydantic 定义工具的参数结构
class WeatherInput(BaseModel):
"""查询指定城市的天气情况"""
city: str = Field(description="城市名称,如 杭州、北京")
unit: str = Field(
default="celsius",
description="温度单位,celsius(摄氏度)或 fahrenheit(华氏度)"
)


class CalculatorInput(BaseModel):
"""执行数学计算"""
expression: str = Field(
description="要计算的数学表达式,如 '(3 + 5) * 2'"
)

model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)

# 传入 Pydantic 模型,LangChain 自动转换为工具描述
model_with_tools = model.bind_tools([WeatherInput, CalculatorInput])

# 测试复杂场景
response = model_with_tools.invoke(
"北京今天多少度?顺便帮我算一下 123 * 456"
)

print(f"模型请求了 {len(response.tool_calls)} 个工具调用:")
for tc in response.tool_calls:
print(f" {tc['name']}({tc['args']})")

  使用 Pydantic 定义工具参数是推荐的做法。它提供了类型安全、自动校验,而且 LangChain 会自动从类名和 Field 描述生成工具描述。

with_structured_output() 让模型返回结构化数据

  with_structured_output() 是比 tool_calling 更直接的方式,可以让模型按照指定的格式返回数据而不是返回 tool_call。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model
import os
from dotenv import load_dotenv

load_dotenv()

api_key = os.getenv("BAILIAN_API_KEY")
base_url = os.getenv("BASE_URL")

# 初始化模型
model = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key = api_key,
base_url = base_url
)

class PersonInfo(BaseModel):
"""从文本中提取的人物信息"""
name: str = Field(description="人物姓名")
age: int = Field(description="年龄")
occupation: str = Field(description="职业")
skills: list[str] = Field(description="技能列表")

# with_structured_output() 让模型按照 PersonInfo 格式返回
structured_model = model.with_structured_output(PersonInfo)

# 传入非结构化文本,获取结构化数据
text = "张三今年28岁,是一名全栈工程师,精通 Python、React 和 Docker"
result = structured_model.invoke(text)

print(f"姓名: {result.name}")
print(f"年龄: {result.age}")
print(f"职业: {result.occupation}")
print(f"技能: {', '.join(result.skills)}")
print(f"类型: {type(result)}")