【 LangChain 1.2 实战(四)】构建一个模块化的天气查询 Agent


上一章节回顾

在上一节中,完成了 LangChain 1.2 环境搭建 ,并编写了一个最简单的 Agent 天气查询 Demo。具体实现了以下内容:

  1. 环境准备

    • 创建并激活 Conda 环境 langchain_v1.2
    • 安装了 langchain==1.2.0langchain-deepseekpython-dotenv 等核心依赖
  2. 安全配置

    • 创建 .env 文件,存放 DEEPSEEK_API_KEYDEEPSEEK_BASE_URL
    • 编写 env_utils.py,利用 python-dotenv 加载 .env 中的密钥与地址
  3. 模型实例化

    • 编写 my_llm.py,通过 ChatDeepSeek 创建了一个指向 DeepSeek 官方的 LLM 实例
  4. 第一个 Agent

    • quick_start.py 中定义了一个模拟天气工具 get_weather
    • 使用 LangChain 1.2 的 create_agent 快速构建了一个能查询天气的智能助手
    • 成功运行并观察到 Agent 自动调用工具、生成友好回复的完整消息流

成果 :我们跑通了 LangChain 1.2 最基本的 Agent 工作流,验证了模型与工具的联通性。
不足:所有代码堆在根目录的零散文件中,配置、模型、工具、Agent 耦合在一起,不利于扩展和维护。

下面的内容将对这个 Demo 进行深度模块化重构,构建一个结构清晰、可长期维护的项目模板。


🧪 LangChain 1.2 实战:构建一个模块化的天气查询 Agent

1.内容简介

通过一个 天气查询 Demo ,实现如何使用 LangChain 1.2 的 create_agent 新接口快速构建一个能够调用工具的智能助手。

项目采用模块化设计,将配置、模型、工具、Agent 分层解耦,不仅易于理解,更便于未来扩展和维护。

目标:

  • 如何搭建一个结构优雅的 Python AI 项目
  • 如何使用 LangChain 1.2 的 create_agent 一键创建能使用工具的 Agent
  • 如何设计可扩展的工具目录,并让 Agent 自动调用
  • 为什么分层目录结构对长期项目至关重要

2. 技术栈

组件 说明
Python 3.10+ 运行环境
LangChain 1.2 大模型应用开发框架
langchain-openai 提供 OpenAI 兼容接口,用于连接 SiliconFlow
python-dotenv .env 文件加载敏感配置
SiliconFlow 国产大模型 API 中转平台(兼容 OpenAI 接口)

3. 项目目录结构及其设计哲学

复制代码
deepseek_agent_project/          # 项目根目录(一切从这里开始)
├── app/                         # 核心应用包(隔离业务代码)
│   ├── __init__.py              # 声明本目录为 Python 包
│   ├── config.py                # 集中管理所有配置项
│   ├── llm.py                   # 负责实例化大模型
│   ├── agent.py                 # Agent 定义(大脑 + 工具)
│   └── tools/                   # 工具包(可为 Agent 增加各种能力)
│       ├── __init__.py
│       └── weather.py           # 天气查询工具的实现
├── .env                         # 敏感配置(密钥、地址),不提交 Git
├── .gitignore                   # 忽略本地文件
├── main.py                      # 程序入口,开箱即用
└── requirements.txt             # 依赖声明,一键安装

为什么这样设计?

  • app/ 独立成包
    所有业务逻辑收拢在 app 内,根目录保持清爽。未来若需部署为 Web 服务、编写测试、打包发布,只需操作 app 包即可,不会污染全局空间。
  • config.py 是唯一配置来源
    所有环境变量、路径定义集中在一处,其余模块通过 from app.config import ... 获取,方便切换环境(开发/生产)和运行时校验。
  • llm.py 只生产模型实例
    避免在多个地方重复初始化模型,统一管理参数(如 temperature),后续换模型仅需改这一个文件。
  • tools/ 目录独立
    每个工具一个文件,新增能力只需在此目录添加文件,然后在 agent.py 中注册即可。工具模块与 Agent 实现彻底解耦,可单独测试。
  • .env + python-dotenv
    密钥与代码分离,杜绝安全风险。通过 pathlib 绝对定位,不管从哪个目录运行脚本都能正确加载配置。
  • main.py 作为演示入口
    简洁地展示如何调用 Agent,同时证明各模块协作正常。用户可快速"看效果"。

核心理念:高内聚、低耦合、可扩展、可测试。

4. 快速开始

4.1 环境准备

  • Python 3.10+
  • 一个 SiliconFlow 账号,获取 API Key
  • (可选)PyCharm 或 VS Code

4.2 克隆或创建项目

按上述目录结构创建所有文件和文件夹,或直接复制下文代码。

4.3 安装依赖

在项目根目录打开终端,执行:

bash 复制代码
pip install -r requirements.txt

4.4 配置密钥

编辑 .env 文件,填入你的真实 API Key:

ini 复制代码
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
DEEPSEEK_BASE_URL=https://api.siliconflow.cn/v1
MODEL_NAME=deepseek-ai/DeepSeek-V3

4.5 运行

bash 复制代码
python main.py

你会看到类似这样的输出:

复制代码
用户: 北京今天天气怎么样?
助手: 北京 天气(2026-05-04 14:22:10)
🌤 天气:多云
🌡 温度:19°C
💧 湿度:62%
💨 风力:4 级
💡 建议:注意增减衣物。

5. 逐文件深度解析

下面将依次展示每个文件的完整代码,并解释其设计意图。


5.1 项目骨架:requirements.txt.gitignore

requirements.txt

txt 复制代码
langchain>=1.2.0
langchain-openai
python-dotenv

声明了必要依赖,使用 >=1.2.0 确保兼容本教程的 create_agent 接口。

.gitignore

复制代码
.env
__pycache__/
*.pyc
.venv/

保护密钥,忽略临时文件。


5.2 配置中心:app/config.py

python 复制代码
import os
from pathlib import Path
from dotenv import load_dotenv

# 定位项目根目录(config.py 的上两级目录)
PROJECT_ROOT = Path(__file__).resolve().parent.parent

# 加载 .env 文件(绝对路径,不受执行目录影响)
load_dotenv(PROJECT_ROOT / ".env")

# 读取必要配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
if not DEEPSEEK_API_KEY:
    raise ValueError("⚠️ .env 中缺少 DEEPSEEK_API_KEY,请检查!")

DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.siliconflow.cn/v1")
MODEL_NAME = os.getenv("MODEL_NAME", "deepseek-ai/DeepSeek-V3")

设计解读

  • 使用 Path(__file__).resolve().parent.parent 确保无论从哪个目录启动程序,都能找到 .env
  • 缺少关键配置时会立即抛出异常,避免在深层调用时才报错。
  • 提供默认值(如模型名)让新用户开箱即用,同时保留修改空间。

5.3 模型实例化:app/llm.py

python 复制代码
from langchain_openai import ChatOpenAI
from app.config import DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, MODEL_NAME

deepseek_llm = ChatOpenAI(
    openai_api_key=DEEPSEEK_API_KEY,
    openai_api_base=DEEPSEEK_BASE_URL,
    model=MODEL_NAME,
    temperature=0,
)

为什么用 ChatOpenAI 而不是 ChatDeepSeek

SiliconFlow 的 API 完全遵守 OpenAI 的接口规范,使用 langchain-openaiChatOpenAI 可以避免不同版本 langchain-deepseek 参数变动带来的兼容性问题,稳定性更高。

temperature=0 意味着模型输出确定性最强,适合演示和测试。


5.4 工具实现:app/tools/weather.py

python 复制代码
import random
from datetime import datetime

def get_weather(city: str) -> str:
    """获取指定城市的实时天气信息(模拟)。

    参数:
        city: 城市名称,例如 '北京'。
    返回:
        包含天气状况、温度、湿度、风力及查询时间的字符串。
    """
    # 模拟天气类型
    conditions = ["晴天", "多云", "阴天", "小雨", "雷阵雨", "雾霾", "大风"]
    temperature = random.randint(-5, 38)
    humidity = random.randint(30, 90)
    wind_speed = random.randint(1, 10)

    condition = random.choice(conditions)
    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # 根据天气给出生活建议
    if "雨" in condition:
        advice = "记得带伞!"
    elif "晴" in condition:
        advice = "适合户外活动。"
    elif "霾" in condition:
        advice = "请佩戴口罩。"
    else:
        advice = "注意增减衣物。"

    return (
        f"{city} 天气({now})\n"
        f"🌤 天气:{condition}\n"
        f"🌡 温度:{temperature}°C\n"
        f"💧 湿度:{humidity}%\n"
        f"💨 风力:{wind_speed} 级\n"
        f"💡 建议:{advice}"
    )

LangChain 1.2 的增强体验

工具函数不需要 @tool 装饰器或复杂的 BaseTool 子类。只要满足以下条件:

  • 有清晰的类型注解(city: str
  • 有 Docstring(帮助 Agent 理解函数的用途)
  • 返回字符串

Agent 就能自动识别并调用它!这使得定义工具的门槛降到最低。

模拟数据的巧思

采用随机值模拟天气变化,每次查询结果不同,让 Demo 更生动、更像真实 API。同时返回结构化信息(温度、湿度、风力、建议),增强实用性。


5.5 Agent 大脑:app/agent.py

python 复制代码
from langchain.agents import create_agent
from app.llm import deepseek_llm
from app.tools.weather import get_weather

# 使用 LangChain 1.2 的一键创建接口
agent = create_agent(
    model=deepseek_llm,
    tools=[get_weather],
    system_prompt="你是一个助手,你可以查询城市的天气。",
)

这里体现了 LangChain 1.2 最大的简化

旧版写法 (LangChain 0.x/1.0) 新版 (LangChain 1.2)
需要定义 ChatPromptTemplate,手动放置 {agent_scratchpad} 等占位符 只需一个 system_prompt 字符串
必须额外构建 AgentExecutor 实例 create_agent 直接返回可调用的 Agent 实例
调用时传入 {"input": "..."} 调用格式为标准消息列表 {"messages": [{"role": "user", "content": "..."}]}
输出通过 result["output"] 提取 输出是完整的消息列表,最后一条消息的 content 即为助手回答

新接口的调用方式

python 复制代码
resp = agent.invoke(
    {"messages": [{"role": "user", "content": "北京天气怎么样?"}]}
)
final_answer = resp["messages"][-1].content

这种消息列表格式与底层 LLM 的交互完全对齐,更加透明和标准化。


5.6 程序入口:main.py

python 复制代码
from app.agent import agent

if __name__ == "__main__":
    queries = [
        "北京今天天气怎么样?",
        "上海适合户外运动吗?",
    ]
    for q in queries:
        print(f"用户: {q}")
        resp = agent.invoke({"messages": [{"role": "user", "content": q}]})
        final_message = resp["messages"][-1]
        print(f"助手: {final_message.content}\n")

入口文件极端精简,仅展示如何调用 Agent。你可以将其替换为 FastAPI 路由、命令行工具等,无需改动核心逻辑。


6. 技术架构与 LangChain 1.2 特性剖析

6.1 整体架构

复制代码
┌──────────┐
│  main.py │ (表示层)
└────┬─────┘
     │ 调用
┌────▼─────────────────────────────┐
│         agent.py                 │ (Agent 层)
│  create_agent(model, tools,      │
│              system_prompt)      │
└────┬────────────┬────────────────┘
     │            │
┌────▼─────┐  ┌──▼──────────────┐
│ llm.py   │  │ tools/weather.py│ (能力层)
│模型实例化│  │   工具函数       │
└────┬─────┘  └─────────────────┘
     │
┌────▼─────┐
│config.py │ (配置层)
│ .env加载 │
└──────────┘
  • 配置层 为所有层提供敏感参数。
  • 能力层(llm + tools)是"大脑"和"手脚",由 Agent 层统一调度。
  • Agent 层 负责理解用户意图、决策使用哪个工具、组装最终回答,对外暴露极简接口。
  • 表示层main.py)只负责展示,可轻易替换。

6.2 LangChain 1.2 的 create_agent 带来了什么?

  1. 极简创建:一行代码搞定 Agent,无需拼接模板和执行器。
  2. 工具自动识别:普通函数加类型注解和文档字符串即可被 Agent 理解,极大降低开发门槛。
  3. 标准消息接口:输入/输出均为消息列表,便于集成流式处理、上下文管理等高级功能。
  4. 开箱即用的容错 :Agent 内置了对工具调用格式错误的恢复机制(可通过 handle_parsing_errors 调整)。
  5. 面向未来 :新版本 LangChain 的 Agent 图(LangGraph)与 create_agent 兼容,后续可无缝升级到有状态的多步智能体。

6.3 项目如何展示 LangChain 1.2 的功能?

  • 工具调用(Tool Calling) :用户询问天气,Agent 自动识别并调用 get_weather,将函数返回结果组织成自然语言。
  • 角色设定(System Prompt) :通过 system_prompt 定义助手的行为边界,Agent 会严格遵守。
  • 模型无关性 :通过 ChatOpenAI 兼容接口,轻松切换底层大模型(只需改 config.py 中的模型名)。
  • 可扩展性 :在 tools/ 下新增工具文件并注册到 agent.py,Agent 立即可用,无需修改其他代码。

7. 扩展思路(不改变功能,仅作提示)

虽然本 Demo 只包含一个天气工具,但架构已经为扩展做好准备:

  • 添加新工具 :在 tools/ 下新建文件,定义任意函数,然后在 agent.pytools 列表中追加即可。
  • 替换真实 API :只需修改 weather.py 的内部实现,调用和风或 OpenWeather 的 HTTP 接口,其余代码完全不变。
  • 调整 Agent 行为 :修改 system_prompt 可以改变助手的语气、能力范围。
  • 部署为 Web 服务 :新建 api.py,导入 agent 对象,用 FastAPI 封装一个 POST 接口即可上线。

提示:若运行时遇到任何问题,请检查:

  • .env 中的 DEEPSEEK_API_KEY 是否正确
  • 网络是否能访问 api.siliconflow.cn
  • 依赖是否安装完整(pip list 确认 langchain 版本 ≥ 1.2.0)
相关推荐
小满zs2 小时前
Next.js精通SEO第四章(JSON-LD + web vitals)
前端·seo·next.js
云水一下10 小时前
从零开始!VMware安装Fedora Workstation 44桌面系统完整教程
前端
wuminyu11 小时前
专家视角看Java字节码加载与存储指令机制
java·linux·c语言·jvm·c++
小码哥_常11 小时前
安卓黑科技:实现多平台商品详情页一键跳转APP
前端
killerbasd11 小时前
还是迷茫 5.3
前端·react.js·前端框架
不会敲代码112 小时前
TCP/IP 与前端性能:从数据包到首次渲染的底层逻辑
前端·tcp/ip
kyriewen12 小时前
奥特曼借GPT-5.5干杯,而你的Copilot正按Token收钱
前端·github·openai
callJJ12 小时前
Spring Data Redis 两种编程模型详解:同步 vs 响应式
java·spring boot·redis·python·spring
AC赳赳老秦12 小时前
投标合规提效:用 OpenClaw 实现标书 / 合同自动审核、关键词校验、格式优化,降低废标风险
开发语言·前端·python·eclipse·emacs·deepseek·openclaw