chore: version up to 2.80.35 and package with experience memory
This commit is contained in:
+40
-7
@@ -96,13 +96,18 @@ export class RetrievalOrchestrator {
|
||||
allChunks,
|
||||
options.contextBudget
|
||||
);
|
||||
fusionLog.push(`Selected: ${selected.length}, Dropped: ${dropped.length}, Tokens: ${tokensUsed}`);
|
||||
// Pull lesson/playbook/qa-finding chunks out so callers can inject them as a prominent
|
||||
// "verify before finalizing" block rather than burying them in the brain-knowledge section.
|
||||
const lessonChunks = selected.filter((c) => c.metadata.isLesson);
|
||||
const selectedChunks = selected.filter((c) => !c.metadata.isLesson);
|
||||
fusionLog.push(`Selected: ${selectedChunks.length} (+${lessonChunks.length} lesson), Dropped: ${dropped.length}, Tokens: ${tokensUsed}`);
|
||||
|
||||
return {
|
||||
query,
|
||||
totalChunks: allChunks.length,
|
||||
selectedChunks: selected,
|
||||
selectedChunks,
|
||||
droppedChunks: dropped,
|
||||
lessonChunks,
|
||||
totalTokensUsed: tokensUsed,
|
||||
contextBudget: options.contextBudget?.totalBudget || 8000,
|
||||
fusionLog
|
||||
@@ -110,7 +115,7 @@ export class RetrievalOrchestrator {
|
||||
}
|
||||
|
||||
/**
|
||||
* 검색 결과를 최종 컨텍스트 문자열로 변환합니다.
|
||||
* 검색 결과를 최종 컨텍스트 문자열로 변환합니다 (레슨 청크는 제외 — 별도 블록으로 주입).
|
||||
*/
|
||||
public buildContextString(result: RetrievalResult): string {
|
||||
return assembleContext(result.selectedChunks);
|
||||
@@ -150,18 +155,42 @@ export class RetrievalOrchestrator {
|
||||
}))
|
||||
);
|
||||
|
||||
// Always consider lesson cards for the top slots even if they didn't crack the raw-score top-`limit`:
|
||||
// they're short, high-signal, and we want them surfaced when relevant. We keep the regular top-`limit`
|
||||
// and additively pull in up to a few lesson cards (deduped by index).
|
||||
const ranked = scored.filter((x) => x.score > 0).sort((a, b) => b.score - a.score);
|
||||
const pickedIdx = new Set<number>();
|
||||
for (const s of ranked.slice(0, limit)) pickedIdx.add(s.index);
|
||||
const LESSON_EXTRA = 3;
|
||||
let lessonExtra = 0;
|
||||
for (const s of ranked) {
|
||||
if (lessonExtra >= LESSON_EXTRA) break;
|
||||
if (pickedIdx.has(s.index)) continue;
|
||||
if ((indexed[s.index].kind || '') === '') continue;
|
||||
pickedIdx.add(s.index);
|
||||
lessonExtra++;
|
||||
}
|
||||
// Preserve rank order for the chosen set.
|
||||
const chosen = ranked.filter((s) => pickedIdx.has(s.index));
|
||||
|
||||
const topResults: RetrievalChunk[] = [];
|
||||
for (const s of scored.filter((x) => x.score > 0).sort((a, b) => b.score - a.score).slice(0, limit)) {
|
||||
for (const s of chosen) {
|
||||
const doc = indexed[s.index];
|
||||
// Only the top `limit` files are actually read off disk (for excerpt extraction).
|
||||
const isLesson = (doc.kind || '') !== '';
|
||||
// Only the chosen files are actually read off disk (for excerpt extraction).
|
||||
let content = '';
|
||||
try { content = fs.readFileSync(doc.filePath, 'utf8'); } catch { /* deleted just now — skip */ continue; }
|
||||
const excerpt = extractBestExcerpt(content, expandedTokens, 400);
|
||||
// Lesson cards: hand back the whole card (they're meant to be short) so the Prevention Checklist
|
||||
// survives; fall back to a generous excerpt for long ones. Regular notes: the usual 400-char excerpt.
|
||||
const excerpt = isLesson
|
||||
? (content.length <= 2500 ? content.trim() : extractBestExcerpt(content, expandedTokens, 1500))
|
||||
: extractBestExcerpt(content, expandedTokens, 400);
|
||||
const cap = isLesson ? 2500 : 400;
|
||||
topResults.push({
|
||||
id: `brain-${s.index}`,
|
||||
source: 'brain-memory' as const,
|
||||
title: doc.relativePath,
|
||||
content: summarizeText(excerpt, 400),
|
||||
content: summarizeText(excerpt, cap),
|
||||
score: s.score,
|
||||
tokenEstimate: estimateTokens(excerpt),
|
||||
metadata: {
|
||||
@@ -173,6 +202,7 @@ export class RetrievalOrchestrator {
|
||||
conflictDetected: s.conflictDetected,
|
||||
conflictSeverity: s.conflictSeverity,
|
||||
informationDensity: s.informationDensity,
|
||||
...(isLesson ? { isLesson: true, lessonKind: doc.kind } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -293,6 +323,9 @@ export class RetrievalOrchestrator {
|
||||
for (const chunk of chunks) {
|
||||
const boost = sourceBoost[chunk.source] || 0.5;
|
||||
chunk.score *= boost;
|
||||
// Lesson cards are short, high-signal guardrails — nudge relevant ones above ordinary brain notes
|
||||
// so they survive the budget. Modest (1.4×) so they don't crowd everything out when many match.
|
||||
if (chunk.metadata.isLesson) chunk.score *= 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user