上下文移位
上下文移位通过移除或压缩最不重要的上下文,同时保留所有必须保留的内容, 把组装好的对话装进模型的令牌预算。
请求前步骤
在发送请求之前,管线遵循以下步骤:
- 确定模型的分词器配置文件和上下文限制。
- 为响应预留空间。
- 保留系统提示词、角色、必需的设定集条目和置顶消息。
- 首先移除或压缩最旧的未置顶块。
- 工具调用和工具结果消息只成对移除。
- 每次更改后重新统计令牌。
- 向用户显示被排除或摘要的内容。
如果受保护上下文本身超过了预算,生成会以稳定的 TOKEN_BUDGET_EXCEEDED
错误结束,而不是向提供商发送超预算的请求。
移位如何工作
shiftContext(messages, countTokens, budget) 把对话调整到令牌预算。
它返回三个列表:
kept—— 装得下的消息;excluded—— 被移除并显示给用户的消息;truncated—— 被压缩而不是丢弃的块。
系统消息和置顶消息总是受保护的。最旧的未置顶块首先被移除。工具调用及其
结果通过 toolCallId、tool_call_id 或 callId 关联,
作为一个组移除,即使它们不相邻。
内置策略
策略由 contextStrategy 设置选择,并通过 ContextStrategyRegistry 应用:
- truncate —— 移除最旧的未置顶组。
- summarize —— 对被排除的历史构建本地抽取式摘要, 并把它保留在当前用户输入之前。
- vector-recall —— 在低相关块之前丢弃低相关性的设定集和记忆块, 然后缩短旧历史。
- manual —— 首先排除标记了
meta.manualExcluded: true的消息 (包括配对的工具调用和工具结果),如果还需要更多空间, 则继续进行常规缩减。
插件与预算
插件可以注册更多策略;注册会返回一个清理函数。插件策略无法绕过预算:
- 宿主恢复必需的消息,并拒绝移除了受保护上下文的策略;
- 宿主独立地重新核算真实预算;
- 计数和移位在插件拦截器之前运行,之后强制进行带最终移位的重新计数 —— 插件无法事后添加消息来偷偷绕过限制。
上下文审计
每次生成都会在网络调用之前创建一个 PromptContextAudit,
并以一个终止状态结束:completed、failed 或 cancelled。审计记录:
- 生成 ID、提供商和模型;
- 每个提示词块的实际顺序,带令牌计数以及包含或排除的稳定原因;
- 上下文限制、响应预留和最终的提示词令牌计数;
- 分词器配置文件以及它是否为近似;
- 最终的提供商消息和插件拦截器诊断;
- 规范化的提供商错误码,不包含上游响应体。
每个聊天只保留最后一次完整的审计;新请求原子地替换旧请求,
删除聊天也会删除审计。界面通过 GET /api/v2/chats/:id/context-audit 读取它。
一个实时预览端点 POST /api/v2/context-preview 运行相同的人设、设定集、
记忆、模板、分词器和移位阶段,而不创建消息、分支或审计。