mcpField
C
commerce-prompt-caching

commerce-prompt-caching

github.com/anthropicsAgent 工作流3.4k42 次安装8 周前更新
代码仓库

关于 commerce-prompt-caching

为购物与商家 Agent 提供稳定组装提示词请求的技能,通过区分静态内容、动态上下文和滚动消息断点来减少缓存失效。适合维护相关运行时及排查提示词缓存命中问题。

主要功能

  1. 01静态提示词与动态上下文分离
  2. 02工具列表固定排序
  3. 03滚动消息缓存断点
  4. 04压缩历史工具结果
  5. 05提供缓存命中验证方法

适用场景

  1. 01减少每轮请求的提示词前缀变化
  2. 02排查对话缓存读取率下降
  3. 03配置购物与商家 Agent 的提示词组装

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/anthropics/commerce-agents --skill commerce-prompt-caching

安装后在 Claude Code 中输入/commerce-prompt-caching确认已加载。

详细介绍

缓存稳定的请求组装

commerce_common/ 是 commerce-common/commerce_common/,shopping_agent/ 是 shopping-agent/core/shopping_agent/,而 merchant_agent/ 是 merchant-agent/core/merchant_agent/。

三个断点

请求中可缓存的前缀依次为 tools、system 和消息;断点会结束一个跨度,供下一次调用读回。参考 Agent 在 commerce_common/prompt_assembly.py 中设置了三个断点:

  1. 最后一个工具:with_tool_cache_control(tools)。
  2. 静态系统文本:build_system_blocks(static, context) 为其标记,并追加未标记的上下文块。
  3. 最新的持久化消息:build_request_messages(messages, rolling_breakpoint=...) 只在发出的请求中标记最后一个持久化块;这样,下次调用便能从缓存读取更早的轮次,包括搜索载荷。

每个请求的数据都放在上下文块中,该角色的 build_dynamic_context(...) 会在每个轮次渲染一次。若把这些字节放入静态块或工具列表,每个请求都会打断系统或工具跨度;放在上下文块中,则只会在购物车、页面或事实发生变化的轮次重新读取一次对话,而滚动标记会从该轮次的下一轮开始生效。时钟按小时渲染(context_clock),因此分钟变化不会造成任何改变。

实际实现的拆分方式

  • 每个角色的 prompt.py 中的 build_static_system(config, skills) 会根据配置和已安装的技能渲染身份信息、最大轮次数规则、围栏说明和技能索引:在一次部署的整个生命周期内,这些字节都保持不变。
  • 同一模块中的 build_dynamic_context(...) 会在该角色的数据围栏内渲染每个请求所需的内容:购物 Agent 使用偏好、记忆事实、购物车、页面、账户块和时间;商家 Agent 使用商店上下文、记忆事实和时间。后端上下文块各自有大小上限。
  • ShoppingAgent.__init__ 和 MerchantAgent.__init__(分别位于各角色的 runtime-messages-api orchestrator.py 中)会在每个进程启动时构建 _static_system 和 _tools;stream_turn 会在每个轮次渲染上下文块,并在每次模型调用时调用 build_request_messages。
  • 每个角色的 tools/registry.py 中的 build_tools 会按固定顺序输出内置工具(商家构建器在启用时会在这些工具之后添加 run_analysis),接着是按排序排列的 load_skill 枚举,然后是按给定顺序排列的扩展,最后是在启用时添加 web_search;每个已注册的工具都会随每个请求一同发送,执行器会在收到调用时判断是否能够处理。
  • Agent SDK 运行时会传递相同的静态文本(以及 SKILL_TOOL_ADAPTER)和相同的契约,并由 SDK 缓存;托管清单将这些文本存放在 system.md 中,scripts/check.py 会将其与构建器进行比较。

跳过滚动标记的情况

有两种轮次不带标记。第一种是纯粹的首次调用(只有一条消息):一次性会话会付出写入成本,却没有后续读取,而第二次调用的标记无论如何都会覆盖第一条消息。第二种是 tool_choice 不为 auto 的轮次(被强制要求进行检索的首轮迭代,以及被强制要求输出文本的最后一轮):tool_choice 是消息跨度的键,因此,在强制轮次下写入的条目无法被之后的自动轮次读取;系统和工具跨度仍然可以命中缓存。这两种情况都由 build_request_messages 和循环中的 rolling_breakpoint= 参数处理;rolling_conversation_cache 可在调试时关闭该标记。

对话被压缩时

当某一轮最后一次调用的使用量达到或超过 compact_history_above_tokens(该轮的 usage 会显示;默认值为平台自身的工具结果清除默认值,即上下文窗口的十分之一)时,这一轮会在 commerce_common/turn.py 中以 compact_history 结束。它会将存储对话中最旧的工具结果替换为一行标记,直到对话缩短至原来大小的一半。下一轮的第一轮处理会重写一次消息片段,之后的轮次则读取较短的版本;turn_complete.results_cleared 会告知会追加其记录文本的宿主需要重写。系统和工具片段、消息以及写入门控不受影响;来源信息保存在会话状态中。

会占用提示词字节数的配置字段

commerce_common/config.py 和各角色配置中标记为 (prompt) 的字段,以及商家工具构建器读取的 enable_analysis 和 max_items_per_change,都会渲染为静态文本或工具列表;更改其中任何一项都需要重新部署,并会导致下一次请求未命中:

配置字段
BaseAgentConfig(commerce_common/config.py)brand_name、assistant_name、brand_voice、enable_web_search
ShoppingAgentConfig(shopping_agent/config.py)domain_search_notes、enable_disclosures,以及系统开关 enable_cart、enable_orders、enable_policies、enable_fulfillment
MerchantAgentConfig(merchant_agent/config.py)enable_analysis、require_host_approval、approval_surface、stage_shows_preview,以及系统开关 enable_listing_edits、enable_inventory、enable_pricing、enable_campaigns;max_items_per_change 和 max_search_results 用于设置工具架构中的 maxItems 和 maximum

技能、呈现扩展和委派对象也会占用提示词字节数。门控词典、护栏限制、记忆设置、延迟参数(eager_tool_dispatch、rolling_conversation_cache、eager_partial_frames、close_on_presentation)、购物车上限和 compact_history_above_tokens 则不会;tests/test_role_registries.py 会逐项断言这一点。

哪些情况会导致未命中

  • 静态区块或工具列表中的任何逐请求变化内容:名称、购物车数量、页面、时钟、请求 ID。上下文区块会包含前四项;请求 ID 不应出现在任何位置。
  • 将集合或字典写入提示词文本或工具架构时未排序。
  • 按请求决定 tools[] 的成员(而不是在构造时读取一次标志)。
  • 在轮次内部而非构造函数中重新构建静态文本或工具列表。
  • 将滚动标记持久化到存储的对话中,导致每轮都增加一个标记。
  • 在运行中的部署上切换 (prompt) 字段、技能或扩展;每项变更都需要重新部署。
  • 按请求而非按部署选择提示词变体。
  • 前缀短于模型可缓存的最小长度,因此不会写入任何内容。
  • 强制指定 tool_choice(先 grounding,最后 none)只会导致消息片段未命中;循环会在该处跳过标记。

验证方法

  • turn_complete 会携带 usage(即 commerce_common/turn.py 中的 usage_totals,为该轮各次调用的总和)和 elapsed_ms;每次调用也会记录一行日志,其中包含相同的计数器以及该次调用耗时(log_model_call,位于 shopping_agent_runtime.orchestrator 和 merchant_agent_runtime.orchestrator 中)。如果对话第二轮的缓存读取量为零, 就意味着前缀发生了变化。每个配置版本值得绘制图表的指标包括:缓存读取量占输入的比例、elapsed_ms、每轮的轮数,以及按门控统计的被阻止的 tool_result 事件。
  • tests/test_role_registries.py 会分别构建每个角色的提示词和工具两次并比较字节内容、检查缓存标记, 还会检查非提示词设置不会造成任何变化;commerce-common/tests/test_prompt_assembly.py 涵盖区块构建器、上下文时钟、 滚动标记和跳过情形;tests/test_turn_loop.py 会验证两个循环使用相同的区块、标记和干净的历史记录。部署的测试也包含相同的三项检查。
  • 在已部署的环境中运行一次三轮对话,并读取第二轮和第三轮的 usage;代理或重试层改写请求的情况会在这里显现,别处不会。

评论

支持 Markdown