MCPcopy Create free account
hub / github.com/diillson/chatcli / RunWithLLM

Method RunWithLLM

cli/workspace/memory/compactor.go:104–184  ·  view source on GitHub ↗

RunWithLLM performs LLM-assisted compaction.

(ctx context.Context, sendPrompt func(ctx context.Context, prompt string) (string, error))

Source from the content-addressed store, hash-verified

102
103// RunWithLLM performs LLM-assisted compaction.
104func (c *Compactor) RunWithLLM(ctx context.Context, sendPrompt func(ctx context.Context, prompt string) (string, error)) error {
105 c.logger.Info("Starting memory compaction (LLM-assisted)")
106
107 facts := c.facts.GetAll()
108 if len(facts) < 10 {
109 c.logger.Debug("Too few facts for compaction", zap.Int("count", len(facts)))
110 c.markCompacted()
111 return nil
112 }
113
114 // Build fact list for LLM
115 var sb strings.Builder
116 for i, f := range facts {
117 sb.WriteString(fmt.Sprintf("%d. [%s] %s (score: %.2f, accessed: %d times)\n",
118 i+1, f.Category, f.Content, f.Score, f.AccessCount))
119 }
120
121 prompt := compactionPrompt + "\n\n---\n\nCURRENT FACTS (" +
122 fmt.Sprintf("%d", len(facts)) + " total):\n\n" + sb.String()
123
124 response, err := sendPrompt(ctx, prompt)
125 if err != nil {
126 // Fall back to score-based pruning
127 c.logger.Warn("LLM compaction failed, falling back to score-based pruning", zap.Error(err))
128 return c.RunScoreBased()
129 }
130
131 // Parse the LLM response
132 consolidated := c.parseCompactionResponse(response, facts)
133 if len(consolidated) == 0 {
134 c.logger.Warn("LLM returned empty compaction, keeping original facts")
135 c.markCompacted()
136 return nil
137 }
138
139 // Shrink guard: consolidation legitimately merges near-duplicates, but a
140 // result that keeps under half the facts is far more likely a truncated
141 // model answer than a real cleanup. Refuse it — memory loss is the one
142 // failure this subsystem must never have — and curate conservatively.
143 if float64(len(consolidated)) < float64(len(facts))*compactionMinKeepRatio {
144 c.logger.Warn("LLM compaction kept too few facts — rejecting as truncated output",
145 zap.Int("before", len(facts)),
146 zap.Int("after", len(consolidated)))
147 return c.RunScoreBased()
148 }
149
150 // Archive whatever the consolidation dropped BEFORE replacing, so every
151 // removed fact stays individually recoverable from memory_archive.json.
152 kept := make(map[string]struct{}, len(consolidated))
153 for _, f := range consolidated {
154 kept[f.ID] = struct{}{}
155 }
156 var dropped []*Fact
157 for _, f := range facts {
158 if _, ok := kept[f.ID]; !ok {
159 dropped = append(dropped, f)
160 }
161 }

Calls 11

markCompactedMethod · 0.95
RunScoreBasedMethod · 0.95
writeMemoryMDMethod · 0.95
appendFactsToArchiveFunction · 0.85
WarnMethod · 0.80
ReplaceFactsMethod · 0.80
InfoMethod · 0.65
ErrorMethod · 0.65
GetAllMethod · 0.45
StringMethod · 0.45