跳到主要内容

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,换语言不换结构。

设计取舍(面试可讲)​

  1. 假 LLM:先证明编排正确,再换真模型,避免 key/账单挡住学习
  2. 最大步数:硬终止优先于「智能停止」
  3. 工具面极窄:演示加法即可,多工具放到下一篇

实践要点​

  1. 先跑通循环与轨迹,再换真 LLM。
  2. 验收看:工具是否被调用、能否终止、日志是否可读。
  3. 面试挂钩:这就是 Orchestrator + Tool Registry 的最小实现。
  4. 下一步:用状态图表达同一循环见 [LangGraph 编排实践](/docs/ai/Agent/LangGraph 编排实践);多工具 schema、失败重试见 工具调用与评测实践。