问题
目前 token 数量通过简单的字符数启发式算法估算(发送请求前本地预估),
不同 provider 的 tokenizer 差异较大,导致 context compaction 触发时机不准确:
- 估算偏小 → 超出模型上下文窗口,触发 API 错误
- 估算偏大 → 过早压缩,浪费有效上下文
建议方案
将 token 计数逻辑模块化,每个 provider 在自己的模块中实现 countTokens(messages) 方法,
adapter.js 统一分发调用。
各 provider 实现方式
| Provider |
方案 |
精度 |
| DeepSeek / OpenAI / Groq / Gemini |
tiktoken (cl100k_base),本地计算,无需 API 调用 |
高 |
| Anthropic |
client.beta.messages.countTokens(),官方 SDK,精确 |
精确 |
| Ollama |
保留启发式估算作为 fallback |
近似 |
代码结构
src/api/
├── openai-client.js → tiktoken 本地计算
├── anthropic-client.js → SDK countTokens()
└── adapter.js → 统一分发 countTokens(provider, messages)
好处
- compaction 触发时机更准确,充分利用上下文窗口
- 各 provider token 计算逻辑内聚,新增 provider 只需实现对应方法
- 对用户透明,无感知,自动生效
相关文件
src/api/adapter.js
src/api/openai-client.js
src/api/anthropic-client.js
src/chat/agent-loop.js(compaction 触发逻辑)
优先级建议
先实现 DeepSeek(主要用户群)+ Anthropic(已有 SDK),
其他 provider 保留现有 heuristic 作为 fallback。
问题
目前 token 数量通过简单的字符数启发式算法估算(发送请求前本地预估),
不同 provider 的 tokenizer 差异较大,导致 context compaction 触发时机不准确:
建议方案
将 token 计数逻辑模块化,每个 provider 在自己的模块中实现
countTokens(messages)方法,adapter.js统一分发调用。各 provider 实现方式
tiktoken(cl100k_base),本地计算,无需 API 调用client.beta.messages.countTokens(),官方 SDK,精确代码结构
src/api/
├── openai-client.js → tiktoken 本地计算
├── anthropic-client.js → SDK countTokens()
└── adapter.js → 统一分发 countTokens(provider, messages)
好处
相关文件
src/api/adapter.jssrc/api/openai-client.jssrc/api/anthropic-client.jssrc/chat/agent-loop.js(compaction 触发逻辑)优先级建议
先实现 DeepSeek(主要用户群)+ Anthropic(已有 SDK),
其他 provider 保留现有 heuristic 作为 fallback。