大模型与Agent智能体开发实战

智能体开发实战:从"玩具"到"生产力工具"的全流程拆解

一、引言:智能体不是"对话机器人"的升级版

在技术圈,"智能体(Agent)"正被过度消费------仿佛给LLM套上System Prompt、让它能调几个API,就摇身一变成了智能体。但在真正的开发实战中,智能体是一个能够自主感知环境、制定计划、执行动作并从反馈中持续优化的闭环系统。它不仅要"理解"用户意图,更要在复杂的数字世界中独立完成多步任务,比如自动整理邮箱、撰写周报并发送、或者根据股票行情自动调仓。

本文将带你从需求分析→架构设计→核心编码→测试调优→生产部署全流程走一遍,用少量核心代码展示智能体开发的"骨架",让你亲手搭建一个可运行的轻量级智能体,并理解其背后的工程权衡。


二、实战目标:我们要构建什么样的智能体?

为了聚焦实战,我们设定一个中等复杂度的业务场景:

智能体名称Meeting Assistant Agent(会议助手)

核心功能

  1. 读取用户的日程邮件(模拟),自动识别未安排的会议请求。
  2. 根据参会人的空闲时间(调用日历API),推荐3个备选时间段。
  3. 自动发送会议邀请邮件(含会议链接),并记录结果。
  4. 若预定失败,自动调整策略重试。

这个场景包含了感知(读邮件)、规划(选时间)、行动(发邮件)、反馈(记录结果) 四个关键环节,足够展示智能体开发的全貌。


三、架构设计:智能体的"三驾马车"

一个生产级智能体通常划分为三个核心模块,我们依此设计代码结构:

模块 职责 技术选型建议
感知模块(Perceptor) 解析用户输入、读取外部数据、识别当前状态 文本解析用LLM;结构化数据用pandas;邮件用IMAP
决策模块(Brain) 制定计划、选择工具、判断终止条件 使用ReAct模式,LLM调用 + 工具注册表
执行模块(Actuator) 调用外部API、操作GUI、发送命令 工具函数(Python函数)+ 异常重试装饰器
记忆模块(Memory) 存储对话历史、中间结果、任务状态 list + dict(内存);持久化用RedisSQLite

我们使用纯Python,避免重度依赖框架,便于理解底层逻辑。


四、Step 1:定义工具(Tools)------智能体的"手"

工具是智能体与外部世界交互的唯一方式。我们按照"输入/输出明确、可重试、有超时"的原则封装。

python 复制代码
# tools.py
import random
import smtplib
from email.mime.text import MIMEText
from typing import List, Dict, Optional
import json

# ---------- 模拟日历API ----------
def get_free_slots(user_id: str, date: str, duration_minutes: int = 30) -> List[str]:
    """
    模拟获取某个用户在指定日期的空闲时段(返回时间点列表,如["09:00", "09:30"])
    真实场景可调用Google Calendar API或Outlook REST API
    """
    # 模拟数据:不同用户有不同的忙碌时段
    mock_data = {
        "alice": ["09:00", "10:30", "11:00", "14:00", "15:30"],
        "bob":   ["09:30", "10:00", "13:00", "14:30", "16:00"],
        "carol": ["08:30", "09:30", "10:30", "11:30", "15:00"],
    }
    slots = mock_data.get(user_id, [])
    # 模拟随机失败(用于测试重试)
    if random.random() < 0.1:
        raise ConnectionError("日历服务暂时不可用")
    return slots

# ---------- 发送邮件工具 ----------
def send_email(to: str, subject: str, body: str, smtp_config: Dict) -> bool:
    """
    通过SMTP发送邮件,返回是否成功
    """
    try:
        msg = MIMEText(body, "plain", "utf-8")
        msg["Subject"] = subject
        msg["From"] = smtp_config["from"]
        msg["To"] = to
        
        with smtplib.SMTP_SSL(smtp_config["host"], smtp_config["port"]) as server:
            server.login(smtp_config["user"], smtp_config["password"])
            server.send_message(msg)
        return True
    except Exception as e:
        print(f"邮件发送失败: {e}")
        return False

# ---------- 工具注册表(统一管理) ----------
TOOL_REGISTRY = {
    "get_free_slots": {
        "func": get_free_slots,
        "description": "查询指定用户在指定日期的空闲时间段列表,输入user_id和date(YYYY-MM-DD),输出时间字符串列表。",
        "parameters": {
            "type": "object",
            "properties": {
                "user_id": {"type": "string"},
                "date": {"type": "string"},
                "duration_minutes": {"type": "integer", "default": 30}
            },
            "required": ["user_id", "date"]
        }
    },
    "send_email": {
        "func": send_email,
        "description": "发送邮件给指定收件人,需要提供主题、正文和SMTP配置。",
        "parameters": {
            "type": "object",
            "properties": {
                "to": {"type": "string"},
                "subject": {"type": "string"},
                "body": {"type": "string"},
                "smtp_config": {"type": "object"}
            },
            "required": ["to", "subject", "body"]
        }
    }
}

五、Step 2:实现感知与记忆模块

感知模块负责将用户自然语言输入转化为结构化任务,同时维护对话记忆。

python 复制代码
# memory.py
from typing import List, Dict, Any

class AgentMemory:
    """
    智能体的短期记忆,保存对话历史和工具调用结果
    """
    def __init__(self, system_prompt: str):
        self.messages: List[Dict[str, Any]] = [
            {"role": "system", "content": system_prompt}
        ]
        self.task_state: Dict[str, Any] = {}  # 存储任务中间状态,如已找到的空闲时段
    
    def add_user_message(self, content: str):
        self.messages.append({"role": "user", "content": content})
    
    def add_assistant_message(self, content: str, tool_calls: Optional[List] = None):
        msg = {"role": "assistant", "content": content}
        if tool_calls:
            msg["tool_calls"] = tool_calls
        self.messages.append(msg)
    
    def add_tool_result(self, tool_call_id: str, result: Any):
        self.messages.append({
            "role": "tool",
            "tool_call_id": tool_call_id,
            "content": json.dumps(result, ensure_ascii=False)
        })
    
    def get_context(self) -> List[Dict]:
        """返回当前上下文(含系统提示)"""
        return self.messages

六、Step 3:大脑------ReAct循环与LLM调度

这是智能体的核心,我们使用OpenAI的Function Calling(或其他支持工具调用的模型)来驱动思考和行动交替。

python 复制代码
# brain.py
import json
import os
from openai import OpenAI
from tools import TOOL_REGISTRY
from memory import AgentMemory

class AgentBrain:
    def __init__(self, model="gpt-4o-mini", max_iterations=5):
        self.client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
        self.model = model
        self.max_iterations = max_iterations
        self.tools = [v["schema"] for v in TOOL_REGISTRY.values()]  # 需提前构建schema
    
    def build_tools_schema(self):
        # 将工具注册表转换为OpenAI compatible schema(可在初始化时完成)
        schemas = []
        for name, info in TOOL_REGISTRY.items():
            schemas.append({
                "type": "function",
                "function": {
                    "name": name,
                    "description": info["description"],
                    "parameters": info["parameters"]
                }
            })
        return schemas
    
    def run(self, memory: AgentMemory) -> str:
        """
        执行ReAct循环,直到模型不请求工具或达到最大迭代次数。
        返回最终答案。
        """
        tools_schema = self.build_tools_schema()
        
        for iteration in range(self.max_iterations):
            # 1. 调用LLM
            response = self.client.chat.completions.create(
                model=self.model,
                messages=memory.get_context(),
                tools=tools_schema,
                tool_choice="auto",
                temperature=0.3
            )
            
            assistant_msg = response.choices[0].message
            # 保存助手消息到记忆
            memory.messages.append({
                "role": "assistant",
                "content": assistant_msg.content or "",
                "tool_calls": assistant_msg.tool_calls
            })
            
            # 2. 判断是否需要调用工具
            if not assistant_msg.tool_calls:
                # 没有工具调用,说明已得出最终答案
                return assistant_msg.content or "任务完成。"
            
            # 3. 执行工具调用
            for tool_call in assistant_msg.tool_calls:
                tool_name = tool_call.function.name
                args = json.loads(tool_call.function.arguments)
                print(f"🔧 迭代{iteration+1}:调用工具 {tool_name},参数:{args}")
                
                # 从注册表获取函数
                tool_info = TOOL_REGISTRY.get(tool_name)
                if not tool_info:
                    result = f"未知工具:{tool_name}"
                else:
                    try:
                        func = tool_info["func"]
                        result = func(**args)
                    except Exception as e:
                        result = f"工具执行异常:{str(e)}"
                
                # 将工具结果写回记忆(作为Observation)
                memory.add_tool_result(tool_call.id, result)
                print(f"✅ 工具返回:{result}")
        
        return "智能体达到最大迭代次数,未完成全部任务。"

七、Step 4:主程序------组装并运行智能体

现在将所有模块组合起来,形成一个可交互的智能体。

python 复制代码
# main.py
import os
from memory import AgentMemory
from brain import AgentBrain

# 定义系统提示(角色设定 + 任务指引)
SYSTEM_PROMPT = """
你是一位智能会议助手,你的任务是帮助用户安排会议。
你有以下工具可用:
- get_free_slots:查询用户空闲时段
- send_email:发送会议邀请邮件

你必须按以下流程操作:
1. 从用户的请求中提取:参会人列表、期望日期、会议时长。
2. 调用 get_free_slots 查询每个参会人的空闲时段,找出交集。
3. 如果交集时段存在,选择一个最佳时段,调用 send_email 发送邀请。
4. 如果无交集,告知用户并建议更换日期。
5. 所有操作完成后,输出最终结果(成功或失败原因)。

注意:
- 如果某工具调用失败,尝试重试或调整参数。
- 不要虚构信息,所有数据必须来自工具返回。
"""

def main():
    # 初始化记忆
    memory = AgentMemory(SYSTEM_PROMPT)
    
    # 用户输入(模拟)
    user_query = """
    帮我安排一场会议,参会人有 alice, bob, carol,日期是2026-09-15,时长30分钟。
    请帮我找空闲时间并发送邀请邮件。
    """
    memory.add_user_message(user_query)
    
    # 启动大脑
    brain = AgentBrain(model="gpt-4o-mini", max_iterations=6)
    final_answer = brain.run(memory)
    
    print("\n" + "="*50)
    print("📌 最终结果:")
    print(final_answer)
    print("="*50)

if __name__ == "__main__":
    # 请确保环境变量 OPENAI_API_KEY 已配置
    main()

八、测试与调优:让智能体"不犯傻"

8.1 常见失败模式与修复

失败现象 根本原因 修复策略
工具调用参数缺失 LLM未从上下文中提取关键信息 在System Prompt中明确要求"必须从用户输入中提取XXX"
陷入死循环 连续调用同一工具且输入相同 在Brain层检测重复调用,超过2次则强制终止并提示
选择不合适的工具 工具描述不清晰 优化description字段,增加使用示例(Few-shot)
结果格式解析错误 LLM返回非预期格式 使用response_format强制JSON输出(模型支持时)

8.2 调试技巧:打印"思维链"

brain.run()循环中加入详细日志,打印每次LLM的tool_calls和工具返回值。建议使用结构化日志(JSON格式),便于后续分析。

ini 复制代码
# 在brain.py中添加
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 在工具调用前后记录日志
logger.info(json.dumps({"step": iteration, "tool": tool_name, "args": args}))

8.3 性能优化:缓存重复查询

对于高频查询(如get_free_slots),可以引入缓存层 ,减少外部API调用。用functools.lru_cache简单实现:

python 复制代码
from functools import lru_cache

@lru_cache(maxsize=128)
def get_free_slots_cached(user_id: str, date: str, duration_minutes: int = 30):
    return get_free_slots(user_id, date, duration_minutes)

九、生产环境部署要点

  1. 异步化改造 :将brain.run()改为异步async,支持并发处理多个用户请求,避免阻塞。使用asyncio.to_thread封装同步工具函数。
  2. 状态持久化 :将AgentMemory序列化到Redis,实现智能体状态的恢复(断点续跑)。在长时间运行的任务中尤其重要。
  3. 工具限流与超时:为每个工具调用设置超时(如5秒),超时后返回"工具不可用"并触发降级逻辑。
  4. 安全护栏 :严格限制工具的使用范围(如不能执行系统命令、不能访问任意URL)。使用pydantic对参数做类型校验。
  5. 可观测性:接入OpenTelemetry,记录每次LLM调用的Token消耗、延迟和工具调用链,便于成本归因。

十、扩展思考:多智能体协作

如果任务过于复杂(如涉及多个角色),可以将当前单体智能体拆分为多个专职智能体(例如"日程规划师"、"邮件撰写师"、"会议链接生成师"),通过消息总线协调。这种多智能体系统(MAS) 能提升专精度和容错性。


十一、结语:智能体开发是"驯服"而非"创造"

智能体开发的本质,不是创造一个有"意识"的数字生命,而是用工程手段将LLM的通用推理能力约束在安全、可预测的业务边界内。你不需要完美地预测每一步,而是设计好"当意外发生时,系统能优雅降级"。

本文从零构建的会议助手,虽然简陋,却涵盖了智能体的核心骨架。你可以在此基础上,逐步添加更多工具(如Slack通知、文档搜索)、更复杂的记忆机制(向量记忆)、以及更精细的Prompt工程,将其打磨成能真正为团队提效的生产级工具。

记住:智能体的上限,取决于你定义工具的精准度和对LLM行为边界的管理能力。从今天开始,为你手头的业务设计一个智能体原型吧------你会发现,让代码学会"自主行动",是比堆砌算法更令人兴奋的挑战。


(本文代码基于 Python 3.10+、OpenAI SDK 1.0+,完整代码可在整合后直接运行。生产环境请根据实际API替换模拟函数。)

相关推荐
尘中远18 分钟前
7大开源Agent源码对比解读——架构对比
ai·开源·agent·codex·harness
潘锦38 分钟前
Session First 和 Agent First,本身并没有高低之分
agent
张忠琳2 小时前
【deepseek-harness】Cordis 时空可组合性编程范式 — 三段式精读笔记(二)
ai·agent·deepseek·harness·cordis·dsh
小沈同学呀3 小时前
【Agent开发第七期】记忆系统:让 Agent 跨会话也记得你
人工智能·agent·长期记忆·记忆系统
哥不是小萝莉3 小时前
AI 编码 Agent 从原理到可运行代码
ai·agent
新知图书4 小时前
16.3 基于MCP的多Agent旅行规划助手项目结构
人工智能·agent·ai agent·智能体
似水流年QC5 小时前
什么是 Skill?深入理解 AI Agent Skill 的工作原理与应用实践
人工智能·agent·skill
水管在开花.5 小时前
Agent范式与LangGraph④-零基础保姆级教程
人工智能·agent·rag