共计 2187 个字符,预计需要花费 6 分钟才能阅读完成。
问题场景
在开发 AI 代理系统时,经常会遇到 agent couldn't generate a response 错误。这个错误通常发生在以下场景中:

- 异步工具调用超时 :当 AI 代理调用外部工具(如 API 或数据库)时,如果响应时间过长,代理可能无法及时生成响应。
- 动作结果解析失败 :工具返回的结果格式不符合预期,导致代理无法正确解析。
- 长时任务处理 :某些任务需要较长时间完成(如文件处理或复杂计算),代理可能在等待过程中超时。
这些问题的根本原因是工具动作执行状态的不透明性。代理无法实时获取工具的执行状态,导致响应生成失败。
架构设计
为了解决这个问题,我们对比了三种监控方案:
- 轮询检查 :定期查询工具的执行状态。优点是实现简单,缺点是可能增加系统负载。
- 回调通知 :工具完成任务后主动通知代理。优点是实时性高,但需要工具支持回调机制。
- 状态机跟踪 :使用状态机跟踪工具的执行状态。优点是状态管理清晰,适合复杂流程。
综合来看,状态机跟踪是最优方案,尤其是结合幂等性设计。每个工具动作附带一个唯一版本号,确保重复请求不会导致多次执行。
核心实现
以下是关键逻辑的 Python 实现:
工具动作状态持久化(Redis 示例)
import redis
# 初始化 Redis 连接
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)
def save_action_state(action_id, state, version):
""" 保存工具动作状态到 Redis
Args:
action_id: 动作唯一 ID
state: 当前状态(如 'pending', 'completed', 'failed')version: 动作版本号
"""key = f'action:{action_id}'redis_client.hset(key,'state', state)
redis_client.hset(key, 'version', version)
响应超时的自动重试机制(含指数退避)
import time
def retry_with_backoff(action_func, max_retries=3, initial_delay=1):
""" 带指数退避的重试机制
Args:
action_func: 需要重试的函数
max_retries: 最大重试次数
initial_delay: 初始延迟时间(秒)"""
retry_count = 0
delay = initial_delay
while retry_count < max_retries:
try:
return action_func()
except Exception as e:
retry_count += 1
if retry_count == max_retries:
raise
time.sleep(delay)
delay *= 2 # 指数退避
动作结果解析的异常处理模板
def parse_action_result(result):
""" 解析工具动作结果
Args:
result: 工具返回的原始结果
Returns:
解析后的结果
Raises:
ValueError: 解析失败时抛出
"""
try:
# 假设结果应为 JSON 格式
parsed = json.loads(result)
if 'status' not in parsed or 'data' not in parsed:
raise ValueError('Invalid result format')
return parsed
except json.JSONDecodeError as e:
raise ValueError('Failed to decode JSON') from e
生产部署
在生产环境中,建议采取以下措施:
- 设置合理的超时阈值 :根据工具的平均响应时间设置超时阈值,避免过长或过短。
- 避免重复执行 :在分布式环境下,使用分布式锁(如 Redis 锁)确保同一动作不会被多次执行。
- 监控指标埋点 :使用 Prometheus 监控工具动作的执行时间和成功率。
以下是 Prometheus 指标设计示例:
from prometheus_client import Counter, Histogram
# 定义指标
ACTION_EXECUTION_TIME = Histogram(
'action_execution_time_seconds',
'Time spent processing actions',
['action_type']
)
ACTION_FAILURES = Counter(
'action_failures_total',
'Total number of failed actions',
['action_type', 'error_code']
)
验证测试
使用 Locust 模拟高并发场景,验证系统的稳定性:
from locust import HttpUser, task, between
class ActionTestUser(HttpUser):
wait_time = between(1, 5)
@task
def test_action(self):
self.client.post('/execute_action', json={'action': 'sample'})
延伸思考
在更复杂的场景中,工具动作可能需要跨多个微服务完成。这时,如何设计两阶段提交(2PC)机制来确保数据一致性?这是一个值得深入探讨的问题。
正文完
