设计目标 :通过渐进式实战,亲手构建具备工具调用能力的 Agent,掌握从零到一的完整开发流程,建立"可调试、可扩展、安全可靠"的工程化思维。所有代码均适配 Linux 环境
3.1 环境初始化(5 分钟快速就绪)
bash
# 激活模块一配置的环境
source ~/agent-env/bin/activate
# 安装精准版本依赖(避免 LangChain 大版本变动导致示例失效)
pip install "langchain==0.1.16" "langchain-community==0.0.34" \
"langchain-core==0.1.46" "requests==2.31.0" \
"python-dotenv==1.0.0" "tqdm==4.66.1"
# 创建标准项目结构
mkdir -p my-first-agent/{tools,agents,config,logs}
cd my-first-agent
touch __init__.py tools/__init__.py agents/__init__.py .env .gitignore requirements.txt
.env 安全模板
bash
# LLM 配置(三选一)
OPENAI_API_KEY=sk-...
# ANTHROPIC_API_KEY=sk-...
# LOCAL_MODEL_ENDPOINT=http://localhost:11434/api/generate # Ollama
# 安全沙箱配置
ALLOWED_LINUX_COMMANDS=ls,pwd,cat,df,du
COMMAND_TIMEOUT=5
3.2 核心实战:三阶段渐进式开发
🌱 实战学习一:基础 ReAct Agent(天气查询助手)
tools/weather_tool.py:
python
import requests
from langchain.tools import Tool
from dotenv import load_dotenv
import os
load_dotenv()
def get_weather(city: str) -> str:
"""
安全封装天气查询(模拟 API,实际项目替换为真实服务)
安全设计:城市名校验 + 超时控制 + 错误隔离
"""
# 白名单校验(防 Prompt Injection)
allowed_cities = ["beijing", "shanghai", "guangzhou", "shenzhen", "hangzhou"]
city_clean = city.strip().lower()
if city_clean not in allowed_cities:
return f"❌ 仅支持查询: {', '.join(allowed_cities)}。您输入了: {city}"
try:
# 实际项目替换为和风天气/彩云天气 API
# 此处用 mock 数据避免依赖外部服务
mock_data = {
"beijing": "🌤️ 北京: 晴, 28°C, 微风",
"shanghai": "🌧️ 上海: 小雨, 26°C, 东南风3级",
"guangzhou": "⛈️ 广州: 雷阵雨, 31°C, 南风2级"
}
return mock_data.get(city_clean, f"🌤️ {city_clean.capitalize()}: 晴, 25°C")
except Exception as e:
return f"⚠️ 天气服务异常: {str(e)[:50]}"
# 注册为 LangChain Tool
weather_tool = Tool(
name="get_weather",
func=get_weather,
description=(
"查询中国主要城市的实时天气。"
"参数: 城市英文名(小写,如 beijing)。"
"注意: 仅支持 beijing/shanghai/guangzhou/shenzhen/hangzhou"
)
)
agents/weather_agent.py:
python
from langchain.agents import create_react_agent, AgentExecutor
from langchain.prompts import PromptTemplate
from langchain_community.llms import Ollama # 本地模型,无需网络
from tools.weather_tool import weather_tool
import logging
# 配置日志(Linux 工程师熟悉的方式)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s | %(levelname)s | %(message)s',
handlers=[
logging.FileHandler("logs/agent.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
def create_weather_agent():
# 1. 选择本地模型(适配 Linux 环境)
llm = Ollama(
model="qwen:7b", # 需提前 ollama pull qwen:7b
temperature=0.3, # 降低随机性,提升工具调用稳定性
timeout=120
)
# 2. 定制 ReAct Prompt(关键!注入领域知识)
template = """你是一个严谨的天气查询助手,严格遵守以下规则:
1. 用户问天气时,必须调用 get_weather 工具
2. 城市名必须转为小写英文(如"北京"→"beijing")
3. 若工具返回错误,明确告知用户限制范围
4. 最终回答需包含emoji和实用建议(如"适合带伞")
工具描述:
{tools}
使用以下格式:
Question: 用户问题
Thought: 分析需求
Action: 工具名 参数
Observation: 工具返回
...(可重复)
Final Answer: 清晰结论
当前问题: {input}
{agent_scratchpad}"""
prompt = PromptTemplate.from_template(template)
# 3. 创建 Agent
agent = create_react_agent(llm, [weather_tool], prompt)
executor = AgentExecutor(
agent=agent,
tools=[weather_tool],
verbose=True, # 关键:输出思考过程
handle_parsing_errors=True, # 防止 LLM 格式错误崩溃
max_iterations=5 # 防止无限循环
)
logger.info("✅ Weather Agent 初始化成功")
return executor
# CLI 入口(Linux 工程师熟悉的交互方式)
if __name__ == "__main__":
agent = create_weather_agent()
print("🌤️ 天气助手已启动 (输入 'quit' 退出)")
print("-" * 50)
while True:
try:
user_input = input("\n👤 你的问题: ").strip()
if user_input.lower() in ["quit", "exit"]:
break
if not user_input:
continue
result = agent.invoke({"input": user_input})
print(f"\n🤖 助手: {result['output']}")
except KeyboardInterrupt:
print("\n⚠️ 用户中断")
break
except Exception as e:
logger.error(f"Agent 执行异常: {e}")
print(f"❌ 系统错误: {str(e)[:100]}")
print("\n👋 感谢使用!日志已保存至 logs/agent.log")
运行验证:
bash
cd my-first-agent
python agents/weather_agent.py
# 输入: "上海明天天气如何?"
# 预期输出: 🌧️ 上海: 小雨, 26°C, 东南风3级 → 建议携带雨具