78 lines
1.8 KiB
TypeScript
78 lines
1.8 KiB
TypeScript
export interface ConversationTurn {
|
|
role: "user" | "assistant";
|
|
text: string;
|
|
speakerId?: string;
|
|
speakerName?: string;
|
|
createdAt: number;
|
|
}
|
|
|
|
export interface UserUtterance {
|
|
speakerId: string;
|
|
speakerName: string;
|
|
text: string;
|
|
}
|
|
|
|
export class ConversationMemory {
|
|
private readonly turns: ConversationTurn[] = [];
|
|
|
|
constructor(private readonly maxTurns: number) {}
|
|
|
|
addUserTurn(utterance: UserUtterance): void {
|
|
this.turns.push({
|
|
role: "user",
|
|
text: utterance.text,
|
|
speakerId: utterance.speakerId,
|
|
speakerName: utterance.speakerName,
|
|
createdAt: Date.now(),
|
|
});
|
|
this.trim();
|
|
}
|
|
|
|
addAssistantTurn(text: string): void {
|
|
this.turns.push({
|
|
role: "assistant",
|
|
text,
|
|
createdAt: Date.now(),
|
|
});
|
|
this.trim();
|
|
}
|
|
|
|
clear(): void {
|
|
this.turns.splice(0, this.turns.length);
|
|
}
|
|
|
|
recentTurns(): ConversationTurn[] {
|
|
return [...this.turns];
|
|
}
|
|
|
|
buildPrompt(currentUtterance: UserUtterance): string {
|
|
const recent = this.turns
|
|
.slice(-this.maxTurns)
|
|
.map((turn) => {
|
|
if (turn.role === "assistant") {
|
|
return `[assistant]\n${turn.text}`;
|
|
}
|
|
return `[user speaker_id=${turn.speakerId ?? "unknown"} speaker_name=${turn.speakerName ?? "unknown"}]\n${turn.text}`;
|
|
})
|
|
.join("\n\n");
|
|
|
|
const historyBlock = recent.length > 0 ? recent : "(이전 대화 없음)";
|
|
|
|
return [
|
|
"최근 대화:",
|
|
historyBlock,
|
|
"",
|
|
"이번 발화:",
|
|
`[user speaker_id=${currentUtterance.speakerId} speaker_name=${currentUtterance.speakerName}]`,
|
|
currentUtterance.text,
|
|
].join("\n");
|
|
}
|
|
|
|
private trim(): void {
|
|
const overflow = this.turns.length - this.maxTurns;
|
|
if (overflow > 0) {
|
|
this.turns.splice(0, overflow);
|
|
}
|
|
}
|
|
}
|