2026-07-28 | LangChain 学习 Day 1
前言
一直想系统学习 LangChain,今天终于动手写了第一个 Demo。目标很简单:让本地运行的 AI 模型能查询真实天气数据并回答用户问题。
最终效果:我问”合肥明天天气怎么样?”,Agent 自动调用和风天气 API 获取实时数据,然后用自然语言回答我——和我手机天气 App 显示的数据完全一致。
技术选型
| 组件 | 选择 | 原因 |
|---|---|---|
| Agent 框架 | LangChain 1.3(最新) | 官方主推 create_agent,API 极简 |
| 本地模型 | Ollama + qwen2.5:7b | 免费、本地运行、支持工具调用 |
| 天气数据 | 和风天气 API | 中国气象局数据源,国内城市精准 |
| 配置管理 | python-dotenv | 密钥不硬编码,安全规范 |
架构原理
整个流程只有 4 步:
用户提问 → 模型决策(要不要调工具?调哪个?传什么参数?)→ 执行工具 → 模型整合回答
用 LangChain 的话说,这就是一个 ReAct Agent:Reasoning + Acting 循环。
┌─────────────┐
│ 用户提问 │ "合肥明天天气怎么样?"
└──────┬──────┘
▼
┌─────────────────────────────────┐
│ LLM (qwen2.5:7b) │
│ 思考:需要调用 get_weather 工具 │
│ 决策:city = "合肥" │
└────────────────────────────────┘
▼
┌─────────────────────────────────┐
│ 工具执行:get_weather("合肥") │
│ → 请求和风天气 API │
│ → 返回:晴 25~33°C 南风3-4级 │
└──────┬──────────────────────────┘
▼
┌─────────────────────────────────┐
│ LLM 整合数据,生成自然语言回答 │
│ "明天合肥晴天,25到33度..." │
└─────────────────────────────────┘
完整代码
# pip install -qU langchain langchain-ollama requests python-dotenv
import os
import requests
from dotenv import load_dotenv
from langchain.agents import create_agent
load_dotenv() # 从 .env 文件加载环境变量
# ===== 和风天气配置(从 .env 读取) =====
QWEATHER_HOST = os.getenv("QWEATHER_HOST", "")
QWEATHER_KEY = os.getenv("QWEATHER_KEY", "")
# 城市经纬度映射(常用城市)
CITY_COORDS = {
"合肥": "117.27,31.86",
"北京": "116.41,39.92",
"上海": "121.47,31.23",
"广州": "113.26,23.13",
"深圳": "114.06,22.54",
"杭州": "120.15,30.28",
"南京": "118.78,32.06",
"武汉": "114.31,30.52",
"成都": "104.07,30.67",
"重庆": "106.55,29.56",
}
def get_weather(city: str) -> str:
"""查询指定城市的真实天气预报,包括明天天气。city参数传入中文城市名,如 合肥、北京、上海"""
try:
coords = CITY_COORDS.get(city)
if not coords:
geo_url = f"{QWEATHER_HOST}/v2/city/lookup?location={city}&key={QWEATHER_KEY}"
geo_resp = requests.get(geo_url, timeout=10)
geo_data = geo_resp.json()
if geo_data.get("code") != "200" or not geo_data.get("location"):
return f"未找到城市: {city}"
loc = geo_data["location"][0]
coords = f"{loc['lon']},{loc['lat']}"
city = loc.get("name", city)
url = f"{QWEATHER_HOST}/v7/weather/3d?location={coords}&key={QWEATHER_KEY}"
resp = requests.get(url, timeout=10)
data = resp.json()
if data.get("code") != "200":
return f"查询失败,错误码: {data.get('code')}"
today = data["daily"][0]
today_info = (f"今天({today['fxDate']}): "
f"{today['textDay']} {today['tempMin']}~{today['tempMax']}°C, "
f"{today['windDirDay']}{today['windScaleDay']}级, "
f"湿度{today['humidity']}%")
tomorrow = data["daily"][1]
tomorrow_info = (f"明天({tomorrow['fxDate']}): "
f"{tomorrow['textDay']} {tomorrow['tempMin']}~{tomorrow['tempMax']}°C, "
f"{tomorrow['windDirDay']}{tomorrow['windScaleDay']}级, "
f"湿度{tomorrow['humidity']}%, "
f"日出{tomorrow['sunrise']} 日落{tomorrow['sunset']}")
return f"{city}天气:\n{today_info}\n{tomorrow_info}"
except Exception as e:
return f"查询失败: {e}"
agent = create_agent(
model="ollama:qwen2.5:7b",
tools=[get_weather],
system_prompt="你是一个天气助手,请用中文回答。调用工具时city参数使用中文城市名(如合肥、北京、上海)。",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "合肥明天天气怎么样?"}]}
)
print(result["messages"][-1].content_blocks)
运行结果
合肥明天的天气预计是晴天,气温在25到33摄氏度之间。
南风等级为3-4级,湿度为83%。
日出时间是早上5点25分,日落时间是晚上19点11分。
请注意防晒和补水哦!
对比手机天气 App:明天 25~33°C 晴 —— 完全一致。
踩坑记录
坑 1:项目文件夹不能叫 langchain
一开始我把项目放在 d:\code\ai-code\langchain\ 目录下,结果 from langchain.agents import create_agent 直接报 ModuleNotFoundError。
原因:Python 导入时优先查找当前目录,文件夹名 langchain 遮蔽了已安装的 langchain 包。
解决:改名为 langchain-demo。
坑 2:pip 和 python 版本不一致
系统装了 Python 3.13 和 3.14 两个版本。pip install 装到了 3.14,但 python 命令指向 3.13。
解决:永远用 python -m pip install 确保装到正确版本。
坑 3:wttr.in 国内天气不准
最初用免费的 wttr.in,合肥明天预报 24~27°C 多云/雨,实际是 25~33°C 晴,差了 6 度。
原因:wttr.in 数据源是国外气象服务,对中国城市精度很差。
解决:换和风天气 API,数据来自中国气象局,完全准确。
坑 4:和风天气需要填 API Host
注册后只填了 Key 没填 Host,导致请求发到占位符地址当然失败。
教训:和风天气有两个必填项 —— API Host(每个用户不同)和 API Key。
项目结构
langchain-demo/
├── .env # 密钥配置(不提交 Git)
├── .env.example # 配置模板
├── .gitignore
├── langchaindemo1.py # 主程序
├── LEARNING_ROADMAP.md # 学习路线 TODO
└── 我的第一个LangChain项目.md # 本文
核心收获
- LangChain 的
create_agent极简:10 行代码就能创建一个能调用工具的 Agent - 工具函数的 docstring 很重要:模型靠它理解何时调用、传什么参数
- system_prompt 引导模型行为:比如指定”用中文城市名”避免编码问题
- 数据源选择影响结果质量:国外 API 查国内天气不靠谱,选对数据源很关键
.env管理密钥是基本规范:永远不要把 Key 硬编码在代码里
下一步
按照学习路线,接下来进入阶段 2:
– 学习 Prompt Templates 和 Output Parsers
– 构建第一个 RAG 知识库问答系统
– 尝试 LangSmith 追踪调试
路还很长,但第一步已经迈出去了。

