1. 项目概述:从零构建AI智能体的核心价值

最近在GitHub上看到一个挺有意思的项目,叫 didilili/ai-agents-from-zero 。光看名字,很多朋友可能第一反应是:哦,又一个讲AI智能体的教程。但当我真正点进去,顺着作者的思路和实践代码走了一遍之后,发现它的定位非常精准,就是“从零开始”。这恰恰是当前AI应用开发领域最稀缺的一种内容。

现在市面上关于大语言模型和智能体的讨论很多,但大多集中在两个极端:要么是高度抽象的理论论文,讲智能体架构、思维链、工具使用;要么就是直接甩出一个复杂的、集成了十几个工具的成熟框架,告诉你“用这个就能造智能体”。对于大多数想入门的开发者,尤其是那些有一定编程基础,但对AI底层交互还不熟悉的朋友来说,中间存在一个巨大的断层。 from-zero 这个后缀,就明确地瞄准了这个断层。它不假设你已经精通OpenAI的API调用,不预设你理解什么是Function Calling,更不要求你一眼就能看懂那些框架里复杂的装饰器和类继承关系。它试图做的,就是握住你的手,从最基础的“如何让大模型理解你的指令并执行”开始,一步一步,像搭积木一样,把智能体的核心能力构建出来。

这个项目的核心价值,我认为在于它提供了一条 可感知、可调试、可掌控 的学习路径。当你从最简单的单次对话,演进到能让模型自动调用搜索引擎查天气,再进一步到设计一个可以持续对话、拥有记忆和规划能力的智能体时,你对整个技术栈的理解是层层递进、扎实稳固的。你不会被一个黑盒框架吓到,因为每一个组件都是你亲手组装上去的。这对于建立技术自信和解决实际问题的能力至关重要。接下来,我就结合这个项目的思路,以及我个人的一些实践,来拆解一下从零构建AI智能体的完整地图。

2. 智能体技术栈的逐层拆解

构建一个AI智能体,远不止是调用 ChatCompletion API那么简单。它是一个系统工程,我们可以将其自底向上拆解为几个清晰的层次。理解每一层的作用和实现方式,是“从零开始”的关键。

2.1 基础层:与大模型的可靠通信

这是所有工作的起点。你需要一个稳定、高效、功能完整的客户端来与大模型服务(如OpenAI GPT、Claude、国内各大模型平台)进行交互。这一层的核心诉求是 可靠性和可扩展性

首先,选择一个成熟的SDK是明智的。对于OpenAI,官方Python库 openai 是首选。但“从零开始”意味着我们不仅要会用,还要理解其背后的机制。一个最基本的对话调用,你需要处理:

  • API密钥与终结点管理 :如何安全地配置而不将密钥硬编码在代码里?通常使用环境变量。
  • 模型参数配置 temperature (创造性)、 max_tokens (输出长度)、 top_p (核采样)这些参数对输出质量有直接影响。例如,在需要稳定、可重复结果的工具调用场景, temperature 通常设为0或接近0;而在创意写作时,可以调到0.7以上。
  • 错误处理与重试 :网络超时、速率限制、服务暂时不可用……在生产环境中,健壮的错误处理机制必不可少。需要实现指数退避重试逻辑。
  • 流式输出支持 :对于需要长时间生成的内容,流式输出能极大提升用户体验。这涉及到对响应体的逐块(chunk)处理。

一个常见的误区是只关注成功的调用,而忽略了失败场景。在我的实践中,我会为这个基础通信层封装一个简单的类,集成重试、日志和简单的熔断机制,确保上层业务逻辑不被底层的网络波动干扰。

2.2 核心能力层:函数调用与工具使用

这是智能体区别于普通聊天机器人的分水岭。智能体能够根据你的指令,自动决定是否需要调用外部工具(函数),并正确解析参数、执行函数、将结果返回给模型进行下一步推理。OpenAI将其称为 Function Calling ,其他模型也有类似概念如 Tool Use

关键实现步骤:

  1. 定义工具(函数) :用清晰的JSON Schema描述你的函数。这包括函数名、描述、参数列表及其类型、是否必需等。描述至关重要,它是模型决定是否调用以及如何调用该函数的依据。
    {
      "type": "function",
      "function": {
        "name": "get_current_weather",
        "description": "获取指定城市的当前天气情况",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "城市名称,例如:北京,上海"
            },
            "unit": {
              "type": "string",
              "enum": ["celsius", "fahrenheit"],
              "description": "温度单位"
            }
          },
          "required": ["location"]
        }
      }
    }
    
  2. 对话并请求函数调用 :在调用Chat API时,将定义好的工具列表传入 tools 参数。模型在分析用户输入后,如果认为需要调用工具,会在响应中返回一个 tool_calls 字段,其中包含它想要调用的函数名和参数。
  3. 执行本地函数 :你的代码需要解析 tool_calls ,找到本地对应的函数实现(如一个真正的 get_current_weather 函数,它可能去调用天气API),传入参数并执行。
  4. 将结果返回给模型 :将函数执行的结果,再次作为消息传入后续的对话中,消息角色需指定为 tool ,并包含对应的 tool_call_id 。模型会基于这个结果,生成面向用户的最终回答。

实操心得 :函数的描述(description)是灵魂。描述必须精确、无歧义,且与用户可能提问的自然语言方式对齐。例如,“获取天气”这个描述就太模糊,而“获取指定城市的当前温度、湿度和天气状况”则好得多。参数描述也同样重要,它直接指导模型如何从用户语句中抽取信息。

2.3 架构层:智能体循环与状态管理

当智能体需要处理多轮对话、连续使用多个工具时,就需要一个管理循环(Agent Loop)和状态(State)的架构。这就是 didilili/ai-agents-from-zero 这类项目从“简单示例”走向“实用智能体”的核心。

一个典型的ReAct(Reasoning + Acting)风格智能体循环如下:

  1. 观察 :接收用户输入和当前对话历史(状态)。
  2. 思考 :模型基于当前信息,决定下一步行动:是直接回答,还是调用某个工具?
  3. 行动 :如果决定调用工具,则执行对应的本地函数。
  4. 观察 :将工具执行结果作为新的观察,并入对话历史。
  5. 循环步骤2-4,直到模型认为可以给出最终答案。

状态管理 是这个循环的基石。状态至少需要包含:

  • 完整的对话历史 :包括用户消息、助手消息、工具调用消息和工具结果消息。这是模型的“记忆”。
  • 当前循环的控制信息 :例如,是否应该继续循环?最近一次工具调用的结果是什么?

在简单场景中,你可以用一个列表来维护消息历史。但在复杂任务中,你可能需要引入更精细的状态管理,比如分离“短期工作记忆”(当前任务相关的对话)和“长期记忆”(知识库),或者管理会话的元数据(如用户ID、任务目标等)。

2.4 进阶特性层:记忆、规划与多智能体协作

在基础循环之上,可以添加更强大的能力,使智能体更智能、更持久。

  • 记忆(Memory) :让智能体记住跨会话的信息。这可以通过向量数据库实现,将对话中的关键信息提取并存储,后续通过语义检索召回。也可以设计更简单的键值对存储,用于记录用户偏好。
  • 规划(Planning) :对于复杂任务,智能体需要先制定计划(Plan),再逐步执行。例如,用户说“帮我策划一个周末旅行”,智能体可能需要先分解为“确定目的地、查询交通、查找酒店、安排景点”等子任务,然后逐一解决。这通常通过提示工程(如Chain of Thought)或让模型输出结构化计划(如JSON格式的任务列表)来实现。
  • 多智能体协作(Multi-Agent Collaboration) :不同的智能体专精于不同领域(一个负责数据分析,一个负责文案撰写,一个负责审核),它们通过共享的工作空间或消息总线进行通信和协作,共同完成一个宏大任务。这涉及到更复杂的通信协议和协调机制。

3. 从零开始的实战:构建一个天气查询智能体

理论说再多,不如动手做一遍。我们以构建一个“天气查询智能体”为例,完整走一遍流程。这个智能体能理解用户关于天气的各种问法,自动调用天气API,并给出友好的回复。

3.1 第一步:搭建项目基础与环境

首先,创建一个干净的Python虚拟环境并安装核心依赖。

# 创建项目目录
mkdir weather-agent && cd weather-agent
# 创建虚拟环境(推荐使用venv)
python -m venv venv
# 激活虚拟环境
# Windows: venv\Scripts\activate
# Mac/Linux: source venv/bin/activate
# 安装核心库
pip install openai python-dotenv requests

使用 python-dotenv 来管理敏感信息。在项目根目录创建 .env 文件:

OPENAI_API_KEY=你的OpenAI_API密钥
WEATHER_API_KEY=你的天气服务API密钥(例如和风天气)

然后在代码中加载:

from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')

3.2 第二步:封装基础模型调用类

我们创建一个 LLMClient 类,处理所有与OpenAI API的底层通信,集成重试和基础错误处理。

import openai
from openai import OpenAI
import time
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class LLMClient:
    def __init__(self, api_key, base_url=None, model="gpt-3.5-turbo"):
        self.client = OpenAI(api_key=api_key, base_url=base_url)
        self.model = model

    def chat_completion(self, messages, tools=None, tool_choice=None, **kwargs):
        """发起聊天补全请求,支持工具调用"""
        max_retries = 3
        for attempt in range(max_retries):
            try:
                response = self.client.chat.completions.create(
                    model=self.model,
                    messages=messages,
                    tools=tools,
                    tool_choice=tool_choice,
                    **kwargs
                )
                return response
            except openai.APITimeoutError as e:
                wait_time = 2 ** attempt  # 指数退避
                logger.warning(f"API超时,第{attempt+1}次重试,等待{wait_time}秒...")
                time.sleep(wait_time)
            except openai.RateLimitError as e:
                logger.error("速率限制,请稍后再试或检查配额。")
                raise e
            except openai.APIError as e:
                logger.error(f"OpenAI API错误: {e}")
                if attempt == max_retries - 1:
                    raise e
                time.sleep(1)
        return None

这个类封装了基本的创建逻辑,并实现了简单的超时重试。在实际项目中,你可能还需要处理更多异常类型,并加入更详细的日志。

3.3 第三步:定义并实现天气查询工具

我们需要一个真实的函数来获取天气。这里以和风天气的免费API为例(需注册获取KEY)。

  1. 定义工具Schema :严格按照OpenAI的格式定义。
  2. 实现本地函数 :这个函数会真正去调用第三方天气API。
import requests
import json

# 1. 定义工具Schema
weather_tool_schema = {
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "根据城市名称获取该城市的当前天气实况,包括温度、体感温度、天气状况、风向风力、湿度。",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "城市名称,必须是中文,例如:北京、上海市、广州。不要使用拼音或英文。"
                }
            },
            "required": ["location"]
        }
    }
}

# 2. 实现本地函数
def get_current_weather(location: str) -> str:
    """调用和风天气API获取实时天气"""
    api_key = os.getenv('WEATHER_API_KEY')
    # 和风天气城市搜索API,获取location对应的城市ID
    city_search_url = f"https://geoapi.qweather.com/v2/city/lookup?location={location}&key={api_key}"
    try:
        search_resp = requests.get(city_search_url, timeout=10)
        search_data = search_resp.json()
        if search_data['code'] != '200' or not search_data['location']:
            return f"未找到城市'{location}'的天气信息,请检查城市名称是否正确。"
        
        city_id = search_data['location'][0]['id']
        city_name = search_data['location'][0]['name']
        
        # 和风天气实时天气API
        weather_url = f"https://devapi.qweather.com/v7/weather/now?location={city_id}&key={api_key}"
        weather_resp = requests.get(weather_url, timeout=10)
        weather_data = weather_resp.json()
        
        if weather_data['code'] != '200':
            return "获取天气数据失败,请稍后重试。"
        
        now = weather_data['now']
        # 组织一个对人类友好的描述字符串
        result = (
            f"{city_name}当前天气:{now['text']}。"
            f"温度:{now['temp']}℃,体感温度:{now['feelsLike']}℃。"
            f"风向:{now['windDir']},风力{now['windScale']}级。"
            f"湿度:{now['humidity']}%。"
        )
        return result
    except requests.exceptions.RequestException as e:
        return f"网络请求失败:{str(e)}"
    except json.JSONDecodeError as e:
        return "天气服务响应数据格式错误。"

注意事项 :工具函数的返回值必须是字符串。因为模型需要“阅读”这个结果来生成回复。返回结构化的JSON虽然机器可读,但不利于模型理解。所以,最佳实践是在工具函数内部将结构化数据转化为一段自然的描述性文本。

3.4 第四步:实现智能体执行循环

现在,我们将上述部分组合起来,实现一个能够处理多轮工具调用的智能体循环。

class WeatherAgent:
    def __init__(self, llm_client):
        self.llm = llm_client
        self.conversation_history = []  # 维护对话状态

    def run(self, user_input):
        """执行一轮智能体循环"""
        # 1. 将用户输入加入历史
        self.conversation_history.append({"role": "user", "content": user_input})

        # 2. 开始循环,直到模型不再调用工具
        max_turns = 5  # 防止无限循环
        for turn in range(max_turns):
            # 3. 调用模型,传入历史对话和工具定义
            response = self.llm.chat_completion(
                messages=self.conversation_history,
                tools=[weather_tool_schema],  # 传入工具列表
                tool_choice="auto",  # 让模型自行决定是否调用工具
                temperature=0.1  # 低随机性,保证工具调用的稳定性
            )

            if not response:
                return "抱歉,服务暂时不可用。"

            message = response.choices[0].message
            # 4. 将模型的响应(可能是普通回复,也可能是工具调用请求)加入历史
            self.conversation_history.append(message.to_dict())

            # 5. 检查模型是否要求调用工具
            if not message.tool_calls:
                # 没有工具调用,说明是最终回复,循环结束
                final_answer = message.content
                return final_answer

            # 6. 处理工具调用(可能同时有多个)
            for tool_call in message.tool_calls:
                func_name = tool_call.function.name
                func_args = json.loads(tool_call.function.arguments)

                # 根据函数名,映射到本地函数
                if func_name == "get_current_weather":
                    location = func_args.get("location")
                    if not location:
                        tool_result = "错误:未提供城市名称。"
                    else:
                        tool_result = get_current_weather(location)
                else:
                    tool_result = f"错误:未知工具 '{func_name}'。"

                # 7. 将工具执行结果作为一条新消息加入历史
                self.conversation_history.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": tool_result
                })

            # 循环继续,模型将基于工具结果进行下一轮思考
        return "对话轮次过多,可能遇到了复杂问题。请简化您的问题。"

3.5 第五步:测试与交互

最后,我们写一个简单的主程序来测试这个智能体。

if __name__ == "__main__":
    client = LLMClient(api_key=OPENAI_API_KEY)
    agent = WeatherAgent(client)

    print("天气查询智能体已启动。输入'退出'或'quit'结束。")
    while True:
        try:
            user_input = input("\n你:")
            if user_input.lower() in ['退出', 'quit', 'exit']:
                print("再见!")
                break
            answer = agent.run(user_input)
            print(f"智能体:{answer}")
        except KeyboardInterrupt:
            break
        except Exception as e:
            print(f"系统错误:{e}")

现在,你可以运行这个程序,并尝试以下对话:

  • “北京天气怎么样?”
  • “上海和广州的天气对比一下呢?” (注意:这会触发两次工具调用)
  • “我明天要去杭州出差,需要带伞吗?” (模型需要根据天气状况“下雨”来推理出“需要带伞”)

通过这个完整的例子,你亲手实现了一个具备基础工具调用能力的AI智能体。你理解了从API调用、工具定义、函数执行到状态循环的每一个环节。

4. 深入核心:提示工程与智能体推理模式

工具调用是“手”,而提示工程是赋予智能体“大脑”和“思维模式”的关键。同样的工具,在不同的提示引导下,智能体的表现天差地别。

4.1 系统提示词的设计艺术

系统提示词(System Prompt)是智能体的“人格设定”和“核心指令”。它应该在对话开始时一次性注入,并持续影响模型的后续行为。

一个高效的天气查询智能体系统提示词可能如下:

你是一个专业、友好且细致的天气助手。你的核心能力是调用`get_current_weather`工具来获取真实天气数据。

请遵循以下原则:
1. **主动澄清**:如果用户提到的地点不明确(例如“我家那边”、“首都”),请礼貌地询问具体城市名称。
2. **信息整合**:当用户比较多个城市天气,或询问未来出行的建议时,主动调用工具获取所有必要地点的天气,然后综合分析,给出简洁清晰的对比或建议。
3. **安全边界**:你只回答与天气、气候、穿衣建议、出行准备相关的问题。对于其他问题,礼貌地表示你无法回答。
4. **回复风格**:回复应口语化、亲切,在提供数据的同时,可以附加一句简单的关怀(如“温度较低,请注意添衣”)。

当前日期是:{current_date}。请注意,天气数据是实时的,对于未来日期的询问,请基于当前数据给出一般性建议,并说明实际情况可能变化。

设计要点

  • 角色明确 :让模型进入“天气专家”的角色。
  • 能力声明 :明确告知模型它拥有什么工具。
  • 行为规则 :给出具体的、可操作的行为指令,而不是模糊的“要友好”。
  • 上下文注入 :注入当前日期等实时信息,帮助模型做出更准确的判断(比如避免说“明天是周一”,如果今天已经是周日)。
  • 边界设定 :防止智能体“越界”回答无关问题。

4.2 实现复杂推理:ReAct模式实践

对于需要多步推理的问题,简单的单次工具调用不够。我们需要显式地引导模型进行“思考-行动”的循环。这就是ReAct模式。我们可以通过修改提示词,让模型在调用工具前,先输出它的“思考过程”。

修改 WeatherAgent run 方法中的调用部分,并调整系统提示词:

新的系统提示词片段

...(前述角色设定)...
在回答时,请遵循以下格式:
思考:<你内心的推理过程,分析用户意图,决定下一步做什么>
行动:<如果需要调用工具,则输出工具调用;如果可以直接回答,则输出最终答案>

在代码中,我们需要解析模型输出的 content 字段,分离出“思考”和“行动”部分。如果“行动”是工具调用,我们再像之前一样处理。这虽然增加了解析的复杂性,但带来了两大好处:

  1. 可解释性 :我们可以将模型的“思考”部分打印出来,清晰地看到它的决策过程,便于调试和优化提示词。
  2. 可控性 :我们可以基于模型的思考,在代码层面介入,例如当模型推理出现偏差时,可以纠正其行动。

这种模式是构建复杂任务规划智能体的基础。通过让模型“自言自语”式地推理,我们能引导它解决更复杂的问题,例如:“帮我规划一个本周末从北京出发,去一个温暖且不下雨的城市的两日游。” 这需要模型先推理出“需要查找多个候选城市的天气”,然后调用多次天气工具,最后进行比较和推荐。

5. 工程化与生产部署考量

当你的智能体在本地运行良好后,下一步就是考虑如何将它变成一个可部署、可维护的服务。这涉及到一系列工程化问题。

5.1 会话管理与状态持久化

目前的示例中,对话历史保存在内存的列表里。这意味着:

  • 服务重启后,所有会话丢失。
  • 无法支持多用户并发(所有用户共享同一个历史列表,全乱套了)。

解决方案

  • 引入会话ID :为每个用户或每个对话线程分配唯一ID。
  • 选择后端存储
    • Redis :非常适合存储会话状态,读写速度快,支持设置过期时间(TTL),自动清理过期会话。
    • 数据库 :如PostgreSQL或MySQL,如果需要长期持久化或复杂查询,可以选择。但性能不如Redis。
    • 内存存储(仅限单机) :使用像 cachetools 这样的库,实现一个带LRU淘汰机制的缓存。适用于轻量级、单实例部署。

一个基于Redis的会话管理示例:

import redis
import json
import uuid

class SessionManager:
    def __init__(self, redis_url='redis://localhost:6379', ttl=3600):
        self.redis_client = redis.from_url(redis_url)
        self.ttl = ttl  # 会话存活时间(秒)

    def create_session(self, initial_history=None):
        session_id = str(uuid.uuid4())
        history = initial_history or []
        self.redis_client.setex(
            f"agent:session:{session_id}",
            self.ttl,
            json.dumps(history)
        )
        return session_id

    def get_history(self, session_id):
        data = self.redis_client.get(f"agent:session:{session_id}")
        if data:
            return json.loads(data)
        return None

    def save_history(self, session_id, history):
        self.redis_client.setex(
            f"agent:session:{session_id}",
            self.ttl,
            json.dumps(history)
        )

然后在 WeatherAgent 类中,不再使用 self.conversation_history ,而是通过 session_id SessionManager 中获取和保存历史。

5.2 异步处理与性能优化

同步的API调用会阻塞整个线程。当用户量增大或模型响应慢时,会导致服务响应延迟急剧上升。

采用异步编程 :使用 asyncio 和 支持异步的HTTP客户端(如 aiohttp httpx )来重构你的工具函数和LLM调用。OpenAI的官方库也提供了异步客户端 AsyncOpenAI

import asyncio
from openai import AsyncOpenAI
import httpx

class AsyncLLMClient:
    def __init__(self, api_key):
        self.client = AsyncOpenAI(api_key=api_key)

    async def chat_completion(self, messages, tools=None):
        try:
            response = await self.client.chat.completions.create(
                model="gpt-3.5-turbo",
                messages=messages,
                tools=tools
            )
            return response
        except Exception as e:
            # 处理异常
            pass

async def async_get_current_weather(location):
    async with httpx.AsyncClient() as client:
        # 异步调用天气API
        # ...
        pass

使用异步后,你的智能体服务可以轻松地使用 FastAPI Sanic 这样的异步Web框架来构建,能够高效地处理大量并发请求。

5.3 可观测性与监控

智能体服务上线后,你需要知道它运行得怎么样。

  • 日志记录 :结构化日志(如使用 structlog )至关重要。记录每一次用户请求、模型调用(包括输入token、输出token数量)、工具调用(成功/失败、耗时)、最终响应。这有助于问题排查和成本分析。
  • 指标监控
    • 延迟 :用户请求到收到响应的总时间,以及LLM API调用耗时、工具调用耗时。
    • 成功率 :请求成功完成的比例。
    • Token消耗 :各会话消耗的输入/输出token数,用于成本核算。
    • 工具调用分布 :各个工具被调用的频率,有助于优化工具设计。
  • 链路追踪 :对于复杂的多步调用,使用像OpenTelemetry这样的标准来追踪一个用户请求在整个智能体调用链中的路径,快速定位瓶颈或错误点。

6. 避坑指南与常见问题排查

在实际开发和运维中,你会遇到各种各样的问题。这里总结一些典型坑点和排查思路。

6.1 工具调用相关的问题

问题1:模型不调用工具,总是直接回答。

  • 可能原因1:工具描述不清晰或与用户问题不匹配 。检查函数和参数的 description 是否足够精确。模型是根据描述来判断是否调用的。用更贴近用户自然语言问法的词汇来描述工具。
  • 可能原因2:系统提示词未强调工具使用 。在系统提示词中明确指令,如“当你需要实时信息时,务必使用提供的工具”。
  • 排查方法 :开启OpenAI API的调试日志,或打印出发送给API的完整消息列表,检查工具定义是否正确传入。尝试在调用时设置 tool_choice={"type": "function", "function": {"name": "your_tool_name"}} 来强制调用,测试工具本身是否工作。

问题2:模型调用了工具,但参数解析错误。

  • 可能原因 :参数Schema定义有问题,或者模型对用户意图理解有偏差。
  • 解决方案
    1. 在参数Schema中使用 enum 限制可选值。
    2. 为参数提供更详细的描述和示例。
    3. 在系统提示词中,给出明确的参数提取规则。
    4. 在代码中增加参数验证和清洗逻辑。如果解析出的参数不符合要求,可以返回一个错误信息给模型,让它重新尝试。

6.2 性能与成本优化

问题:响应速度慢,Token消耗高。

  • 优化对话历史 :这是最大的可优化点。不要无限制地增长历史消息。策略包括:
    • 滑动窗口 :只保留最近N轮对话。
    • 总结压缩 :当历史过长时,调用模型对之前的对话进行总结,用一段简短的摘要替换掉旧的历史消息。这需要额外的模型调用,但能显著减少后续对话的Token消耗。
    • 选择性记忆 :只将与当前任务强相关的历史消息保留在上下文中。
  • 模型选型 :对于工具调用等对创造力要求不高的任务,使用 gpt-3.5-turbo 通常比 gpt-4 性价比高得多,且速度更快。
  • 超时设置 :为LLM调用和工具调用设置合理的超时时间,避免因个别慢请求拖垮整个服务。

6.3 稳定性与错误处理

问题:第三方工具API不稳定导致智能体失败。

  • 重试机制 :为工具函数实现重试逻辑,特别是对于网络请求。
  • 降级策略 :当某个工具不可用时,是否有备选方案?例如,主天气API失败后,是否尝试备用API?或者,模型能否在不依赖该工具的情况下,给出一个有限的回答(如“天气服务暂时不可用,但根据一般情况,这个季节建议您...”)?
  • 用户友好错误 :不要将后端复杂的错误栈直接抛给用户。工具函数应捕获异常,并返回一个对模型友好的错误描述,让模型能够生成得体的用户回复,例如“暂时无法获取天气数据,请稍后再试”。

构建AI智能体是一个持续迭代的过程。从最简单的“Hello World”式对话,到具备复杂规划和记忆能力的助手,每一步都建立在对前一步技术的扎实理解之上。 didilili/ai-agents-from-zero 这个项目提供了一个绝佳的起点和思维框架。最重要的是动手实践,从一个具体的小功能开始,逐步添加组件,并在过程中不断思考如何让它更可靠、更高效、更智能。当你亲手解决了上述的每一个问题,你对AI智能体的理解就不再停留在概念层面,而是拥有了将其转化为实际生产力的能力。

更多推荐