乐于分享
好东西不私藏

AI智能体开发实战:10个让新人少走弯路的经验

AI智能体开发实战:10个让新人少走弯路的经验

CAUTION

构建 AI 智能体(AI Agents)已经不是什么新鲜事了,但真正上手做过项目的人都知道:从 demo 到生产环境,中间隔着无数坑。

我见过太多团队兴致勃勃地搭起第一个 Agent,结果上线第一天就崩了——或者更隐蔽的问题是:看起来运行正常,但实际上逻辑漏洞百出,响应质量一言难尽。


这篇文章源自一个 Reddit 高赞帖 [来源1],作者是一位有实战经验的工程师,总结了 构建 AI 智能体最值得告诉新人的 10 件事。我结合自己的踩坑经历,做了进一步的展开和补充。

这不是理论文章,全是实打实的工程细节。读完你带走的,是可以直接复用的经验和代码模式。


一、先让你的第一个 Agent 跑起来,再谈优化

很多新手一上来就想要“完美的智能体”——多层规划、记忆增强、工具链编排……结果代码写了一周,Agent 还是调不通。

核心建议:从最简单的单 Agent 开始。

## 最基础的 Agent 骨架(可直接运行)from langchain.agents import AgentExecutor, create_react_docstore_agentfrom langchain_openai import ChatOpenAIfrom langchain_community.tools import WikipediaQueryRun, WikipediaAPIWrapper## 1. 定义工具tools = [WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())]## 2. 创建 Agentllm = ChatOpenAI(model="gpt-4", temperature=0)agent = create_react_docstore_agent(llm, tools)## 3. 执行executor = AgentExecutor(agent=agent, tools=tools)result = executor.invoke({"input": "谁是爱因斯坦?"})print(result["output"])

这个 Agent 能做什么?接收问题 → 调用 Wikipedia 查询 → 返回答案。就这么简单。

TIP

先把"问题→工具→答案"这条路跑通,再加复杂逻辑。


二、工具调用(Tool Calling)是核心,别轻视

Agent 的能力边界,很大程度上由它能调用多少工具决定。但工具调用本身就有很多坑。

2.1 工具描述要清晰

工具的描述(description)是 LLM 判断"什么时候该调用"的依据。描述模糊,Agent 就会乱调用。

## ❌ 错误示例:描述太模糊tools = [    {"name": "search", "description": "搜索工具", "parameters": {...}}]## ✅ 正确示例:描述清楚输入输出和适用场景tools = [    {        "name": "search_code",        "description": "在代码库中搜索函数或变量定义。输入是自然语言查询,返回匹配的文件路径和行号。适用于:找某个功能在哪里实现。",        "parameters": {            "type": "object",            "properties": {                "query": {                    "type": "string",                    "description": "要搜索的关键词,如函数名、变量名、或功能描述"                }            },            "required": ["query"]        }    }]

2.2 工具返回要结构化

Agent 解析工具返回结果的能力有限,返回内容太乱会导致后续步骤出错。

## ❌ 返回一坨无结构文本def search_code(query):    results = do_search(query)    return str(results)  # 大概率出错## ✅ 返回结构化信息,让 Agent 容易理解def search_code(query):    results = do_search(query)    return json.dumps({        "count": len(results),        "files": [{"path": r.path, "line": r.line, "preview": r.preview}                   for r in results]    }, ensure_ascii=False)


三、记忆管理:别让 Agent "失忆"

Agent 处理长对话时,经常"忘记"之前说过什么。这是因为 LLM 有上下文窗口限制,也因为你没有设计好记忆机制。

3.1 短期记忆:保留最近 N 轮对话

from collections import dequeclass ConversationBuffer:    def __init__(self, max_turns=10):        self.buffer = deque(maxlen=max_turns)  # 只保留最近10轮    def add(self, role, content):        self.buffer.append({"role": role, "content": content})    def get_history(self):        return list(self.buffer)    def clear(self):        self.buffer.clear()## 使用示例memory = ConversationBuffer(max_turns=10)memory.add("user", "帮我查下北京今天的天气")memory.add("assistant", "今天北京晴,气温 15-25 度")memory.add("user", "那上海呢?")## Agent 可以看到前两轮,但更早的会被自动清除

3.2 长期记忆:摘要+向量检索

简单对话用 buffer 够用,但涉及大量历史信息时,需要更复杂的记忆策略:

from langchain.retrievers import VectorStoreRetrieverfrom langchain.text_splitter import CharacterTextSplitterclass AgentMemory:    def __init__(self):        self.short_term = []  # 最近对话        self.summaries = []   # 摘要归档        self.vector_store = None    def add_interaction(self, user_input, assistant_output):        self.short_term.append({            "user": user_input,            "assistant": assistant_output        })        # 超过阈值时,生成摘要并存入长期记忆        if len(self.short_term) > 5:            summary = self._generate_summary(self.short_term)            self.summaries.append(summary)            self.short_term = []    def get_context(self, current_query):        # 检索相关记忆片段        relevant = self.vector_store.similarity_search(current_query, k=3)        return "\n".join([s.content for s in relevant])


四、错误处理:Agent 犯错时怎么办

Agent 调用工具时,失败是常态。你需要提前设计好容错策略。

WARNING

上线前必须设计好容错策略,否则 Agent 出错时就是"裸奔"状态。

4.1 重试机制

import timefrom functools import wrapsdef retry_on_failure(max_attempts=3, delay=1.0):    def decorator(func):        @wraps(func)        def wrapper(*args, **kwargs):            for attempt in range(max_attempts):                try:                    return func(*args, **kwargs)                except Exception as e:                    if attempt == max_attempts - 1:                        raise                    time.sleep(delay * (attempt + 1))  # 指数退避        return wrapper    return decorator## 使用@retry_on_failure(max_attempts=3)def call_api(tool_name, params):    # API 调用逻辑    pass

4.2 优雅降级

def execute_with_fallback(tool_name, params, fallback_result="无法完成该操作"):    try:        result = call_tool(tool_name, params)        return {"status": "success", "data": result}    except ToolNotFoundError:        return {"status": "fallback", "message": "工具不可用,请尝试其他方式"}    except RateLimitError:        time.sleep(5)        return execute_with_fallback(tool_name, params)  # 递归重试    except Exception as e:        return {"status": "error", "message": fallback_result}


五、评估测试:别只靠"感觉"

开发 Agent 最容易犯的错误:用几个例子测了测,感觉 OK,就上线了。结果上线后用户说什么它都听不懂。

5.1 建立评估数据集

## 评估数据集示例EVAL_DATASET = [    {        "input": "帮我把这份报告翻译成英文",        "expected_tools": ["document_loader", "translator"],        "expected_keywords": ["翻译", "英文"]    },    {        "input": "今天周三,提醒我下午三点开会",        "expected_tools": ["calendar_check", "reminder_set"],        "expected_keywords": ["周三", "下午三点", "开会"]    },    # ... 至少准备 30-50 条,覆盖主要场景]def evaluate_agent(agent, dataset):    results = []    for case in dataset:        response = agent.run(case["input"])        score = calculate_similarity(response, case["expected"])        results.append({            "input": case["input"],            "score": score,            "passed": score > 0.7        })    # 输出统计    passed = sum(1 for r in results if r["passed"])    print(f"通过率: {passed}/{len(results)} = {passed/len(results)*100:.1f}%")    return results

5.2 关键指标

NOTE

评估 Agent 时需要关注的核心指标:

• 工具调用准确率:Agent 是否在正确时机调用正确工具

• 任务完成率:用户意图是否被满足

• 响应延迟:P95 延迟是否在可接受范围(一般 < 5s)

• 成本控制:每次任务消耗的 token 数


六、成本控制:LLM 调用很贵

很多团队做 demo 时忽略了成本,上线后收到账单才发现:一天烧了几百块。

6.1 善用小模型

不是所有任务都需要 GPT-4。

def route_to_model(task_type, query):    # 简单查询用小模型,省钱    if task_type == "simple_qa":        return ChatOpenAI(model="gpt-3.5-turbo")    # 复杂推理用大模型    elif task_type == "complex_reasoning":        return ChatOpenAI(model="gpt-4")    # 批量处理用更便宜的    elif task_type == "batch_summary":        return ChatOpenAI(model="gpt-3.5-turbo-16k")def classify_task(query):    # 用小模型做分类,决定用什么模型处理    classifier = ChatOpenAI(model="gpt-3.5-turbo")    classification_prompt = f"""判断以下查询的复杂度:    - simple: 简单问答,不需要推理    - complex: 需要多步推理或复杂理解    查询:{query}"""    result = classifier.invoke(classification_prompt)    return "simple" if "simple" in result.content else "complex"

6.2 缓存重复请求

from functools import lru_cache@lru_cache(maxsize=1000)def cached_llm_call(prompt_hash, model):    # 相同语义的问题,命中缓存直接返回    # 需要配合语义缓存,不能只靠字符串 hash    pass## 更精确的语义缓存from langchain.cache import SemanticCachefrom langchain.embeddings import OpenAIEmbeddingsSemanticCache.from_llm(    llm=ChatOpenAI(model="gpt-3.5-turbo"),    embedding=OpenAIEmbeddings())


七、迭代优化:从 MVP 到生产

构建 Agent 不是一蹴而就的,需要分阶段迭代。

阶段
周期
核心目标
MVP
1-2 周
核心流程跑通,覆盖 80% 常见场景
能力扩展
2-4 周
增加工具,优化调用准确率
稳定性提升
4-8 周
完善错误处理,性能优化
生产上线
-
监控告警,持续评估,快速回滚

八、这些坑,你可能会遇到

坑 1:工具调用死循环

Agent 反复调用同一个工具,拿到的结果相似但不满足,然后继续调用……

解决:设置最大调用次数,超限后强制返回或转人工。

executor = AgentExecutor(    agent=agent,     tools=tools,     max_iterations=10,  # 最多调用 10 次工具    max_execution_time=30  # 或最多执行 30 秒)

坑 2:Prompt 注入

恶意用户试图通过 Prompt 注入让 Agent 执行未授权操作。

解决:在工具层做权限校验,不要完全信任 LLM 的输出。

def execute_tool(tool_name, params, user_id):    # 检查用户权限    if not has_permission(user_id, tool_name):        return {"error": "权限不足"}    # 参数校验    if not validate_params(params, tool_name):        return {"error": "参数格式错误"}    return actual_execute(tool_name, params)

坑 3:上下文溢出

长对话导致 token 超限,Agent "失忆"。

解决:定期总结 + 限制上下文长度。


九、总结:核心 Takeaway

1. 从简单开始:先跑通最小闭环,不要一开始就设计复杂架构

2. 工具描述决定上限:工具是 Agent 能力的边界,描述要清晰、结构化

3. 记忆要有层次:短期 + 摘要 + 长期,按需选择

4. 错误处理是底线:重试 + 降级 + 监控,上线必备

5. 评估驱动迭代:没有量化评估,就没有优化方向

6. 成本要可控:小任务用小模型,做好缓存

7. 迭代是常态:MVP → 扩展 → 稳定 → 上线

IMPORTANT

构建 AI 智能体,本质是构建一个"会犯错但能快速纠正"的系统。不要追求一步到位,要追求持续优化。


十、参考资料

[来源1] Reddit - r/AI_Agents: "10 things I'd tell anyone starting to build AI agents" (来源)