Documentation
¶
Overview ¶
Package compact 提供 eino 框架通用的上下文压缩插件. 实现基于 Claude Code 的 4 层递进压缩体系:
Layer 1: MicroCompact - 规则清理旧工具输出 (<1ms) Layer 2: AutoCompact - 阈值触发 + 断路器 Layer 3: FullCompact - LLM 摘要生成 (5-30s) Layer 4: SessionMemory - 复用已有摘要 (<10ms)
集成方式见 examples/eino_demo/ 目录下的完整示例.
Package compact 提供 eino 框架通用的上下文压缩插件. 实现基于 Claude Code 的 4 层递进压缩体系:
Layer 1: MicroCompact - 规则清理旧工具输出 (<1ms) Layer 2: AutoCompact - 阈值触发 + 断路器 Layer 3: FullCompact - LLM 摘要生成 (5-30s) Layer 4: SessionMemory - 复用已有摘要 (<10ms)
Index ¶
- Constants
- Variables
- func DefaultPinnedMessageFilter(index, total int, msg Message) bool
- func DefaultPromptTooLongDetector(err error) bool
- func EstimateCompactionCost(inputTokens int) (inputEstimate int, outputEstimate int)
- func EstimateMessageTokens(messages []Message) int
- func EstimateMessageTokensPrecise(messages []Message) int
- func EstimateMessageTokensWithCache(messages []Message, cache *TokenCache) int
- func FormatCompactSummary(summary string) string
- func FormatCompactionCost(modelName string, inputTokens, outputTokens int) string
- func GetAutoCompactThreshold(model string, bufferTokens int, maxOutputForSummary int) int
- func GetContextWindow(model string) int
- func GetEffectiveContextWindow(model string, maxOutputForSummary int) int
- func GetNextStepHint(lastAssistantMsg string) string
- func IsUnknownPreset(p ModelPreset) bool
- func LightModelFor(mainModel string) string
- func RoughTokenEstimate(text string) int
- func SnipTokensCalculation(microResult *MicroCompactResult, messages []Message) int
- type AttachmentInjector
- type AutoCompactor
- func (a *AutoCompactor) AutoCompactIfNeeded(ctx context.Context, messages []Message, modelMaxTokens int, ...) (*CompactionResult, error)
- func (a *AutoCompactor) ConsecutiveFailures() int
- func (a *AutoCompactor) GetWarningThreshold(modelMaxTokens int) int
- func (a *AutoCompactor) IsCircuitOpen() bool
- func (a *AutoCompactor) IsNearLimit(messages []Message, modelMaxTokens int) bool
- func (a *AutoCompactor) Reset()
- func (a *AutoCompactor) ShouldAutoCompact(messages []Message, modelMaxTokens int, querySource QuerySource) bool
- type CompactionConfig
- func (c CompactionConfig) AppendFileReadToolNames(names ...string) CompactionConfig
- func (c CompactionConfig) ResetFileReadToolNames() CompactionConfig
- func (c CompactionConfig) WithAutoCompactBufferTokens(n int) CompactionConfig
- func (c CompactionConfig) WithFallbackTruncateMinKeep(n int) CompactionConfig
- func (c CompactionConfig) WithFallbackTruncateRatio(ratio float64) CompactionConfig
- func (c CompactionConfig) WithFileReadToolNames(names ...string) CompactionConfig
- func (c CompactionConfig) WithFileReinjectBudget(n int) CompactionConfig
- func (c CompactionConfig) WithFullCompactMaxRetries(n int) CompactionConfig
- func (c CompactionConfig) WithLogLevel(level LogLevel) CompactionConfig
- func (c CompactionConfig) WithLogger(logger Logger) CompactionConfig
- func (c CompactionConfig) WithMaxOutputTokensForSummary(n int) CompactionConfig
- func (c CompactionConfig) WithMicroCompactCaseInsensitive(v bool) CompactionConfig
- func (c CompactionConfig) WithMicroCompactWhitelist(whitelist map[string]bool) CompactionConfig
- func (c CompactionConfig) WithPinnedMessageFilter(f PinnedMessageFilter) CompactionConfig
- func (c CompactionConfig) WithPostCompact(...) CompactionConfig
- func (c CompactionConfig) WithPreCompact(fn func(ctx context.Context, messages []Message) ([]Message, error)) CompactionConfig
- func (c CompactionConfig) WithPromptTooLongDetector(d PromptTooLongDetector) CompactionConfig
- func (c CompactionConfig) WithRecentFileMaxTokens(n int) CompactionConfig
- func (c CompactionConfig) WithRecentFilesMax(n int) CompactionConfig
- func (c CompactionConfig) WithRecentToolsKeep(n int) CompactionConfig
- func (c CompactionConfig) WithSMMaxTokens(n int) CompactionConfig
- func (c CompactionConfig) WithSMMinTokens(n int) CompactionConfig
- type CompactionHook
- func (h *CompactionHook) PostProcess(ctx context.Context, messages []Message, state interface{}) ([]Message, error)
- func (h *CompactionHook) PreProcess(ctx context.Context, messages []Message, state interface{}) ([]Message, error)
- func (h *CompactionHook) WithCallback(fn func(result *CompactionResult)) *CompactionHook
- func (h *CompactionHook) WithLogLevel(level LogLevel) *CompactionHook
- func (h *CompactionHook) WithLogger(logger Logger) *CompactionHook
- func (h *CompactionHook) WithSilent(silent bool) *CompactionHookdeprecated
- type CompactionInfo
- type CompactionModelConfig
- type CompactionModelStrategy
- type CompactionResult
- type Compactor
- type ContentBlock
- type ContentType
- type DefaultCompactor
- func (c *DefaultCompactor) Compact(ctx context.Context, messages []Message, modelMaxTokens int) (*CompactionResult, error)
- func (c *DefaultCompactor) CompactOnly(messages []Message) []Message
- func (c *DefaultCompactor) CompactWithDirection(ctx context.Context, messages []Message, modelMaxTokens int, direction string, ...) (*CompactionResult, error)
- func (c *DefaultCompactor) Config() CompactionConfig
- func (c *DefaultCompactor) GetAutoCompactor() *AutoCompactor
- func (c *DefaultCompactor) GetFullCompactor() *FullCompactor
- func (c *DefaultCompactor) GetSessionMemoryCompactor() *SessionMemoryCompactor
- func (c *DefaultCompactor) ManualCompact(ctx context.Context, messages []Message, modelMaxTokens int) (*CompactionResult, error)
- func (c *DefaultCompactor) ReactiveCompact(ctx context.Context, messages []Message, modelMaxTokens int) (*CompactionResult, error)
- func (c *DefaultCompactor) Reset()
- func (c *DefaultCompactor) ShouldCompact(messages []Message, modelMaxTokens int) bool
- type FileAttachment
- type FullCompactor
- type InMemorySessionMemoryStore
- func (s *InMemorySessionMemoryStore) AppendMemory(snippet string)
- func (s *InMemorySessionMemoryStore) Clear()
- func (s *InMemorySessionMemoryStore) GetLastSummarizedMessageID(_ context.Context) string
- func (s *InMemorySessionMemoryStore) GetMemory(_ context.Context) (string, error)
- func (s *InMemorySessionMemoryStore) IsEmpty(_ context.Context) bool
- func (s *InMemorySessionMemoryStore) SetLastSummarizedMessageID(id string)
- func (s *InMemorySessionMemoryStore) SetMemory(memory string)
- type LLMClient
- type LLMSummarizer
- type LogLevel
- type Logger
- type Message
- type MicroCompactResult
- type ModelPreset
- func CustomPreset(contextWindow, reservedForSummary int) ModelPreset
- func PresetClaudeHaiku4_5() ModelPreset
- func PresetClaudeOpus4() ModelPreset
- func PresetClaudeSonnet4() ModelPreset
- func PresetClaudeSonnet4_5() ModelPreset
- func PresetDeepSeekV3() ModelPreset
- func PresetForModel(modelName string) ModelPreset
- func PresetGPT4Turbo() ModelPreset
- func PresetGPT4o() ModelPreset
- func PresetGPT4oMini() ModelPreset
- func PresetQwenMax() ModelPreset
- func UnknownPreset() ModelPreset
- type PinnedMessageFilter
- type PromptTooLongDetector
- type QuerySource
- type ReinjectBudget
- type Role
- type Scenario
- type SessionMemoryCompactor
- type SessionMemoryStore
- type Summarizer
- type TokenCache
- type TokenUsage
Constants ¶
const BaseCompactPrompt = noToolsPreamble + `
你正在总结一个 AI Agent 与用户之间的对话。
你的任务是生成一份详细、结构化的摘要,使对话能够从断点处继续,且不丢失上下文。
首先,输出一个 <分析> 块,按时间顺序逐步梳理对话:
1. 逐条查看每条消息
2. 识别用户意图、技术决策和代码模式
3. 特别关注用户反馈 —— 当用户让你做不同的事情时
4. 仔细检查技术准确性和完整性
然后,输出一个 <摘要> 块,包含以下章节:
1. 主要请求和意图:
[详细描述所有用户请求和意图]
2. 关键技术概念:
- [概念 1]
- [概念 2]
3. 文件和代码段:
- [文件名]
- 该文件为什么重要
- 关键代码片段或所做的修改
- [文件名]
- 代码片段
4. 错误与修复:
- [错误描述]:
- 修复方式
- 用户对修复的反馈
5. 问题解决:
[描述已解决的问题和推理过程]
6. 所有用户消息:
- [列出每条非工具结果的用户消息]
7. 待办任务:
- [任务 1]
- [任务 2]
8. 当前工作:
[精确描述当前正在进行的工作,包含文件名和代码片段]
9. 下一步(可选):
[接下来应该做什么,引用最近对话中的原话]
` + noToolsTrailer
BaseCompactPrompt 完整压缩提示词模板.
const CompactBoundaryMarker = "[CompactBoundary]"
CompactBoundaryMarker 压缩边界标记常量。
既出现在生成的边界消息中,也用于 isCompactBoundary 反向识别, 二者必须保持一致 —— 早期版本曾经写入中文 "[压缩边界]" 而识别函数只查找 "[CompactBoundary]",导致 session memory 路径无法找到边界。
const PartialCompactPrompt = noToolsPreamble + `
你正在总结一段较长对话的最近部分。
仅关注最新的消息 —— 对话的早期部分已被单独保留。
输出一个 <分析> 块,后跟一个 <摘要> 块。
<摘要> 必须涵盖完整压缩格式中的第 1-9 节,
但仅限于最近的消息。
不要总结整个对话 —— 仅总结最近的部分。
` + noToolsTrailer
PartialCompactPrompt 部分压缩提示词(from 模式). 只摘要最近的消息,旧消息保留.
const PartialCompactUpToPrompt = noToolsPreamble + `
你正在总结一段对话的早期部分。
摘要点之后的最近消息将被逐字保留。
你的摘要将放在最近消息之前,因此请包含:
除了标准格式中的第 1-9 节外,再添加:
10. 继续工作的上下文:
[提供有助于理解后续最近消息的上下文。
解释发生了什么、做了哪些决策、以及摘要部分结束时工作处于什么状态。
这段上下文对于理解接下来的逐字消息至关重要。]
输出一个 <分析> 块,后跟一个 <摘要> 块。
` + noToolsTrailer
PartialCompactUpToPrompt 部分压缩提示词(up_to 模式). 摘要旧消息,保留新消息。摘要放在开头作为后续消息的前导.
Variables ¶
var CompactableTools = map[string]bool{ "Read": true, "Bash": true, "Grep": true, "Glob": true, "WebSearch": true, "WebFetch": true, "Edit": true, "Write": true, }
CompactableTools 保留向后兼容的可被微压缩工具集合. 若需要自定义白名单,请使用 CompactionConfig.MicroCompactWhitelist.
var DefaultFileReadToolNames = []string{
"Read",
"read_file",
"ReadFile",
"file_read",
"cat",
"view",
"show",
}
DefaultFileReadToolNames 是默认的"文件读取"工具名列表。 附件重注入器会识别这些工具的 tool_result,将其内容在压缩后重新注入上下文。
var ErrPromptTooLong = errors.New("prompt is too long")
ErrPromptTooLong 通用的 prompt-too-long 哨兵错误。
用户实现 LLMClient 时,若能从 SDK 错误中识别出 PTL 类型, 推荐用 fmt.Errorf("...: %w", ErrPromptTooLong) 包裹, 这样 IsPromptTooLongError 会用 errors.Is 准确识别, 避免字符串匹配的误判。
Functions ¶
func DefaultPinnedMessageFilter ¶
DefaultPinnedMessageFilter 默认 pinned 判定规则:
- 首条 user 消息(通常承载原始任务指令)始终保留
- Extra["pinned"] == "true" 的任何消息保留
- Extra["role"] == "system_prompt" 的消息保留(兼容部分接入方约定)
func DefaultPromptTooLongDetector ¶
DefaultPromptTooLongDetector 默认 PTL 判定。
比旧实现更严格:
- 先用 errors.Is 检查 ErrPromptTooLong 哨兵
- 再按完整短语匹配(避免 "400" + "token" 这类宽松匹配)
- 全部检查均在小写化后进行
func EstimateCompactionCost ¶
EstimateCompactionCost 估算一次压缩的 token 消耗.
func EstimateMessageTokens ¶
EstimateMessageTokens 估算消息列表的 token 总数(含保守填充).
func EstimateMessageTokensPrecise ¶
EstimateMessageTokensPrecise 优先使用 API 返回的精确 token 数,不可用时回退到估算.
func EstimateMessageTokensWithCache ¶
func EstimateMessageTokensWithCache(messages []Message, cache *TokenCache) int
EstimateMessageTokensWithCache 与 EstimateMessageTokens 行为一致, 但对长文本块使用 cache 加速.
cache 为 nil 时直接退化为 EstimateMessageTokens(零开销)。
func FormatCompactSummary ¶
FormatCompactSummary 后处理压缩摘要.
操作:
- 删除 <analysis>/<分析> 块(思考草稿,不再有价值)
- 提取 <summary>/<摘要> 内容,替换为可读格式
- 清理多余空行
同时支持中英文标签(向后兼容).
func FormatCompactionCost ¶
FormatCompactionCost 格式化成本信息.
func GetAutoCompactThreshold ¶
GetAutoCompactThreshold 自动压缩触发阈值.
func GetContextWindow ¶
GetContextWindow 根据模型名获取上下文窗口大小. 委托给 PresetForModel 以统一模型预设数据源.
func GetEffectiveContextWindow ¶
GetEffectiveContextWindow 有效上下文窗口 = 总窗口 - 摘要输出预留.
func GetNextStepHint ¶
GetNextStepHint 生成下一步提示(用于压缩后的引导).
func RoughTokenEstimate ¶
RoughTokenEstimate 粗略 token 估算(字符数/4).
func SnipTokensCalculation ¶
func SnipTokensCalculation(microResult *MicroCompactResult, messages []Message) int
SnipTokensCalculation 计算微压缩释放的 token 数.
Types ¶
type AttachmentInjector ¶
type AttachmentInjector struct {
// 最近读取的文件附件(由调用方提供,或从消息历史中自动提取)
RecentFiles []FileAttachment
// Plan 文件内容(可选)
PlanContent string
}
AttachmentInjector 附件重注入器.
func NewAttachmentInjector ¶
func NewAttachmentInjector() *AttachmentInjector
NewAttachmentInjector 创建附件注入器.
func (*AttachmentInjector) InjectAttachments ¶
func (a *AttachmentInjector) InjectAttachments( messages []Message, config CompactionConfig, ) []Message
InjectAttachments 将附件注入压缩后的消息列表.
注入顺序(Claude Code 兼容):
- Plan 文件(如果有)
- 最近读取的文件
- 其他附件
func (*AttachmentInjector) WithPlanContent ¶
func (a *AttachmentInjector) WithPlanContent(content string) *AttachmentInjector
WithPlanContent 设置 Plan 文件内容.
func (*AttachmentInjector) WithRecentFiles ¶
func (a *AttachmentInjector) WithRecentFiles(files []FileAttachment) *AttachmentInjector
WithRecentFiles 设置最近读取的文件.
type AutoCompactor ¶
type AutoCompactor struct {
// contains filtered or unexported fields
}
AutoCompactor 第2层压缩:自动压缩(阈值判断 + 断路器).
核心职责:
- shouldAutoCompact 决策树:判断是否应该触发压缩
- autoCompactIfNeeded 执行流程:SM 优先,回退到传统压缩
- 断路器:连续失败 N 次后停止尝试
断路器状态完全由内部 circuitBreaker 持有,不在外层再维护重复计数器, 避免多 goroutine 下的状态不一致。
func NewAutoCompactor ¶
func NewAutoCompactor( fullCompactor *FullCompactor, sessionCompactor *SessionMemoryCompactor, config CompactionConfig, ) *AutoCompactor
NewAutoCompactor 创建自动压缩器.
func (*AutoCompactor) AutoCompactIfNeeded ¶
func (a *AutoCompactor) AutoCompactIfNeeded( ctx context.Context, messages []Message, modelMaxTokens int, querySource QuerySource, ) (*CompactionResult, error)
AutoCompactIfNeeded 自动压缩执行流程.
流程:
- 断路器检查
- ShouldAutoCompact 判断
- 优先尝试 Session Memory 压缩
- 回退到传统压缩
- 记录失败,触发断路器
func (*AutoCompactor) ConsecutiveFailures ¶
func (a *AutoCompactor) ConsecutiveFailures() int
ConsecutiveFailures 返回当前连续失败次数(用于可观测性与测试).
func (*AutoCompactor) GetWarningThreshold ¶
func (a *AutoCompactor) GetWarningThreshold(modelMaxTokens int) int
GetWarningThreshold 获取警告阈值(token 超过此值发出警告).
func (*AutoCompactor) IsCircuitOpen ¶
func (a *AutoCompactor) IsCircuitOpen() bool
IsCircuitOpen 返回断路器是否已打开(外部只读访问).
func (*AutoCompactor) IsNearLimit ¶
func (a *AutoCompactor) IsNearLimit(messages []Message, modelMaxTokens int) bool
IsNearLimit 判断是否接近上下文限制.
func (*AutoCompactor) ShouldAutoCompact ¶
func (a *AutoCompactor) ShouldAutoCompact( messages []Message, modelMaxTokens int, querySource QuerySource, ) bool
ShouldAutoCompact 决策树:判断是否应该触发自动压缩.
决策树:
- querySource 是 compact 或 session_memory?→ false(防止递归死锁)
- 自动压缩未启用?→ false
- 断路器打开?→ false
- token 数超过阈值?→ true
type CompactionConfig ¶
type CompactionConfig struct {
// 自动压缩阈值相关
AutoCompactEnabled bool `json:"auto_compact_enabled"`
AutoCompactBufferTokens int `json:"auto_compact_buffer_tokens"` // 默认 13K
MaxOutputTokensForSummary int `json:"max_output_tokens_for_summary"` // 默认 20K
WarningThresholdBuffer int `json:"warning_threshold_buffer"` // 默认 20K
// 断路器
MaxConsecutiveFailures int `json:"max_consecutive_failures"` // 默认 3
// Full Compact 重试与降级
FullCompactMaxRetries int `json:"full_compact_max_retries"` // 默认 3
FallbackTruncateRatio float64 `json:"fallback_truncate_ratio"` // 默认 0.3
FallbackTruncateMinKeep int `json:"fallback_truncate_min_keep"` // 默认 4
// Session Memory 配置
SMMinTokens int `json:"sm_min_tokens"` // 默认 10K
SMMaxTokens int `json:"sm_max_tokens"` // 默认 40K
SMMinTextBlockMessages int `json:"sm_min_text_block_msgs"` // 默认 5
// 微压缩
MicroCompactEnabled bool `json:"micro_compact_enabled"`
RecentToolsKeep int `json:"recent_tools_keep"` // 保留最近 N 个工具结果
// MicroCompactWhitelist 微压缩白名单。
// nil 或空 map 表示所有工具结果均可压缩(默认行为)。
// 传入非空 map 时,仅压缩白名单内的工具。
MicroCompactWhitelist map[string]bool `json:"-"`
// MicroCompactCaseInsensitive 白名单是否忽略大小写(默认 true)。
// 设为 true 时,"Read" 可匹配 "read"/"READ"/"Read"。
MicroCompactCaseInsensitive bool `json:"micro_compact_case_insensitive"`
// 模型
ModelName string `json:"model_name"` // 模型名(用于上下文窗口检测)
// 文件重注入
RecentFilesMax int `json:"recent_files_max"` // 默认 5
RecentFileMaxTokens int `json:"recent_file_max_tokens"` // 默认 5000
FileReinjectBudget int `json:"file_reinject_budget"` // 默认 50000
// FileReadToolNames 视为"文件读取"的工具名列表。
FileReadToolNames []string `json:"file_read_tool_names"`
// 回调
OnCompactionStart func(info CompactionInfo) `json:"-"`
OnCompactionEnd func(result CompactionResult) `json:"-"`
// PreCompact 在压缩开始前回调,允许用户改写消息列表。
// 典型用途:敏感信息脱敏、特定消息打标、Pinned 标记的注入。
// 返回的消息列表会替代原列表参与后续压缩。返回 error 时压缩中止。
// nil 表示不处理。
PreCompact func(ctx context.Context, messages []Message) ([]Message, error) `json:"-"`
// PostCompact 在压缩完成后回调,允许用户改写压缩结果。
// 典型用途:附加自定义元数据、二次过滤、上报。
// 返回的结果会替代原结果。返回 error 时整次压缩视为失败。
// nil 表示不处理。
PostCompact func(ctx context.Context, result *CompactionResult) (*CompactionResult, error) `json:"-"`
// PromptTooLongDetector 用户自定义的 PTL 错误判定函数。
// nil 时使用 DefaultPromptTooLongDetector。
// 详见 errors.go。
PromptTooLongDetector PromptTooLongDetector `json:"-"`
// Logger 用户传入的日志实现。
// nil 时使用基于 stdlib log 的默认实现(NewStdLogger)。
// 适配 slog/zap/logrus 时,实现 Logger 接口即可。
Logger Logger `json:"-"`
// LogLevel 日志级别。
// 零值(LogLevelUnset)等同于 LogLevelInfo。
// 仅在 Logger 为 nil 时生效(用户传入的 Logger 自己管理 level)。
LogLevel LogLevel `json:"-"`
// PinnedMessageFilter 判断一条消息是否"必须保留"。
// 在降级截断(fallbackTruncate)等会丢弃消息的路径中,
// 标记为 pinned 的消息会被强制保留在结果中。
// 默认实现:保留首条 user 消息 + 任何 Extra["pinned"]=="true" 的消息。
// nil 时使用 DefaultPinnedMessageFilter。
PinnedMessageFilter PinnedMessageFilter `json:"-"`
}
CompactionConfig 压缩全局配置.
func DefaultCompactionConfig ¶
func DefaultCompactionConfig() CompactionConfig
DefaultCompactionConfig 返回默认配置.
参数值来源于 Claude Code 源码逆向分析(见项目根目录 Claude_Code上下文压缩算法深度分析.md)。 AutoCompact 触发阈值在运行时动态计算:
threshold = modelMaxTokens - MaxOutputTokensForSummary(20K) - AutoCompactBufferTokens(13K)
举例:256K 上下文 → 阈值 = 256K - 20K - 13K = 223K
如需覆盖默认参数,用 Builder 方法链式调整:
config := compact.DefaultCompactionConfig().
WithAutoCompactBufferTokens(10_000).
WithRecentToolsKeep(2)
func PresetForScenario ¶
func PresetForScenario(s Scenario) CompactionConfig
PresetForScenario 根据场景返回调优过的默认配置.
用户可在返回值上继续链式调整:
cfg := compact.PresetForScenario(compact.ScenarioCodingAgent).
WithRecentToolsKeep(5)
未识别场景时返回 DefaultCompactionConfig().
func (CompactionConfig) AppendFileReadToolNames ¶
func (c CompactionConfig) AppendFileReadToolNames(names ...string) CompactionConfig
AppendFileReadToolNames 追加文件读取工具名.
func (CompactionConfig) ResetFileReadToolNames ¶
func (c CompactionConfig) ResetFileReadToolNames() CompactionConfig
ResetFileReadToolNames 恢复为默认文件读取工具名列表.
func (CompactionConfig) WithAutoCompactBufferTokens ¶
func (c CompactionConfig) WithAutoCompactBufferTokens(n int) CompactionConfig
WithAutoCompactBufferTokens 设置自动压缩缓冲 tokens.
func (CompactionConfig) WithFallbackTruncateMinKeep ¶
func (c CompactionConfig) WithFallbackTruncateMinKeep(n int) CompactionConfig
WithFallbackTruncateMinKeep 设置降级截断最少保留消息数.
func (CompactionConfig) WithFallbackTruncateRatio ¶
func (c CompactionConfig) WithFallbackTruncateRatio(ratio float64) CompactionConfig
WithFallbackTruncateRatio 设置降级截断保留比例(0~1).
func (CompactionConfig) WithFileReadToolNames ¶
func (c CompactionConfig) WithFileReadToolNames(names ...string) CompactionConfig
WithFileReadToolNames 直接替换文件读取工具名列表.
func (CompactionConfig) WithFileReinjectBudget ¶
func (c CompactionConfig) WithFileReinjectBudget(n int) CompactionConfig
WithFileReinjectBudget 设置附件重注入总预算 tokens.
func (CompactionConfig) WithFullCompactMaxRetries ¶
func (c CompactionConfig) WithFullCompactMaxRetries(n int) CompactionConfig
WithFullCompactMaxRetries 设置 Full Compact 最大重试次数.
func (CompactionConfig) WithLogLevel ¶
func (c CompactionConfig) WithLogLevel(level LogLevel) CompactionConfig
WithLogLevel 设置默认 logger 的日志级别(仅当未提供自定义 Logger 时生效).
func (CompactionConfig) WithLogger ¶
func (c CompactionConfig) WithLogger(logger Logger) CompactionConfig
WithLogger 设置自定义 Logger。
用户可适配 slog/zap/logrus —— 实现 Logger 接口即可。 nil 时回退到内置默认 logger(受 LogLevel 控制)。
func (CompactionConfig) WithMaxOutputTokensForSummary ¶
func (c CompactionConfig) WithMaxOutputTokensForSummary(n int) CompactionConfig
WithMaxOutputTokensForSummary 设置摘要最大输出 tokens.
func (CompactionConfig) WithMicroCompactCaseInsensitive ¶
func (c CompactionConfig) WithMicroCompactCaseInsensitive(v bool) CompactionConfig
WithMicroCompactCaseInsensitive 设置白名单是否忽略大小写(默认 true)。
func (CompactionConfig) WithMicroCompactWhitelist ¶
func (c CompactionConfig) WithMicroCompactWhitelist(whitelist map[string]bool) CompactionConfig
WithMicroCompactWhitelist 设置微压缩白名单. nil 或空 map 表示所有工具结果均可压缩。
func (CompactionConfig) WithPinnedMessageFilter ¶
func (c CompactionConfig) WithPinnedMessageFilter(f PinnedMessageFilter) CompactionConfig
WithPinnedMessageFilter 设置 pinned 消息判定函数(用于降级截断保留关键消息).
func (CompactionConfig) WithPostCompact ¶
func (c CompactionConfig) WithPostCompact( fn func(ctx context.Context, result *CompactionResult) (*CompactionResult, error), ) CompactionConfig
WithPostCompact 注册压缩后回调。
钩子返回的结果会替代原结果。 返回 error 时本次压缩视为失败(会影响断路器计数)。
func (CompactionConfig) WithPreCompact ¶
func (c CompactionConfig) WithPreCompact( fn func(ctx context.Context, messages []Message) ([]Message, error), ) CompactionConfig
WithPreCompact 注册压缩前回调。
钩子返回的消息列表会替代原列表参与后续压缩。 返回 error 时整次压缩中止(不会触发 PostCompact)。
func (CompactionConfig) WithPromptTooLongDetector ¶
func (c CompactionConfig) WithPromptTooLongDetector(d PromptTooLongDetector) CompactionConfig
WithPromptTooLongDetector 设置用户自定义的 PTL 错误判定函数.
func (CompactionConfig) WithRecentFileMaxTokens ¶
func (c CompactionConfig) WithRecentFileMaxTokens(n int) CompactionConfig
WithRecentFileMaxTokens 设置单个文件最大 tokens.
func (CompactionConfig) WithRecentFilesMax ¶
func (c CompactionConfig) WithRecentFilesMax(n int) CompactionConfig
WithRecentFilesMax 设置最大跟踪文件数.
func (CompactionConfig) WithRecentToolsKeep ¶
func (c CompactionConfig) WithRecentToolsKeep(n int) CompactionConfig
WithRecentToolsKeep 设置保留最近工具结果的数量.
func (CompactionConfig) WithSMMaxTokens ¶
func (c CompactionConfig) WithSMMaxTokens(n int) CompactionConfig
WithSMMaxTokens 设置 Session Memory 最大存储 tokens.
func (CompactionConfig) WithSMMinTokens ¶
func (c CompactionConfig) WithSMMinTokens(n int) CompactionConfig
WithSMMinTokens 设置 Session Memory 最小触发 tokens.
type CompactionHook ¶
type CompactionHook struct {
// Compactor 压缩器实例 (必填).
Compactor *DefaultCompactor
// ModelMaxTokens 模型上下文窗口大小 (默认 200_000).
ModelMaxTokens int
// MicroCompactOnly 仅执行微压缩,不触发自动压缩 (默认 false).
// 设为 true 时,Hook 仅做每轮工具结果清理,不做 LLM 摘要.
MicroCompactOnly bool
// Silent 静默模式,关闭日志 (默认 false).
//
// Deprecated: 使用 Logger / LogLevel 进行更细粒度控制。
// 当 Logger 为 nil 时,Silent=true 等价于 LogLevel=LogLevelSilent。
Silent bool
// Logger 自定义日志实现。
// nil 时使用 Compactor.Config().Logger,再 fallback 到默认 logger。
Logger Logger
// LogLevel 当未提供 Logger 时控制默认 logger 的级别。
LogLevel LogLevel
// OnCompacted 压缩完成回调 (可选).
// 可用于记录指标、审计日志.
OnCompacted func(result *CompactionResult)
}
CompactionHook 压缩钩子配置.
零值可用 (字段均为可选):
hook := &CompactionHook{Compactor: compactor, ModelMaxTokens: 200_000}
func NewCompactionHook ¶
func NewCompactionHook(compactor *DefaultCompactor, modelMaxTokens int) *CompactionHook
NewCompactionHook 创建压缩钩子.
func NewMicroCompactHook ¶
func NewMicroCompactHook(compactor *DefaultCompactor) *CompactionHook
NewMicroCompactHook 创建仅微压缩的钩子(最轻量,无 LLM 调用).
func (*CompactionHook) PostProcess ¶
func (h *CompactionHook) PostProcess(ctx context.Context, messages []Message, state interface{}) ([]Message, error)
PostProcess 在 ChatModel 调用后执行(可用于记录 token 使用).
func (*CompactionHook) PreProcess ¶
func (h *CompactionHook) PreProcess(ctx context.Context, messages []Message, state interface{}) ([]Message, error)
PreProcess 在 ChatModel 调用前执行压缩.
此方法签名兼容 eino 的 StatePreHandler. 实际集成时签名需匹配 eino 的 func(ctx, []*schema.Message, state) ([]*schema.Message, error).
func (*CompactionHook) WithCallback ¶
func (h *CompactionHook) WithCallback(fn func(result *CompactionResult)) *CompactionHook
WithCallback 设置压缩完成回调.
func (*CompactionHook) WithLogLevel ¶
func (h *CompactionHook) WithLogLevel(level LogLevel) *CompactionHook
WithLogLevel 设置默认 logger 的级别.
func (*CompactionHook) WithLogger ¶
func (h *CompactionHook) WithLogger(logger Logger) *CompactionHook
WithLogger 设置自定义 Logger.
func (*CompactionHook) WithSilent
deprecated
func (h *CompactionHook) WithSilent(silent bool) *CompactionHook
WithSilent 设置静默模式.
Deprecated: 使用 WithLogger(compact.NewNopLogger()) 或 WithLogLevel(compact.LogLevelSilent) 替代。
type CompactionInfo ¶
type CompactionInfo struct {
Trigger string `json:"trigger"`
TokensBefore int `json:"tokens_before"`
Threshold int `json:"threshold"`
Layer int `json:"layer"`
}
CompactionInfo 压缩事件信息.
type CompactionModelConfig ¶
type CompactionModelConfig struct {
Strategy CompactionModelStrategy // 策略
MainModel string // 主 agent 模型名
CustomModel string // 自定义模型名(仅 StrategyCustomModel 时生效)
}
CompactionModelConfig 压缩模型配置.
func (*CompactionModelConfig) ResolveModel ¶
func (c *CompactionModelConfig) ResolveModel() string
ResolveModel 根据策略解析实际使用的压缩模型.
type CompactionModelStrategy ¶
type CompactionModelStrategy string
CompactionModelStrategy 压缩模型选择策略.
const ( // StrategySameModel 复用主 agent 模型 —— 摘要质量最高,cache 可共享. StrategySameModel CompactionModelStrategy = "same_model" // StrategyLightModel 使用轻量模型 —— 成本低速度快,推荐用于日常. StrategyLightModel CompactionModelStrategy = "light_model" // StrategyCustomModel 自定义模型 —— 完全由调用方指定. StrategyCustomModel CompactionModelStrategy = "custom" )
type CompactionResult ¶
type CompactionResult struct {
WasCompacted bool `json:"was_compacted"`
Messages []Message `json:"messages"`
TokensBefore int `json:"tokens_before"`
TokensAfter int `json:"tokens_after"`
Trigger string `json:"trigger"`
Summary string `json:"summary,omitempty"`
BoundaryMarker bool `json:"boundary_marker,omitempty"`
}
CompactionResult 压缩结果.
func PartialCompact ¶
func PartialCompact( ctx context.Context, fullCompactor *FullCompactor, messages []Message, splitIndex int, direction string, ) (*CompactionResult, error)
PartialCompact 部分压缩:只压缩一部分消息.
direction:
- "from": 保留旧消息,只摘要最近消息(默认)
- "up_to": 摘要旧消息,保留新消息
type Compactor ¶
type Compactor interface {
Compact(ctx context.Context, messages []Message, modelMaxTokens int) (*CompactionResult, error)
ShouldCompact(messages []Message, modelMaxTokens int) bool
Reset()
}
Compactor 上下文压缩器接口.
type ContentBlock ¶
type ContentBlock struct {
Type ContentType `json:"type"`
Text string `json:"text,omitempty"`
ToolName string `json:"tool_name,omitempty"`
ToolInput string `json:"tool_input,omitempty"`
ToolUseID string `json:"tool_use_id,omitempty"`
ToolOutput string `json:"tool_output,omitempty"`
Thinking string `json:"thinking,omitempty"`
}
ContentBlock 消息内容块.
type ContentType ¶
type ContentType string
ContentType 内容块类型.
const ( ContentTypeText ContentType = "text" ContentTypeToolUse ContentType = "tool_use" ContentTypeToolResult ContentType = "tool_result" ContentTypeImage ContentType = "image" ContentTypeThinking ContentType = "thinking" )
type DefaultCompactor ¶
type DefaultCompactor struct {
// contains filtered or unexported fields
}
DefaultCompactor 默认压缩器——编排 4 层压缩体系.
每轮查询前执行:
用户消息 → [Layer 1: MicroCompact] → [Layer 2: AutoCompact] → API 调用
↓ ↓
细粒度清理旧工具输出 阈值触发时:
(不丢语义, <1ms) → Layer 4: Session Memory (<10ms)
→ Layer 3: Full Compact (5-30s)
实现 Compactor 接口,可作为 eino 组件使用.
func NewDefaultCompactor ¶
func NewDefaultCompactor( config CompactionConfig, summarizer Summarizer, memoryStore SessionMemoryStore, ) *DefaultCompactor
NewDefaultCompactor 创建默认压缩器.
参数:
- config: 压缩配置
- summarizer: LLM 摘要生成器(用于 FullCompact,可为 nil 禁用第3层)
- memoryStore: Session Memory 存储(用于第4层,可为 nil 禁用)
func (*DefaultCompactor) Compact ¶
func (c *DefaultCompactor) Compact( ctx context.Context, messages []Message, modelMaxTokens int, ) (*CompactionResult, error)
Compact 对消息列表执行完整的压缩管线.
管线:
- PreCompact 钩子(用户可改写消息列表)
- MicroCompact: 清理旧的工具输出
- AutoCompact: 如果超过阈值,触发 SM 或 Full Compact
- PostCompact 钩子(用户可改写压缩结果)
func (*DefaultCompactor) CompactOnly ¶
func (c *DefaultCompactor) CompactOnly(messages []Message) []Message
CompactOnly 仅执行 MicroCompact(不触发 AutoCompact).
func (*DefaultCompactor) CompactWithDirection ¶
func (c *DefaultCompactor) CompactWithDirection( ctx context.Context, messages []Message, modelMaxTokens int, direction string, splitIndex int, ) (*CompactionResult, error)
CompactWithDirection 支持部分压缩方向的完整压缩.
func (*DefaultCompactor) Config ¶
func (c *DefaultCompactor) Config() CompactionConfig
Config 获取压缩配置.
func (*DefaultCompactor) GetAutoCompactor ¶
func (c *DefaultCompactor) GetAutoCompactor() *AutoCompactor
GetAutoCompactor 获取内部 AutoCompactor(用于高级定制).
func (*DefaultCompactor) GetFullCompactor ¶
func (c *DefaultCompactor) GetFullCompactor() *FullCompactor
GetFullCompactor 获取内部 FullCompactor(用于高级定制).
func (*DefaultCompactor) GetSessionMemoryCompactor ¶
func (c *DefaultCompactor) GetSessionMemoryCompactor() *SessionMemoryCompactor
GetSessionMemoryCompactor 获取内部 SessionMemoryCompactor(用于高级定制).
func (*DefaultCompactor) ManualCompact ¶
func (c *DefaultCompactor) ManualCompact( ctx context.Context, messages []Message, modelMaxTokens int, ) (*CompactionResult, error)
ManualCompact 手动触发压缩(绕过阈值检查).
func (*DefaultCompactor) ReactiveCompact ¶
func (c *DefaultCompactor) ReactiveCompact( ctx context.Context, messages []Message, modelMaxTokens int, ) (*CompactionResult, error)
ReactiveCompact 响应式压缩 —— API 调用失败后调用.
场景:API 返回 prompt-too-long 错误,需要紧急截断消息以继续对话。 与主动压缩不同,响应式压缩:
- 不调用 LLM 生成摘要(避免再次触发 PTL)
- 直接执行降级截断,保留最近消息
- 使用更激进的保留比例(默认 20%)
这是 Claude Code 5 层错误恢复中的第 2 层。
func (*DefaultCompactor) ShouldCompact ¶
func (c *DefaultCompactor) ShouldCompact(messages []Message, modelMaxTokens int) bool
ShouldCompact 判断是否应该触发压缩.
type FileAttachment ¶
FileAttachment 文件附件信息.
func ExtractRecentFilesFromMessages ¶
func ExtractRecentFilesFromMessages(messages []Message, config CompactionConfig) []FileAttachment
ExtractRecentFilesFromMessages 从消息历史中自动提取最近读取的文件.
扫描配置中指定的"文件读取"工具(FileReadToolNames)的 tool_result, 按出现顺序收集文件内容。
路径来源优先级:
- tool_use 的 ToolInput 中解析 file_path(如 {"file_path":"main.go"})
- tool_result 内容开头的文件路径标记(如 "// file: main.go")
- tool_use_id 作为回退标识
type FullCompactor ¶
type FullCompactor struct {
// contains filtered or unexported fields
}
FullCompactor 第3层压缩:LLM 摘要生成(传统压缩).
使用 Fork Agent 模式:传入全部消息,生成结构化摘要。 核心机制:
- 预处理管线: stripImages → stripReinjected → normalize
- 结构化输出: <analysis> 思考草稿 + <summary> 9 章节摘要
- 重试: 当 LLM 调用失败时最多重试 N 次
- PTL 重试: 当压缩请求自身超限时裁剪最旧消息重试
- 降级截断: 重试全部失败后,直接截断旧消息并保留最近消息
func NewFullCompactor ¶
func NewFullCompactor(summarizer Summarizer, config CompactionConfig) *FullCompactor
NewFullCompactor 创建传统压缩器.
func (*FullCompactor) Compact ¶
func (f *FullCompactor) Compact( ctx context.Context, messages []Message, promptTemplate string, partialDirection string, ) (*CompactionResult, error)
Compact 执行传统压缩.
执行流程:
- 预处理消息(替换图片等)
- 调用 LLM 生成摘要(带重试 + PTL 重试)
- 重试全部失败 → 执行降级截断(fallback truncate)
type InMemorySessionMemoryStore ¶
type InMemorySessionMemoryStore struct {
// contains filtered or unexported fields
}
InMemorySessionMemoryStore 是 SessionMemoryStore 的开箱即用内存实现.
适用场景:
- 单进程 / 单会话的开发与示例代码
- 评测脚本、测试用例
- 接入真正的持久层(Redis/SQL/向量库)之前的快速原型
不适用场景:
- 多副本 / 多用户的生产环境(应自行实现持久化 + 隔离的 Store)
线程安全:所有访问通过 RWMutex 保护,读多写少的并发负载下性能良好.
func NewInMemorySessionMemoryStore ¶
func NewInMemorySessionMemoryStore() *InMemorySessionMemoryStore
NewInMemorySessionMemoryStore 创建空的内存 Session Memory.
func (*InMemorySessionMemoryStore) AppendMemory ¶
func (s *InMemorySessionMemoryStore) AppendMemory(snippet string)
AppendMemory 追加一段 memory 内容,原子操作.
用于"增量更新"模式:每轮对话后追加一段新摘要片段,避免覆盖之前的累积. 自动在原 memory 与新内容之间插入空行分隔.
func (*InMemorySessionMemoryStore) Clear ¶
func (s *InMemorySessionMemoryStore) Clear()
Clear 重置 memory 与 lastSummarizedMessageID.
func (*InMemorySessionMemoryStore) GetLastSummarizedMessageID ¶
func (s *InMemorySessionMemoryStore) GetLastSummarizedMessageID(_ context.Context) string
GetLastSummarizedMessageID 返回上次被纳入摘要的消息 ID.
func (*InMemorySessionMemoryStore) GetMemory ¶
func (s *InMemorySessionMemoryStore) GetMemory(_ context.Context) (string, error)
GetMemory 返回当前累积的 Session Memory 文本.
func (*InMemorySessionMemoryStore) IsEmpty ¶
func (s *InMemorySessionMemoryStore) IsEmpty(_ context.Context) bool
IsEmpty 当 memory 为空白时返回 true.
func (*InMemorySessionMemoryStore) SetLastSummarizedMessageID ¶
func (s *InMemorySessionMemoryStore) SetLastSummarizedMessageID(id string)
SetLastSummarizedMessageID 记录最近一次被纳入摘要的消息 ID.
SessionMemoryCompactor 据此判断哪些消息已被摘要、哪些应原样保留.
func (*InMemorySessionMemoryStore) SetMemory ¶
func (s *InMemorySessionMemoryStore) SetMemory(memory string)
SetMemory 覆盖当前 memory(典型用法:后台记忆提取协程定期写入).
type LLMClient ¶
type LLMClient interface {
// Chat 发送消息并获取回复文本.
Chat(ctx context.Context, prompt string, messages []Message) (string, error)
}
LLMClient 通用 LLM 客户端接口(兼容 eino ChatModel 和直接 API 调用).
type LLMSummarizer ¶
type LLMSummarizer struct {
// contains filtered or unexported fields
}
LLMSummarizer 基于通用 LLM 客户端的摘要生成器.
func NewLLMSummarizer ¶
func NewLLMSummarizer(client LLMClient, modelName string) *LLMSummarizer
NewLLMSummarizer 创建 LLM 摘要生成器.
func NewSummarizer ¶
func NewSummarizer(cfg CompactionModelConfig, client LLMClient) *LLMSummarizer
NewSummarizer 根据策略创建摘要生成器.
func NewSummarizerWithClient ¶
func NewSummarizerWithClient(client LLMClient, modelName string) *LLMSummarizer
NewSummarizerWithClient 用用户传入的 LLMClient 创建摘要器.
func (*LLMSummarizer) GenerateSummary ¶
GenerateSummary 实现 Summarizer 接口.
func (*LLMSummarizer) WithPrompt ¶
func (s *LLMSummarizer) WithPrompt(prompt string) *LLMSummarizer
WithPrompt 自定义压缩提示词.
type LogLevel ¶
type LogLevel int
LogLevel 日志级别.
零值(LogLevelUnset)会被 getLogger 解释为 LogLevelInfo —— 这样用户在 CompactionConfig 中不显式设置 LogLevel 时仍能拿到合理默认行为, 同时不破坏 LogLevelDebug 的可达性。
const ( // LogLevelUnset 零值,等同于 LogLevelInfo. LogLevelUnset LogLevel = iota // LogLevelDebug 详细诊断信息,仅用于排查问题. LogLevelDebug // LogLevelInfo 常规事件,如压缩触发、阈值穿越. LogLevelInfo // LogLevelWarn 异常但可恢复的情况,如断路器即将触发. LogLevelWarn // LogLevelError 操作失败,需要外部关注. LogLevelError // LogLevelSilent 静默,关闭所有输出. LogLevelSilent )
func ParseLogLevel ¶
ParseLogLevel 从字符串解析日志级别(大小写不敏感). 未识别时返回 LogLevelInfo.
type Logger ¶
type Logger interface {
Debug(msg string, args ...any)
Info(msg string, args ...any)
Warn(msg string, args ...any)
Error(msg string, args ...any)
}
Logger 结构化日志接口。
设计目标:
- 不绑定到具体日志库(slog/zap/logrus 均可适配)
- args 采用 (key, value, key, value, ...) 形式,与 slog 兼容
- 用户传入自定义实现即可对接生产日志系统
实现示例(slog 适配):
type SlogAdapter struct{ Logger *slog.Logger }
func (s SlogAdapter) Debug(msg string, args ...any) { s.Logger.Debug(msg, args...) }
func (s SlogAdapter) Info(msg string, args ...any) { s.Logger.Info(msg, args...) }
func (s SlogAdapter) Warn(msg string, args ...any) { s.Logger.Warn(msg, args...) }
func (s SlogAdapter) Error(msg string, args ...any) { s.Logger.Error(msg, args...) }
func GetLogger ¶
func GetLogger(config CompactionConfig) Logger
GetLogger 是 getLogger 的导出版本,供 eino 适配器等子包使用.
不保证线程安全 —— 与底层 stdLogger 一致,每次调用产生新实例。 如需复用同一实例,请在 CompactionConfig.Logger 中显式注入。
func NewDefaultLogger ¶
func NewDefaultLogger() Logger
NewDefaultLogger 返回默认 logger(INFO 级别,stderr 输出).
type Message ¶
type Message struct {
Role Role `json:"role"`
Content []ContentBlock `json:"content"`
// Meta 元数据字段
MessageID string `json:"message_id,omitempty"`
Usage *TokenUsage `json:"usage,omitempty"`
Extra map[string]string `json:"extra,omitempty"`
}
Message 通用消息类型,兼容 eino schema.Message.
func CreateCompactBoundary ¶
CreateCompactBoundary 创建压缩边界标记消息.
标记同时包含英文 [CompactBoundary] 与中文 [压缩边界],以便:
- 程序检测:依赖固定英文标记,避免本地化文案漂移
- 人工阅读:中文标签让对话调试时更易识别
func GetCompactUserSummaryMessage ¶
func GetCompactUserSummaryMessage(summary string, suppressFollowUp bool, recentPreserved bool) Message
GetCompactUserSummaryMessage 生成压缩后的摘要用户消息.
func TopologicalSortMessages ¶
TopologicalSortMessages 按拓扑顺序排列消息(确保 tool_use 在 tool_result 之前).
type MicroCompactResult ¶
type MicroCompactResult struct {
WasCompacted bool
TokensFreed int
ToolsCleared int
Messages []Message
}
MicroCompactResult 微压缩结果.
func MicroCompact ¶
func MicroCompact(messages []Message, keepRecent int, caseInsensitive bool, whitelist ...map[string]bool) *MicroCompactResult
MicroCompact 第1层压缩:纯规则操作,清理旧的工具输出结果.
不调用 LLM,不丢语义信息。遍历消息列表,将旧的可压缩工具结果替换为 "[Old tool result content cleared]",同时保留最近的 N 个工具结果.
特点:
- <1ms 延迟
- 不修改 tool_use 块(保持配对完整性)
- 保留最近 N 个工具结果
- 不传入 whitelist 时,默认**所有**工具结果均可压缩
- caseInsensitive 控制白名单是否忽略大小写
func MicroCompactTimeBased ¶
func MicroCompactTimeBased(messages []Message, keepRecent int) *MicroCompactResult
MicroCompactTimeBased 时间触发的微压缩(子路径 A).
当缓存已过期时使用此路径。与 MicroCompact 逻辑相同,但额外清理 时间戳标记,以便后续处理知道哪些结果已被清除.
func MicroCompactWithConfig ¶
func MicroCompactWithConfig(messages []Message, config CompactionConfig) *MicroCompactResult
MicroCompactWithConfig 使用 CompactionConfig 进行微压缩(推荐)。
type ModelPreset ¶
type ModelPreset struct {
Name string // 模型显示名
ContextWindow int // 总上下文窗口 (tokens)
MaxOutputTokens int // 模型最大输出 (tokens)
ReservedForSummary int // 留给摘要输出的预算 (默认 20K)
BufferTokens int // 自动压缩缓冲 (默认 13K)
}
ModelPreset 模型预设 —— 预定义的窗口大小和推荐配置.
使用方式:
preset := PresetClaudeOpus4() // 推荐:按模型选择
preset := PresetForModel("sonnet") // 自动匹配
func CustomPreset ¶
func CustomPreset(contextWindow, reservedForSummary int) ModelPreset
CustomPreset 创建自定义预设.
只需填关键参数,其他使用默认值:
preset := compact.CustomPreset(100_000, 8_000) // 100K 窗口, 8K 输入
func PresetClaudeHaiku4_5 ¶
func PresetClaudeHaiku4_5() ModelPreset
func PresetClaudeSonnet4 ¶
func PresetClaudeSonnet4() ModelPreset
func PresetClaudeSonnet4_5 ¶
func PresetClaudeSonnet4_5() ModelPreset
func PresetForModel ¶
func PresetForModel(modelName string) ModelPreset
PresetForModel 根据模型名自动选择预设. 匹配规则:模型名转小写后按关键词匹配. 未匹配到任何已知模型时返回 UnknownPreset,调用方应通过 IsUnknownPreset 检测并提示用户显式传入 WithModelMaxTokens()。
func PresetGPT4Turbo ¶
func PresetGPT4Turbo() ModelPreset
func PresetGPT4oMini ¶
func PresetGPT4oMini() ModelPreset
func UnknownPreset ¶
func UnknownPreset() ModelPreset
UnknownPreset 表示未知模型的兜底预设。 Name 以 "Unknown" 开头,便于 IsUnknownPreset 识别。
注意:兜底窗口仍设为 128K 以便程序能继续运行,但调用方必须意识到 这只是一个保守猜测。理想情况下,用户应通过 WithModelMaxTokens() 显式覆盖,否则真实窗口超出此值时阈值不会触发, 真实窗口小于此值时则会被 API 直接拒绝。
func (ModelPreset) AutoCompactThreshold ¶
func (p ModelPreset) AutoCompactThreshold() int
AutoCompactThreshold 该预设下的自动压缩触发阈值.
阈值 = ContextWindow - max(ReservedForSummary, MaxOutputTokens) - BufferTokens
func (ModelPreset) EffectiveWindow ¶
func (p ModelPreset) EffectiveWindow() int
EffectiveWindow 该预设下的有效上下文窗口.
func (ModelPreset) WithBuffer ¶
func (p ModelPreset) WithBuffer(tokens int) ModelPreset
WithBuffer 自定义缓冲大小.
func (ModelPreset) WithName ¶
func (p ModelPreset) WithName(name string) ModelPreset
WithName 设置显示名.
type PinnedMessageFilter ¶
PinnedMessageFilter 判断一条消息是否在降级截断中必须保留。
参数:
- index: 该消息在原始列表中的位置
- total: 原始列表的总长度
- msg: 被判断的消息本体
返回 true 表示"必须保留"。Pinned 消息会被附加到截断后保留消息的前面(按原始顺序)。
type PromptTooLongDetector ¶
PromptTooLongDetector 用户自定义的 PTL 错误判断函数。
不同 LLM SDK 返回的错误结构不同(Anthropic 用 *anthropic.Error, OpenAI 用 *openai.APIError,eino 透传原始错误等)。 通过此钩子,用户可以传入针对自家 SDK 的精确判定逻辑。
nil 表示使用默认实现(DefaultPromptTooLongDetector)。
type QuerySource ¶
type QuerySource string
QuerySource 查询来源类型.
const ( QuerySourceNormal QuerySource = "normal" QuerySourceCompact QuerySource = "compact" QuerySourceSessionMemory QuerySource = "session_memory" )
type ReinjectBudget ¶
type ReinjectBudget struct {
// contains filtered or unexported fields
}
ReinjectBudget 文件重注入预算管理.
压缩后重新注入最近读取的文件,以保持上下文连续性。 预算控制:
- 最近 N 个文件(默认 5)
- 每个文件 ≤ maxTokens(默认 5K)
- 总预算 ≤ budget(默认 50K tokens)
func DefaultReinjectBudget ¶
func DefaultReinjectBudget() *ReinjectBudget
DefaultReinjectBudget 默认重注入预算.
func NewReinjectBudget ¶
func NewReinjectBudget(maxFiles, maxTokens, budget int) *ReinjectBudget
NewReinjectBudget 创建文件重注入预算管理器.
func (*ReinjectBudget) SelectFiles ¶
func (r *ReinjectBudget) SelectFiles(files []FileAttachment) []FileAttachment
SelectFiles 从文件列表中选择可重注入的文件.
策略:
- 按最近使用排序(调用方保证顺序)
- 逐个检查 token 预算
- 在总预算内尽可能多地包含文件
type Scenario ¶
type Scenario string
Scenario 压缩场景类型 —— 不同应用场景对压缩策略的偏好不同.
通过 PresetForScenario 一键拿到针对该场景调优过的 CompactionConfig, 避免每个用户都重新摸索"缓冲该设多大、文件该重注入多少"等参数。
const ( // ScenarioCodingAgent 编码代理:长对话、大量 tool_result、文件读取频繁. // // 特点: // - RecentToolsKeep 较大(保留更多最近工具结果,便于 LLM 引用) // - FileReinjectBudget 充裕(鼓励重注入文件给后续轮次使用) // - 自动压缩缓冲略大(避免一次压缩后立即又超阈值) ScenarioCodingAgent Scenario = "coding_agent" // ScenarioCustomerSupport 客服 / 长会话问答:以纯文本对话为主、少工具调用. // // 特点: // - 微压缩白名单缩窄(少量工具,无需激进压缩) // - SMMinTokens / SMMaxTokens 较小(早摘要、早释放) // - 文件重注入预算很小(很少读文件) ScenarioCustomerSupport Scenario = "customer_support" // ScenarioResearchAnalysis 研究分析:多检索 / 多 RAG 调用、上下文跨多份文档. // // 特点: // - RecentToolsKeep 较大(保留最近检索结果链) // - SMMaxTokens 较大(允许 session memory 容纳更多源信息) // - 摘要预算较大(让 LLM 生成更详尽摘要) ScenarioResearchAnalysis Scenario = "research_analysis" // ScenarioLightweight 轻量 / 嵌入式:尽可能少触发 LLM 压缩,省 token. // // 特点: // - 关闭 Session Memory(SMMinTokens 设大到等同于禁用) // - 降级截断更激进(保留 25% 即可) // - 微压缩开启但 RecentToolsKeep 调小 ScenarioLightweight Scenario = "lightweight" )
type SessionMemoryCompactor ¶
type SessionMemoryCompactor struct {
// contains filtered or unexported fields
}
SessionMemoryCompactor 第4层压缩:复用已有 Session Memory 作为摘要.
不调用 LLM,直接使用后台记忆提取积累的 Session Memory。 优势:
- <10ms 延迟
- 质量可预测(渐进更新,非一次性压缩)
- 保留近期消息
func NewSessionMemoryCompactor ¶
func NewSessionMemoryCompactor(store SessionMemoryStore, config CompactionConfig) *SessionMemoryCompactor
NewSessionMemoryCompactor 创建 Session Memory 压缩器.
func (*SessionMemoryCompactor) TryCompact ¶
func (s *SessionMemoryCompactor) TryCompact( ctx context.Context, messages []Message, autoCompactThreshold int, ) (*CompactionResult, error)
TryCompact 尝试使用 Session Memory 进行压缩. 返回 nil 表示不适用或失败,需要回退到传统压缩.
type SessionMemoryStore ¶
type SessionMemoryStore interface {
GetMemory(ctx context.Context) (string, error)
GetLastSummarizedMessageID(ctx context.Context) string
IsEmpty(ctx context.Context) bool
}
SessionMemoryStore Session Memory 存储接口.
type Summarizer ¶
type Summarizer interface {
GenerateSummary(ctx context.Context, messages []Message) (string, error)
}
Summarizer LLM 摘要生成接口,用于 FullCompact.
type TokenCache ¶
type TokenCache struct {
// contains filtered or unexported fields
}
TokenCache 是一个并发安全的 LRU,用于缓存"内容串 → token 数"映射.
设计目标:
- 默认 *不启用*:调用方按需创建并通过 EstimateMessageTokensWithCache 显式传入
- 只缓存大块内容(短串本来就 O(len/4),缓存反而更慢)
- 用 FNV-1a 而非加密哈希,键空间冲突可以接受 —— 估算误差最多偏 1 个 block
适用场景:
- Agent 主循环里同一批消息会被 ShouldCompact + Compact 反复扫描
- 单元测试 / benchmark 场景反复构造相似消息
不适用场景:
- 消息内容每次都变化(命中率低,反而是负优化)
func NewTokenCache ¶
func NewTokenCache(capacity int) *TokenCache
NewTokenCache 创建容量为 capacity 的 LRU。
capacity <= 0 时强制使用 1024 —— 太小的缓存价值不大,太大又容易吃内存。 minBlockLen 控制只缓存 len(content) >= 阈值的块(默认 512 字符)。
func (*TokenCache) EstimateBlock ¶
func (c *TokenCache) EstimateBlock(content string) int
EstimateBlock 估算单个内容串 token 数,命中缓存时直接返回。
content 较短(< minBlockLen)时跳过缓存 —— hash 比 len/4 更慢。
func (*TokenCache) WithMinBlockLen ¶
func (c *TokenCache) WithMinBlockLen(n int) *TokenCache
WithMinBlockLen 调整最小缓存阈值;返回自身以便链式调用.
type TokenUsage ¶
type TokenUsage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
}
TokenUsage API 返回的精确 token 统计.