Files
connectai/src/memory/MemoryExtractor.ts
T

116 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* ============================================================
* Memory Extractor (기억 추출기)
*
* 대화 종료 시 히스토리를 분석하여 각 메모리 레이어에
* 저장할 정보를 자동으로 추출합니다.
* LLM 호출 없이 패턴 매칭 기반으로 동작합니다.
* ============================================================
*/
import { LongTermMemory } from './LongTermMemory';
import { ProjectMemory } from './ProjectMemory';
import { EpisodicMemory } from './EpisodicMemory';
interface ExtractionResult {
longTermCandidates: number;
episodeCreated: boolean;
projectUpdated: boolean;
}
export class MemoryExtractor {
/**
* 세션 종료 시 모든 메모리 레이어에 대해 추출을 수행합니다.
*/
public extractFromSession(
sessionId: string,
messages: Array<{ role: string; content: string; timestamp?: number }>,
longTermMemory: LongTermMemory,
episodicMemory: EpisodicMemory,
projectMemory: ProjectMemory | null,
projectContext?: string
): ExtractionResult {
const result: ExtractionResult = {
longTermCandidates: 0,
episodeCreated: false,
projectUpdated: false
};
// 1. Long-Term Memory 추출
const candidates = LongTermMemory.extractCandidates(messages);
for (const candidate of candidates) {
longTermMemory.addEntry(
candidate.category,
candidate.content,
`session:${sessionId}`,
0.7 // 자동 추출이므로 기본 신뢰도 0.7
);
}
result.longTermCandidates = candidates.length;
// 2. Episodic Memory 생성
const episode = episodicMemory.createEpisode(
sessionId,
messages,
projectContext
);
result.episodeCreated = !!episode;
// 3. Project Memory 업데이트 (프로젝트 관련 대화인 경우)
if (projectMemory && projectContext) {
const updated = this.extractProjectInfo(messages, projectMemory);
result.projectUpdated = updated;
}
return result;
}
/**
* 대화에서 프로젝트 관련 정보를 추출하여 Project Memory에 저장합니다.
*/
private extractProjectInfo(
messages: Array<{ role: string; content: string }>,
projectMemory: ProjectMemory
): boolean {
let updated = false;
const allText = messages.map((m) => m.content).join('\n');
// Tech stack 추출
const techPatterns = [
/(?:사용|using|사용하는|tech\s*stack|기술\s*스택)[\s:]*([^\n]+)/gi
];
for (const pattern of techPatterns) {
let match;
while ((match = pattern.exec(allText)) !== null) {
const techs = match[1]
.split(/[,\s]+/)
.filter((t) => t.length >= 2 && t.length <= 20);
for (const tech of techs) {
projectMemory.addTechStack(tech.trim());
updated = true;
}
}
}
// Bug report 추출
const bugPatterns = [
/(?:버그|bug|오류|error|이슈|issue)[\s:]+(.{10,200})/gi
];
for (const pattern of bugPatterns) {
let match;
while ((match = pattern.exec(allText)) !== null) {
// 간단한 버그만 자동 기록 (상세 분석은 사용자 확인 필요)
// 여기서는 패턴만 감지하고, 실제 기록은 사용자 확인 후
updated = true;
}
}
if (updated) {
projectMemory.save();
}
return updated;
}
}