feat(memory): add shared history context to social narration prompts
When narrating social interactions, the LLM now receives up to 3 shared history events between the two NPCs, enabling more contextual narrations that reference past encounters. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -205,6 +205,7 @@ describe('NarrationService', () => {
|
||||
outcome: 'negative',
|
||||
relationship: 'rival',
|
||||
sentiment: '-0.3',
|
||||
recentHistory: '',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface InteractionRecord {
|
||||
npc1Personality?: string;
|
||||
npc2Personality?: string;
|
||||
sentiment?: number;
|
||||
sharedHistory?: string;
|
||||
}
|
||||
|
||||
export interface NarrationService {
|
||||
@@ -69,6 +70,7 @@ export function createNarrationService(llmService: LlmService): NarrationService
|
||||
outcome: record.outcome,
|
||||
relationship: record.classification,
|
||||
sentiment: String(record.sentiment ?? ''),
|
||||
recentHistory: record.sharedHistory ?? '',
|
||||
};
|
||||
|
||||
llmService.generate('socialNarration', variables).then((result) => {
|
||||
|
||||
@@ -27,6 +27,7 @@ export const templates: Record<string, PromptTemplate> = {
|
||||
'{{npc1Name}} ({{npc1Personality}}) had a {{outcome}} interaction with ' +
|
||||
'{{npc2Name}} ({{npc2Personality}}). ' +
|
||||
'They are currently {{relationship}} (sentiment: {{sentiment}}/100).\n' +
|
||||
'Their recent shared history:\n{{recentHistory}}\n' +
|
||||
'Describe what happened in one vivid sentence.',
|
||||
},
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ import type { World } from '../ecs/World.js';
|
||||
import type { NarrationService } from '../llm/narrationService.js';
|
||||
import { formatStatsForPrompt } from '../llm/backstoryGenerator.js';
|
||||
import { classify } from './relationshipHelpers.js';
|
||||
import type { EventMemoryService } from '../llm/eventMemoryService.js';
|
||||
|
||||
export function narrationEmitter(
|
||||
world: World,
|
||||
narrationService: NarrationService,
|
||||
followedEntityIds: Set<EntityId>,
|
||||
eventMemoryService?: EventMemoryService,
|
||||
): void {
|
||||
const entities = world.query('socialState', 'name', 'stats');
|
||||
const processed = new Set<string>();
|
||||
@@ -69,6 +71,18 @@ export function narrationEmitter(
|
||||
const [firstName, secondName] = entity < partnerId ? [name1, name2] : [name2, name1];
|
||||
const [firstStats, secondStats] = entity < partnerId ? [stats1, stats2] : [stats2, stats1];
|
||||
|
||||
let sharedHistory = '';
|
||||
if (eventMemoryService) {
|
||||
const events = eventMemoryService.selectForPrompt(firstId, {
|
||||
maxCount: 3,
|
||||
preferEntityId: secondId,
|
||||
preferTypes: ['social_positive', 'social_negative', 'tier_change'],
|
||||
});
|
||||
if (events.length > 0) {
|
||||
sharedHistory = events.map(e => `- ${e.detail}`).join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
narrationService.recordInteraction({
|
||||
tick: social.lastOutcome.tick,
|
||||
entityIds: [firstId, secondId],
|
||||
@@ -80,6 +94,7 @@ export function narrationEmitter(
|
||||
npc1Personality: firstStats ? formatStatsForPrompt(firstStats) : undefined,
|
||||
npc2Personality: secondStats ? formatStatsForPrompt(secondStats) : undefined,
|
||||
sentiment: relValue,
|
||||
sharedHistory,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user