Appearance
23. 工具返回的结果太大时,Agent 怎么处理?
难度 P1 高频 · 岗位 应用 · 频率 ★★★★☆ · 预计阅读 8 min 公司 OpenAI · Anthropic 相关题 Q62 工具使用模式 · Q76 上下文工程
本题阅读地图
- 面试场景还原 — 1 min
- TL;DR 速记 — 30 sec
- 图解 — 30 sec
- 详细解析 — 5 min
- 4.1 为什么大结果是问题?
- 4.2 处理策略:分场景应对
- 4.3 长文本处理:摘要与分块
- 4.4 结构化数据处理:提取与聚合
- 4.5 列表数据处理:排序与分页
- 常见踩坑与反例 — 1 min
- 面试官可能继续追问 — 1 min
面试场景还原
👔面试官:假设你的 Agent 调用了数据库查询工具,返回了 10 万条用户记录,你打算怎么处理?
🙋♂️我:截断一下,只保留前面的部分传给模型。
👔面试官:简单粗暴截断可能会丢失关键信息。如果是按时间排序的,后面的最新记录就被截掉了。你能讲更系统的做法吗?
🙋♂️我:呃……那可以按时间倒序,取最新的?
👔面试官:这只是列表场景。如果返回的是一份 100 页的研究报告,或者一个包含上百个字段的复杂 JSON,该怎么处理?
🙋♂️我:可能要做摘要?
👔面试官:对。处理大结果要分场景:长文本用摘要/分块,结构化数据做字段提取/聚合,列表做排序/筛选/分页。还要考虑是否触发二次查询来获取细节。
TL;DR 速记
- 核心问题:大结果超出上下文窗口,可能导致信息丢失或成本过高
- 分场景处理:长文本→摘要/分块;结构化→提取/聚合;列表→排序/分页
- 策略分层:预过滤(工具层)→ 后处理(Agent 层)→ 二次查询(按需加载)
- 关键原则:不要简单截断,要根据数据特性和任务需求智能处理
- 进阶手段:摘要模型轻量处理、向量化检索、分页加载、链接替代
图解
图 1:大结果处理的分层策略
图 2:Agent 大结果处理决策流程
详细解析
为什么大结果是问题?
LLM 有上下文窗口限制(Context Window Limit),当前主流模型的限制:
- GPT-4: 128K tokens
- Claude 3: 200K tokens
- Gemini: 1M+ tokens
即使窗口很大,放入太多信息也会带来问题:
问题 1:成本急剧上升
- LLM API 按输入+输出的 token 数收费
- 10 万条记录直接塞进去,成本可能高 100 倍
问题 2:关键信息被淹没
- 参考 Lost in the Middle 现象
- 长文本中间部分的信息,模型容易忽略
问题 3:推理质量下降
- 信息过载导致模型难以聚焦
- 响应时间显著增加
问题 4:工具设计不合理
- 很多工具返回「全量数据」而非「按需数据」
- API 设计时没有考虑 Agent 消费场景
处理策略:分场景应对
| 数据类型 | 典型场景 | 处理策略 |
|---|---|---|
| 长文本 | 研究报告、文档、网页内容 | 摘要、分块、提取关键段落 |
| 结构化数据 | JSON、数据库查询结果 | 字段筛选、聚合统计、Schema 提取 |
| 列表/数组 | 搜索结果、记录列表 | 排序筛选 Top-N、分页加载 |
| 多媒体 | 图片、视频、音频 | 转描述文本、提供链接、提取元数据 |
长文本处理:摘要与分块
策略 1:摘要(Summarization)
用轻量级模型(或同样的 LLM)做摘要:
python
# 原始文本:10万字的研究报告
full_text = tool_call("get_research_report", topic="AI trends")
# 提取摘要
summary = llm_generate(
prompt=f"请总结以下报告的核心观点和数据:\n\n{full_text[:10000]}...",
max_tokens=500
)
# 返回给 Agent 的是摘要而非全文
return {"summary": summary, "full_report_link": report_url}策略 2:分块 + RAG(Retrieval-Augmented Generation)
python
# 将长文档切分成 chunk
chunks = chunk_text(full_text, chunk_size=1000, overlap=100)
# 建立向量索引
vector_store.index(chunks)
# Agent 提问时,检索相关 chunks
relevant_chunks = vector_store.search(query, top_k=5)
context = "\n".join(relevant_chunks)策略 3:关键信息提取
用结构化方式提取指定信息:
python
extraction_prompt = """
从以下研究报告中提取:
1. 核心结论(1句话)
2. 关键数据(最多3个)
3. 主要观点(最多5条)
报告内容:
{full_text}
以 JSON 格式输出。
"""结构化数据处理:提取与聚合
场景:数据库查询返回 10 万条用户记录
策略 1:字段筛选
python
# 工具层预过滤
@tool
def query_users(fields: list, limit: int = 100):
"""
查询用户信息
Args:
fields: 需要的字段列表,如 ["id", "name", "email"]
limit: 返回记录数上限,默认100
"""
# 只查询指定字段,限制数量策略 2:聚合统计
python
# 原始查询结果(太大)
{
"users": [
{"id": 1, "name": "...", "orders": [...]},
// ... 100000 条
]
}
# 聚合后(精简)
{
"summary": {
"total_users": 100000,
"active_today": 5234,
"premium_users": 1234
},
"top_users": [ // 只取 Top-10
{"id": 123, "name": "...", "total_spent": 9999},
...
],
"distribution": {
"by_region": {...},
"by_age_group": {...}
}
}策略 3:分层加载
- 第一层:聚合统计(总览)
- 第二层:Top-N 详情(典型样本)
- 第三层:按需查询(通过 ID 查具体记录)
列表数据处理:排序与分页
场景:搜索返回 1000 条结果
策略 1:智能排序 + Top-N
python
# 按相关性排序,只取前 N 条
results = search(query)
results.sort(key=lambda x: x.relevance_score, reverse=True)
top_results = results[:10] # 只给 Agent Top-10策略 2:分页加载
python
# 工具支持分页参数
@tool
def search_products(
query: str,
page: int = 1,
page_size: int = 20
):
"""
搜索产品
Args:
query: 搜索关键词
page: 页码,从1开始
page_size: 每页数量,默认20,最大100
"""
# 返回结构
{
"items": [...], // 当前页数据
"total": 1000, // 总数
"page": 1,
"page_size": 20,
"has_next": true
}策略 3:渐进加载
python
# 先返回概要 + 第一页
{
"summary": "找到 1000 个相关产品",
"first_page": [...],
"total": 1000,
"suggestions": ["笔记本电脑", "平板电脑", "配件"] // 建议细化查询
}
# Agent 判断是否需要更多
if agent_decide("需要更多结果"):
next_page = tool_call("search_products", query="...", page=2)二次查询机制
当精简后的信息不够时,支持 Agent 发起二次查询:
场景 1:摘要不够详细
python
# 第一次:获取摘要
summary = get_report_summary(report_id)
# Agent 判断需要详情
if "需要第三章的详细内容" in agent_thought:
detail = get_report_section(report_id, section="chapter_3")场景 2:需要特定字段
python
# 第一次:获取用户列表(精简版)
users = query_users(fields=["id", "name"], limit=10)
# Agent 需要某个用户的完整信息
if "查看用户 123 的详细资料" in agent_thought:
user_detail = get_user_by_id(user_id=123, fields="all")场景 3:关联数据
python
# 第一次:获取订单列表
orders = query_orders(limit=10)
# Agent 需要订单的商品详情
for order in orders:
if "需要商品详情" in agent_thought:
products = query_products(order_id=order.id)常见踩坑与反例
踩坑 1:简单粗暴截断
错误做法:
python
result = tool_call(...)
return result[:4000] # 直接截断到 4000 字符问题:
- JSON 截断后格式损坏,无法解析
- 关键信息在尾部,被截掉了
- 没有告诉模型「结果被截断了」
正确做法: 根据数据类型选择合适的处理策略,并在返回中标注处理方式。
踩坑 2:把所有信息都塞进上下文
错误做法: 不管结果多大,全部塞进 Prompt 给 LLM。
问题:
- 成本高
- 容易触发长度限制
- 关键信息被淹没
正确做法: 预过滤 + 摘要,只给 LLM 必要的信息。
踩坑 3:过度摘要导致信息丢失
错误做法: 10 万字报告摘要成 1 句话,丢失了所有关键数据。
正确做法: 分层摘要:1 句话概括 + 3-5 条关键观点 + 核心数据 + 原文链接。
踩坑 4:不支持二次查询
错误做法: 工具只支持「全量查询」,没有「详情查询」接口。
问题: Agent 无法按需获取细节,要么信息不足,要么信息过载。
正确做法: 工具设计时支持分层查询:概览 → Top-N → 详情。
踩坑 5:忽视工具层的预过滤
错误做法: 工具返回全量数据,依赖 Agent 层处理。
正确做法: 工具层支持参数过滤(fields、limit、filter),减少数据传输。
面试官可能继续追问
追问 1:如果数据库查询返回 100 万条记录,怎么设计工具接口? 答题要点:1)强制分页(max limit = 1000);2)默认聚合模式(count/sum/avg);3)支持流式输出;4)提供筛选条件参数。
追问 2:怎么判断摘要是否保留了关键信息? 答题要点:用 LLM 评估摘要质量;保留关键实体和数据;对比原文和摘要的实体召回率;人工抽样检查。
追问 3:大结果处理的性能怎么优化? 答题要点:异步处理 + 缓存;增量加载而非全量;向量化索引加速检索;分层存储(热/冷数据)。
追问 4:多媒体数据(图片、视频)怎么处理? 答题要点:图片用 VLM 生成描述文本;视频提取关键帧 + 转录文本;音频转录为文本;原文件提供链接而非直接嵌入。
面试总结
工具大结果处理是 Agent 工程的关键能力。面试时强调三点:
- 核心问题:上下文限制、成本、信息淹没,需要智能处理而非简单截断
- 分场景策略:长文本→摘要/分块;结构化→提取/聚合;列表→排序/分页
- 分层设计:工具层预过滤 → Agent 层智能处理 → 支持按需二次查询
记住:不要直接截断,要根据数据类型和任务需求选择合适的处理策略。好的工具设计应该在工具层就支持参数过滤,减少不必要的数据传输。