perf: 上下文策略自适应优化

This commit is contained in:
voocel
2026-03-12 15:17:53 +08:00
parent e9c8220bc3
commit 3d65afa276
3 changed files with 56 additions and 9 deletions

View File

@@ -59,6 +59,25 @@ func (p *Progress) NextChapter() int {
return max + 1
}
// ContextProfile 上下文加载策略,根据总章节数自适应。
type ContextProfile struct {
SummaryWindow int // 加载最近 N 章摘要
TimelineWindow int // 加载最近 N 章时间线
FullContext bool // true = 忽略窗口,全量加载
}
// NewContextProfile 根据总章节数计算上下文策略。
func NewContextProfile(totalChapters int) ContextProfile {
switch {
case totalChapters <= 15:
return ContextProfile{FullContext: true}
case totalChapters <= 50:
return ContextProfile{SummaryWindow: 5, TimelineWindow: 10}
default:
return ContextProfile{SummaryWindow: 3, TimelineWindow: 8}
}
}
// RunMeta 运行元信息,持久化到 meta/run.json。
type RunMeta struct {
StartedAt string `json:"started_at"`

View File

@@ -39,3 +39,8 @@ func (s *Store) LoadRecentSummaries(current, count int) ([]domain.ChapterSummary
}
return result, nil
}
// LoadAllSummaries 加载 current 章之前的所有摘要(短篇全量模式)。
func (s *Store) LoadAllSummaries(current int) ([]domain.ChapterSummary, error) {
return s.LoadRecentSummaries(current, current)
}

View File

@@ -73,6 +73,12 @@ func (t *ContextTool) Execute(_ context.Context, args json.RawMessage) (json.Raw
}
if a.Chapter > 0 {
// 根据总章节数计算上下文策略
profile := domain.NewContextProfile(0)
if progress, err := t.store.LoadProgress(); err == nil && progress != nil && progress.TotalChapters > 0 {
profile = domain.NewContextProfile(progress.TotalChapters)
}
// 角色按 Tier 过滤core/important 始终返回secondary/decorative 按出场匹配
t.loadFilteredCharacters(result, a.Chapter)
@@ -80,18 +86,35 @@ func (t *ContextTool) Execute(_ context.Context, args json.RawMessage) (json.Raw
if entry, err := t.store.GetChapterOutline(a.Chapter); err == nil {
result["current_chapter_outline"] = entry
}
if summaries, err := t.store.LoadRecentSummaries(a.Chapter, 2); err == nil && len(summaries) > 0 {
result["recent_summaries"] = summaries
if profile.FullContext {
if summaries, err := t.store.LoadAllSummaries(a.Chapter); err == nil && len(summaries) > 0 {
result["recent_summaries"] = summaries
}
} else {
if summaries, err := t.store.LoadRecentSummaries(a.Chapter, profile.SummaryWindow); err == nil && len(summaries) > 0 {
result["recent_summaries"] = summaries
}
}
// V3: 状态数据分级加载
// timeline只取最近 5 章的事件(避免后期全量膨胀)
if timeline, err := t.store.LoadRecentTimeline(a.Chapter, 5); err == nil && len(timeline) > 0 {
result["timeline"] = timeline
// 状态数据按策略加载
if profile.FullContext {
if timeline, err := t.store.LoadTimeline(); err == nil && len(timeline) > 0 {
result["timeline"] = timeline
}
} else {
if timeline, err := t.store.LoadRecentTimeline(a.Chapter, profile.TimelineWindow); err == nil && len(timeline) > 0 {
result["timeline"] = timeline
}
}
// foreshadow只取未回收条目(已回收的对后续写作无意义)
if foreshadow, err := t.store.LoadActiveForeshadow(); err == nil && len(foreshadow) > 0 {
result["foreshadow_ledger"] = foreshadow
// foreshadow短篇全量,否则只取未回收条目
if profile.FullContext {
if foreshadow, err := t.store.LoadForeshadowLedger(); err == nil && len(foreshadow) > 0 {
result["foreshadow_ledger"] = foreshadow
}
} else {
if foreshadow, err := t.store.LoadActiveForeshadow(); err == nil && len(foreshadow) > 0 {
result["foreshadow_ledger"] = foreshadow
}
}
// relationships保持全量pair-key 去重,数据量天然可控)
if relationships, err := t.store.LoadRelationships(); err == nil && len(relationships) > 0 {