Fix AI rule drift and add auto-save during streaming
- Add rule reminders after 10+ messages to prevent AI drift - Add auto-save every 5 seconds during streaming - Add beforeunload warning for unsaved changes - Save user message immediately before generating AI response - Use refs for latest session data in async operations - Reduce summary threshold from 20 to 15 messages
This commit is contained in:
@@ -11,7 +11,7 @@ const DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions";
|
||||
|
||||
// Context settings
|
||||
const RECENT_MESSAGES_COUNT = 6; // Last N messages for context
|
||||
const SUMMARY_THRESHOLD = 20; // After how many messages to generate summary
|
||||
const SUMMARY_THRESHOLD = 15; // After how many messages to generate summary
|
||||
|
||||
// API key should be stored in environment variables
|
||||
const getApiKey = () => import.meta.env.VITE_DEEPSEEK_API_KEY || "";
|
||||
@@ -269,15 +269,24 @@ ${story.plot}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds dynamic context (state + summary)
|
||||
* Builds dynamic context (state + summary + rule reminders)
|
||||
*/
|
||||
export function buildDynamicContext(session: GameSession): string {
|
||||
export function buildDynamicContext(session: GameSession, messageCount?: number): string {
|
||||
const state = session.currentState;
|
||||
const summary = session.storySummary || "The story just began.";
|
||||
const keyEvents = session.keyEvents?.length
|
||||
? session.keyEvents.slice(-5).join("\n- ")
|
||||
: "No significant events yet.";
|
||||
|
||||
// Add rule reminders after 10+ messages to prevent drift
|
||||
const ruleReminder = (messageCount && messageCount >= 10) ? `
|
||||
|
||||
=== REMINDER ===
|
||||
• Do NOT act for the player — only describe reactions and consequences
|
||||
• Do NOT ask "What do you do?" — end with atmosphere, not questions
|
||||
• Format dialogue: **"text"** (double asterisks = bold)
|
||||
• React to player's words explicitly` : '';
|
||||
|
||||
return `
|
||||
=== CURRENT STATE ===
|
||||
Location: ${state.location}
|
||||
@@ -288,7 +297,7 @@ Inventory: ${state.inventory.length > 0 ? state.inventory.join(", ") : "Empty"}
|
||||
${summary}
|
||||
|
||||
=== KEY EVENTS ===
|
||||
- ${keyEvents}`;
|
||||
- ${keyEvents}${ruleReminder}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,8 +326,8 @@ export async function generateStoryResponse(
|
||||
// 2. World context (cached by DeepSeek)
|
||||
const worldContext = buildWorldContext(story);
|
||||
|
||||
// 3. Dynamic context (state + summary)
|
||||
const dynamicContext = session ? buildDynamicContext(session) : "";
|
||||
// 3. Dynamic context (state + summary + rule reminders after 10+ messages)
|
||||
const dynamicContext = session ? buildDynamicContext(session, chatHistory.length) : "";
|
||||
|
||||
// 4. Last N messages (not the full history!)
|
||||
const recentMessages = chatHistory.slice(-RECENT_MESSAGES_COUNT);
|
||||
@@ -353,7 +362,7 @@ export async function generateStoryResponseStream(
|
||||
): Promise<string> {
|
||||
const styleRules = buildStyleRules(story, player);
|
||||
const worldContext = buildWorldContext(story);
|
||||
const dynamicContext = session ? buildDynamicContext(session) : "";
|
||||
const dynamicContext = session ? buildDynamicContext(session, chatHistory.length) : "";
|
||||
const recentMessages = chatHistory.slice(-RECENT_MESSAGES_COUNT);
|
||||
const systemPrompt = styleRules + "\n" + worldContext + "\n" + dynamicContext;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user