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. 架构总览

下面用一张图总结这两天项目的整体架构:

用户输入

FastAPI 入口

意图路由 Agent

是否需要工具?

工具注册表

查询用户/订单

回传结果给 LLM

生成结构化工单

返回 TicketResponse

5. 总结与下一步

第五十七天到第五十八天,我从「会写 Agent 代码」进阶到「能交付一个完整的 Agent 服务」。核心收获有三点:

  • 整合能力:把 LLM 调用、工具注册、记忆、路由串成一条完整链路。
  • 工程意识:配置管理、日志、重试、错误处理,是生产级 Agent 和 Demo 的分水岭。
  • 表达输出:能讲清楚架构设计、能回答高频面试题、能写出有说服力的 README。

下一步计划:

  • 为项目补充向量记忆,支持跨会话长期记忆。
  • 增加 2~3 个真实业务工具(如查库存、查物流)。
  • 用 LangSmith 或自建评测集,量化 Agent 的工具调用准确率。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐