Agent 最小可运行项目
目标:用假 LLM + 本地工具跑通「规划→调工具→观察→回答」循环,不依赖付费 API。读完应能向面试官画清目录与终止条件。概念见 Agent 核心概念与架构。
目标与验收
| 验收项 | 标准 |
|---|---|
| 能调工具 | 用户问「3+5」时走到计算器工具 |
| 有轨迹 | 打印每步:thought / tool / result |
| 能终止 | 最大步数或得到最终答案后停止 |
| 可讲解 | 说清为何不需要真实模型也能演示闭环 |
建议目录
mini_agent/
main.py # 循环入口
tools.py # 工具注册
fake_llm.py # 规则/关键字「假模型」
README.md # 怎么跑
工具(最小)
# tools.py
def add(a: float, b: float) -> float:
return a + b
TOOLS = {
"add": {
"fn": add,
"schema": {"a": "number", "b": "number"},
"desc": "两数相加",
}
}
def call_tool(name: str, args: dict):
if name not in TOOLS:
raise ValueError(f"unknown tool: {name}")
return TOOLS[name]["fn"](**args)
假 LLM(演示闭环)
真实项目里把这里换成 API;面试演示用规则足够:
# fake_llm.py
import re
def decide(user: str, last_obs: str | None):
if last_obs is not None:
return {"type": "final", "content": f"结果是 {last_obs}"}
m = re.search(r"(-?\d+)\s*\+\s*(-?\d+)", user)
if m:
return {
"type": "tool",
"name": "add",
"args": {"a": float(m.group(1)), "b": float(m.group(2))},
}
return {"type": "final", "content": "我只会两数相加,请换问题。"}
主循环
# main.py
from fake_llm import decide
from tools import call_tool
def run(user: str, max_steps: int = 5):
obs = None
for step in range(max_steps):
decision = decide(user, obs)
print(f"step={step} decision={decision}")
if decision["type"] == "final":
return decision["content"]
obs = str(call_tool(decision["name"], decision["args"]))
return "达到最大步数,中止"
if __name__ == "__main__":
print(run("帮我算 3+5"))
运行:python main.py,应看到一步 tool、一步 final。
TypeScript 对照直觉:同样是 decide → callTool → loop,换语言不换结构。
设计取舍(面试可讲)
- 假 LLM:先证明编排正确,再换真模型,避免 key/账单挡住学习
- 最大步数:硬终止优先于「智能停止」
- 工具面极窄:演示加法即可,多工具放到下一篇
实践要点
- 先跑通循环与轨迹,再换真 LLM。
- 验收看:工具是否被调用、能否终止、日志是否可读。
- 面试挂钩:这就是 Orchestrator + Tool Registry 的最小实现。
- 下一步:用状态图表达同一循环见 [LangGraph 编排实践](/docs/ai/Agent/LangGraph 编排实践);多工具 schema、失败重试见 工具调用与评测实践。