从零开始:前端转型 AI Agent 直到就业——第五十七天至第五十八天
1. 引言
不知不觉,转型之路已经走到了第五十七天和第五十八天。这两天的核心任务,是把前面学到的 Agent 编排、工具调用、记忆管理等能力,真正整合到一个完整的项目里,并完成一次接近真实工作场景的交付演练。
2. 第五十七天:Agent 项目整合实战
2.1 今日目标
- 将前几周积累的组件(LLM 调用、工具注册、记忆模块、路由逻辑)整合为一个可运行的 Agent 服务。
- 补齐工程化短板:配置管理、日志、错误处理。
- 完成一次端到端的功能验证。
2.2 项目结构设计
这两天我选择了一个贴近业务场景的选题:智能客服工单分类与摘要 Agent。输入一段用户反馈,Agent 自动完成意图识别、工单分类、紧急程度判断,并生成摘要。
agent-service/
├── app/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置管理
│ ├── agent/
│ │ ├── router.py # 意图路由
│ │ ├── tools.py # 工具注册
│ │ └── memory.py # 会话记忆
│ ├── llm/
│ │ └── client.py # LLM 封装
│ └── schemas/
│ └── ticket.py # 数据模型
├── tests/
│ └── test_agent.py
└── requirements.txt
2.3 核心代码:Agent 路由与工具调用
# app/agent/router.py
from typing import Literal
from pydantic import BaseModel, Field
class TicketIntent(BaseModel):
"""工单意图识别结果"""
category: Literal["bug", "feature", "billing", "other"] = Field(
description="工单分类"
)
urgency: Literal["low", "medium", "high"] = Field(
description="紧急程度"
)
summary: str = Field(description="一句话摘要")
def route_intent(user_input: str, llm_client) -> TicketIntent:
"""将用户输入路由为结构化工单信息"""
prompt = f"""
你是一名客服工单分析助手。请分析以下用户反馈,输出分类、紧急程度和摘要。
用户反馈:{user_input}
请严格按照 JSON 格式输出。
"""
raw = llm_client.chat(prompt)
return TicketIntent.model_validate_json(raw)
2.4 工具注册与条件调用
# app/agent/tools.py
from typing import Callable, Dict
class ToolRegistry:
"""轻量工具注册表"""
def __init__(self):
self._tools: Dict[str, Callable] = {}
def register(self, name: str):
def decorator(func: Callable):
self._tools[name] = func
return func
return decorator
def call(self, name: str, **kwargs):
if name not in self._tools:
raise KeyError(f"工具 {name} 未注册")
return self._tools[name](**kwargs)
registry = ToolRegistry()
@registry.register("lookup_user")
def lookup_user(user_id: str) -> dict:
"""查询用户信息(模拟)"""
return {"user_id": user_id, "level": "vip", "region": "华东"}
@registry.register("check_order")
def check_order(order_id: str) -> dict:
"""查询订单状态(模拟)"""
return {"order_id": order_id, "status": "已发货", "eta": "2026-09-10"}
2.5 记忆模块:让 Agent 记住上下文
# app/agent/memory.py
from collections import deque
from dataclasses import dataclass, field
@dataclass
class ConversationMemory:
"""基于滑动窗口的会话记忆"""
max_turns: int = 6
history: deque = field(default_factory=deque)
def add(self, role: str, content: str) -> None:
self.history.append({"role": role, "content": content})
if len(self.history) > self.max_turns * 2:
self.history.popleft()
def to_messages(self) -> list:
return list(self.history)
2.6 端到端验证
# tests/test_agent.py
from app.agent.router import route_intent
from app.llm.client import LLMClient
def test_ticket_route():
client = LLMClient(model="gpt-4o-mini")
result = route_intent("我昨天买的耳机坏了,想退货", client)
assert result.category == "bug" or result.category == "billing"
assert result.urgency in ("low", "medium", "high")
assert len(result.summary) > 0
3. 第五十八天:工程化打磨与面试演练
3.1 今日目标
- 为 Agent 服务补齐日志、错误处理与配置管理。
- 编写 README 与架构说明,形成可展示的作品集。
- 模拟面试问答,梳理 Agent 相关的高频考点。
3.2 配置管理与环境隔离
# app/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""应用配置,支持 .env 覆盖"""
app_name: str = "ticket-agent"
model_name: str = "gpt-4o-mini"
temperature: float = 0.2
max_tokens: int = 1024
log_level: str = "INFO"
class Config:
env_file = ".env"
settings = Settings()
3.3 错误处理与重试机制
# app/llm/client.py
import logging
import time
from tenacity import retry, stop_after_attempt, wait_exponential
logger = logging.getLogger(__name__)
class LLMClient:
"""带重试与日志的 LLM 客户端封装"""
def __init__(self, model: str, temperature: float = 0.2):
self.model = model
self.temperature = temperature
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=10),
reraise=True,
)
def chat(self, prompt: str) -> str:
# 这里替换为真实 LLM 调用
logger.info("calling LLM, prompt length=%d", len(prompt))
# 模拟网络抖动
if time.time() % 5 < 0.5:
raise ConnectionError("simulated network error")
return '{"category": "bug", "urgency": "medium", "summary": "耳机故障申请退货"}'
3.4 FastAPI 服务入口
# app/main.py
import logging
from fastapi import FastAPI, HTTPException
from app.agent.router import route_intent
from app.agent.tools import registry
from app.llm.client import LLMClient
from app.schemas.ticket import TicketRequest, TicketResponse
logging.basicConfig(level=logging.INFO)
app = FastAPI(title="Ticket Agent")
llm = LLMClient(model="gpt-4o-mini")
@app.post("/api/ticket/analyze", response_model=TicketResponse)
def analyze_ticket(req: TicketRequest):
try:
intent = route_intent(req.content, llm)
# 按需调用工具
if req.user_id:
user = registry.call("lookup_user", user_id=req.user_id)
intent.summary += f"(用户等级:{user['level']})"
return TicketResponse(**intent.model_dump())
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc))
3.5 面试高频考点梳理
这两天我整理了 Agent 方向面试最常被问到的几个问题,并准备了回答思路:
Q1:什么是 Agent?和普通 LLM 调用有什么区别?
普通 LLM 调用是「单轮问答」,模型只根据 prompt 输出文本;Agent 则是在 LLM 之上增加了规划、工具调用、记忆、反思等能力,能够自主拆解任务、调用外部工具并迭代执行,直到完成目标。
Q2:如何设计工具调用(Function Calling)?
核心是「声明式工具描述 + 结构化参数校验」。先用 JSON Schema 描述每个工具的名称、参数和用途,LLM 根据用户意图选择工具并生成参数,代码侧用 Pydantic 校验后执行,最后把结果回传给模型继续推理。
Q3:Agent 的记忆怎么实现?
常用方案有三种:滑动窗口(只保留最近 N 轮)、摘要压缩(把早期对话总结成摘要)、向量检索(把历史存入向量数据库,按相关性召回)。实际项目中通常组合使用。
Q4:如何评估一个 Agent 的效果?
从三个维度:任务完成率(是否达成目标)、工具调用准确率(是否选对工具、参数是否正确)、成本与延迟(token 消耗和响应时间)。线上可用 A/B 测试,线下可构建评测集。
3.6 作品集 README 要点
为了让项目在简历和面试中更有说服力,我整理了 README 的核心结构:
# Ticket Agent:智能工单分类与摘要
## 项目简介
基于 LLM + Function Calling 的智能客服工单处理 Agent,
自动完成意图识别、分类、紧急度判断与摘要生成。
## 技术栈
- Python 3.11 / FastAPI
- OpenAI-compatible LLM API
- Pydantic v2 / Pydantic-Settings
- Tenacity(重试)/ Logging
## 核心能力
- 意图路由:将自由文本转为结构化工单
- 工具调用:按需查询用户信息、订单状态
- 会话记忆:滑动窗口上下文管理
- 工程化:配置隔离、日志、重试、错误处理
## 快速开始
(安装依赖、配置 .env、启动服务、调用示例)
## 架构图
(Mermaid 流程图)
4. 架构总览
下面用一张图总结这两天项目的整体架构:
5. 总结与下一步
第五十七天到第五十八天,我从「会写 Agent 代码」进阶到「能交付一个完整的 Agent 服务」。核心收获有三点:
- 整合能力:把 LLM 调用、工具注册、记忆、路由串成一条完整链路。
- 工程意识:配置管理、日志、重试、错误处理,是生产级 Agent 和 Demo 的分水岭。
- 表达输出:能讲清楚架构设计、能回答高频面试题、能写出有说服力的 README。
下一步计划:
- 为项目补充向量记忆,支持跨会话长期记忆。
- 增加 2~3 个真实业务工具(如查库存、查物流)。
- 用 LangSmith 或自建评测集,量化 Agent 的工具调用准确率。
更多推荐


所有评论(0)