Skip to content

feat: 模块化 token 计数,各 provider 使用精确 tokenizer 优化 context compaction #149

@YSMsimon

Description

@YSMsimon

问题

目前 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。

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions