← 工具调用

资源有几千条时,怎么避免把数据一次全塞给模型?

中等 工具选择与工具收窄 · 第 2 / 2 问 更新于 2026/09/29
工具调用上下文管理Agent成本控制工具设计
本题落地项目AI Agent旅游行程智能规划平台

简化版

一次把几千条数据交给模型,要么超出上下文直接失败,要么装得下但注意力被无关条目稀释,模型更容易报出一个「感觉存在」的 ID。做法是分四层收窄,按顺序叠加:候选池预热(Agent 启动前由代码按用户画像、预算、偏好筛出每类几十条,工具只在池内查)→ 字段裁剪(列表工具只返回决策需要的字段,细节交给一次查一个的详情工具)→ 返回上限(每个列表工具单次最多返回 N 条,上限可配置)→ hasMore 与下一步提示(告诉模型还有多少没返回、应该换什么条件再查、不要重复同样的参数)。第一层决定问题规模,后三层控制每一次调用的体积。

详细版

原始资源:1828 个点位 + 850 家酒店 + 4240 条班次
  ↓ 第一层 候选池预热(启动前,不经过模型)
每个城市:点位约 60 条 + 必玩清单、酒店 12 家、每段城际班次 8 趟
  ↓ 第二层 字段裁剪
列表每行只给 ID、名称、类型、城区、价格、时长、热度、标签;详情单独查
  ↓ 第三层 返回上限
点位每次最多 25 条、酒店 10 条、班次 8 条
  ↓ 第四层 hasMore 提示
{"total": 63, "returned": 25, "hasMore": true, "hint": "还有 38 条没返回,可换标签或城区再查,不要重复相同参数"}
层在哪做解决什么
候选池预热业务代码,启动前把「几千里选」变成「几十里选」
字段裁剪列表 / 详情两个工具单条记录不膨胀
返回上限工具执行时读配置单次调用不超量
hasMore 提示返回结构模型知道自己看到的是子集,换条件而不是重复调用

完整版教学

一、一次给全为什么不行

先算体积。一条点位只保留名称、类型、城区、门票、时长、热度、标签,也有六七十个字符:

1828 条点位 × 约 65 字符 ≈ 12 万字符
再加 850 家酒店、4240 条班次,总量几十万字符

这已经会占满很多模型的上下文窗口,请求直接失败。即使窗口装得下,问题也没解决:

候选太多,模型容易报一个「感觉存在」的 ID,写入时被校验打回
注意力分散到大量无关条目上,排出来的方案质量反而下降
每一轮往返都要带着这几十万字符,成本按轮数翻倍

所以要在工具的设计上收窄,而不是指望模型「自己看着办」。

二、第一层:候选池预热

最有效的一层是在 Agent 启动之前,由业务代码按确定的规则筛出候选,不经过模型:

每个目的地城市:
  ① 取启用的全部点位
  ② 按预算档过滤门票:经济档去掉门票超过 150 元的,舒适档去掉超过 300 元的,品质档不过滤
  ③ 按兴趣标签命中个数从多到少、再按热度从高到低排序
  ④ 取前 60 条
  ⑤ 用户必玩清单里的点位无条件补进来,不受 ② 和 ④ 的限制

这一层把问题从「1828 条里选」变成「每个城市几十条里选」。之后所有查询工具都只在候选池里查,SQL 上按候选池的 ID 集合限定,绕过候选池直接全表查的工具就是实现错误。

预热的风险是把用户真正想要的筛掉了,所以要有三层保护:用户明确要去的(必玩清单)无条件进池;池子大小是配置项可以调;候选池写进本次运行的快照,出问题能拿原始快照复现。

记忆钩子:能用规则确定的筛选,就不要交给模型。代码先把范围缩小,模型只在小范围里做需要判断的选择。

三、第二层:列表只给决策字段

候选池里每一条都相关了,但每条还带着很多决策用不上的字段。解决办法是把一个工具拆成两个:

工具返回用途调用方式
列表工具ID、名称、类型、城区、门票、建议时长、热度、标签在候选里挑按条件筛,每次多条
详情工具开放星期、开放时段、最晚入场、闭园季、经纬度、简介写入前确认一次查一个

列表阶段模型只需要比较;真要写入某一项时,再花一次调用确认它当天开不开门。详情工具的描述要写明「只在准备写入之前调用,一次查一个;不要批量调用,也不要用来搜索」。

四、第三层:返回上限

候选池里每个城市还有几十条,列表工具也不一次全给:

点位列表    每次最多 25 条
酒店列表    每次最多 10 条
城际班次    每次最多 8 条

上限放在工具注册表里,工具执行时读取;表里没填就用代码里的默认值。每次调用都现读,调整上限后,正在跑的任务下一次调用就按新值截断。

五、第四层:告诉模型「还有更多」

只截断还不够。模型看到 25 条,会以为这就是全部,然后要么据此做决定,要么用同样的参数反复调用想「翻页」。返回结构要明确说明:

{
  "total": 63,
  "returned": 25,
  "hasMore": true,
  "limit": 25,
  "hint": "候选池中还有 38 条没返回。可换 tags 或 area 条件再查,不要重复调用相同参数。",
  "rows": [ ... ]
}

hint 按情况给出下一步:

情况提示
一条都没匹配上放宽条件,去掉部分筛选,不要逐个试探
还有没返回的换条件再查,不要重复相同参数
全部返回了进入详情确认和写入

六、收窄的效果要能看见

四层收窄让数字链条变得清楚,也是很好的排查依据:

全量 1828 个点位 → 进入候选池 63 个 → 模型最终选用 21 个

把这组数字展示在页面上,能直观看出收窄是否过度(候选太少排不出合规行程)或不足(候选太多模型反复查询)。如果轮数用尽仍排不出合格方案的比例偏高,往往就是候选池太小,需要调大池子。

七、其他场景怎么套用

商城导购:候选商品按预算过滤后最多返回 8 条,价格库存另用工具单查
客服知识:先按业务线、产品过滤知识库,再做语义检索取前几条
数据分析:先用元数据选出相关的几张表,再把这几张表的字段交给模型

核心思路一致:先用确定规则缩小范围,再让模型在小范围里判断;每次调用有上限,并告诉模型还有多少。

八、常见误区与追问

  • 误区:上下文窗口够大就可以一次全给。 装得下不代表用得好,候选太多会稀释注意力、增加编造 ID 的概率,还按轮数放大成本。
  • 误区:收窄交给模型自己用查询条件完成。 能用规则确定的筛选应在启动前由代码完成,模型只在候选里判断。
  • 误区:列表工具把所有字段都带上最方便。 细节字段应拆到详情工具,列表只给决策需要的字段。
  • 误区:截断到 N 条就够了。 不告诉模型还有更多,它会以为这是全部,或者用相同参数反复调用。
  • 误区:候选池筛得越小越好。 太小会排不出合格方案,要保留用户明确要求的项并允许调整池子大小。
  • 追问:怎么防止预热把用户真正想要的筛掉? 必玩清单无条件进池,池子大小可配置,候选池写进运行快照便于复现。
  • 追问:返回上限怎么定? 按一次决策需要比较的数量定,放进配置表,根据调用日志里的查询次数调整。

九、加强记忆

几千条数据一次给全会撑满上下文、稀释注意力、放大成本。四层收窄按顺序叠加:启动前由代码按画像和预算预热候选池,必玩项无条件进池、池子可配、写进快照,工具只在池内查;列表只给决策字段,细节交给一次查一个的详情工具;每个列表工具有可配置的返回上限;返回结构带 total、returned、hasMore 和下一步提示,让模型换条件而不是重复调用。全量、进池、选用三个数字要能看见。

项目实战落地

项目里怎么做的

《AI Agent旅游行程智能规划平台》的资源库有 1828 个点位、850 家酒店、4240 条城际班次,行程编排 Agent 按四层收窄:

  • 候选池预热:CandidatePoolService 在 Agent 启动前按城市预热:点位按预算档过滤门票(经济档去掉门票高于 150 元、舒适档去掉高于 300 元),按标签命中数和热度排序取前 POOL_POI_SIZE(60)条,必玩清单无条件加入;酒店按预算档映射星级、每城取 12 家;班次按出发时间分散取,每段 8 趟;三个池子大小都在系统参数里;
  • 快照与池内查询:候选池写进 agent_run.input_snapshot,同时把 ID 集合放进运行上下文,所有查询工具只在池内查,写入工具核对 ID 在池内;
  • 列表和详情分开:点位列表工具每行只返回决策字段,开放时间、闭园季、经纬度放在一次查一个的详情工具里;
  • 返回上限与提示:上限来自 function_tool.max_return_rows(点位 25、酒店 10、班次 8),buildPageResult 统一返回 total、returned、hasMore、limit、hint,点位工具的 hint 按「一条没匹配上 / 还有没返回的 / 全部返回了」三种情况生成。

为什么这样取舍

  • 池子由代码预热:把问题从「1828 条里选」变成「每城几十条里选」,后面三层才有意义;页面能展示「从 1828 个点位里筛出 63 个候选,Agent 从中选了 21 个」。
  • 提示写明不要重复参数:模型知道自己看到的是子集,会换一个标签或城区再查,而不是用同样的参数反复调用把轮数打满。

面试官还会追问

  • 候选池把资源筛掉了一大部分,会不会把用户本来想去的地方也筛没了?项目怎么兜底?
  • 两座城市之间没有直达班次时,班次工具返回什么?会不会编一趟出来?

学完《AI Agent旅游行程智能规划平台》,上面这些追问你都会迎刃而解。

本题落地项目地狱锤炼AI Agent旅游行程智能规划平台基于 SpringBoot + LangChain4j、攻略知识库 RAG、MySQL 向量检索、Function Calling 与数据库驱动工具中心,实现候选池预热与工具收窄、多城联游行程编排、14 条代码硬校验驱动的反思重排、教训记忆与多版本对比、三道闸防空转、编排前探活、预算测算和 Agent 执行时间线,覆盖从需求识别到行程交付的完整闭环。SpringbootLangChain4JAgentRAGFunction Calling源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目