Improve narrative rules, update temperature defaults, fix session character loading

This commit is contained in:
Alexej Wolff
2026-05-04 00:59:56 +02:00
parent f52c86b049
commit 1f7d13e44c
3 changed files with 45 additions and 21 deletions
+5 -5
View File
@@ -77,7 +77,7 @@ export default function CreateStoryPage() {
plot: "", plot: "",
firstMessage: "", firstMessage: "",
isNsfw: false, isNsfw: false,
temperature: 1.3, // Креативность ИИ temperature: 0.9, // Креативность ИИ
narrativeRules: "", // Правила повествования для ИИ narrativeRules: "", // Правила повествования для ИИ
// NPC персонажи мира // NPC персонажи мира
characters: [{ name: "", description: "", role: "Союзник" }] as Character[], characters: [{ name: "", description: "", role: "Союзник" }] as Character[],
@@ -116,7 +116,7 @@ export default function CreateStoryPage() {
plot: story.plot || "", plot: story.plot || "",
firstMessage: story.firstMessage || "", firstMessage: story.firstMessage || "",
isNsfw: story.isNsfw || false, isNsfw: story.isNsfw || false,
temperature: story.temperature || 1.3, temperature: story.temperature || 0.9,
narrativeRules: story.narrativeRules || "", narrativeRules: story.narrativeRules || "",
characters: characters:
story.characters?.length > 0 story.characters?.length > 0
@@ -448,9 +448,9 @@ export default function CreateStoryPage() {
</p> </p>
<div className="temperature-selector"> <div className="temperature-selector">
{[ {[
{ value: 1.0, label: "🎯 Сосредоточенный", desc: "1.0" }, { value: 0.9, label: "⚖️ Сбалансированный", desc: "0.9" },
{ value: 1.3, label: "⚖️ Сбалансированный", desc: "1.3" }, { value: 0.95, label: "✨ Живой", desc: "0.95" },
{ value: 1.5, label: " Креативный", desc: "1.5" }, { value: 1.05, label: "🎨 Креативный", desc: "1.05" },
].map((opt) => ( ].map((opt) => (
<button <button
key={opt.value} key={opt.value}
+21 -2
View File
@@ -10,6 +10,7 @@ import {
saveSession as apiSaveSession, saveSession as apiSaveSession,
deleteSession, deleteSession,
getPlayerCharacter, getPlayerCharacter,
getPlayerCharacters,
type SessionListItem, type SessionListItem,
} from "../services/api"; } from "../services/api";
import { import {
@@ -96,6 +97,13 @@ export default function GamePage() {
if (characterId) { if (characterId) {
character = await getPlayerCharacter(characterId); character = await getPlayerCharacter(characterId);
setPlayerCharacter(character); setPlayerCharacter(character);
} else {
// Если персонаж не указан в URL, загружаем первого доступного (или избранного)
const characters = await getPlayerCharacters();
if (characters.length > 0) {
character = characters.find(c => c.isFavorite) || characters[0];
setPlayerCharacter(character);
}
} }
// Если есть сессии, загружаем последнюю (или создаём новую) // Если есть сессии, загружаем последнюю (или создаём новую)
@@ -107,11 +115,21 @@ export default function GamePage() {
console.log("[GamePage] Session data loaded:", sessionData); console.log("[GamePage] Session data loaded:", sessionData);
if (sessionData) { if (sessionData) {
setSession(sessionData); setSession(sessionData);
// Загружаем персонажа из сессии если не выбран // Загружаем персонажа: приоритет URL > сессия
if (!character && sessionData.playerId) { if (!character && sessionData.playerId) {
character = await getPlayerCharacter(sessionData.playerId); character = await getPlayerCharacter(sessionData.playerId);
setPlayerCharacter(character); setPlayerCharacter(character);
} }
// Если в сессии нет playerId, но персонаж выбран в URL — обновляем сессию
if (!sessionData.playerId && character) {
const updatedSession = { ...sessionData, playerId: character.id };
await apiSaveSession(id, latestSession.id, updatedSession);
setSession(updatedSession);
}
// Если сессия пустая (нет сообщений) — запускаем историю
if (sessionData.messages.length === 0 && character) {
startStory(normalizedStory, sessionData, character, latestSession.id);
}
} }
} else if (characterId) { } else if (characterId) {
// Нет сессий и выбран персонаж — создаём новую // Нет сессий и выбран персонаж — создаём новую
@@ -608,7 +626,8 @@ export default function GamePage() {
// Используем персонажа из текущей сессии или выбранного // Используем персонажа из текущей сессии или выбранного
const characterId = playerCharacter?.id || session?.playerId; const characterId = playerCharacter?.id || session?.playerId;
if (!characterId) { if (!characterId) {
alert("Не выбран персонаж для игры"); // Перенаправляем на страницу выбора персонажа
window.location.href = `/story/${id}`;
return; return;
} }
+19 -14
View File
@@ -54,6 +54,7 @@ export async function sendMessage(
Authorization: `Bearer ${apiKey}`, Authorization: `Bearer ${apiKey}`,
}, },
body: JSON.stringify({ body: JSON.stringify({
// model: "deepseek-chat",
model: "deepseek-chat", model: "deepseek-chat",
messages, messages,
temperature, temperature,
@@ -213,20 +214,24 @@ ${nsfwBlock}
=== NARRATIVE RULES === === NARRATIVE RULES ===
1. Player writes their own actions and dialogue 1. Player writes their own actions and dialogue
2. Weave player actions into the scene, describe character reactions and consequences 2. Weave player actions into the scene, describe character reactions and consequences
3. NEVER make decisions for the player 3. Do not make decisions for the player — let them choose
4. NEVER ask the player questions 4. Do not ask questions like "What do you do?" or "What will you choose?"
5. NEVER offer action choices 5. Do not offer explicit action choices
6. NEVER assume player intentions 6. Do not assume what player wants to do next
7. No time skips without explicit indication 7. No time skips without explicit indication
8. If action not written by player — it did NOT happen 8. If action not written by player — it did NOT happen
=== PROTAGONIST RULES === === PROTAGONIST HANDLING ===
You are NOT ALLOWED to: Guidelines for the main character (MC):
— describe MC's physical actions Do not describe MC's physical actions (walking, grabbing, looking) unless player wrote them
describe their internal sensations, emotions, or thoughts Do not put thoughts or internal monologue in MC's mind
put words or dialogue in their mouth Do not speak for MC unless player wrote dialogue
Until player writes an action or dialogue, — When player hasn't acted, describe the scene and other characters' reactions
the hero is considered motionless, silent, and observing. — You may describe what MC perceives (sights, sounds, sensations) to set atmosphere
— End scenes with situation that invites action, not with direct questions
WRONG: "Ты протягиваешь руку и берёшь кристалл. Что ты делаешь?"
RIGHT: "Кристалл лежит на земле, мерцая голубым светом. Где-то вдали слышен стук копыт."
=== REACTIONS TO MC's DIALOGUE === === REACTIONS TO MC's DIALOGUE ===
Characters MUST explicitly react to MC's words: Characters MUST explicitly react to MC's words:
@@ -341,8 +346,8 @@ export async function generateStoryResponse(
{ role: "user", content: userMessage }, { role: "user", content: userMessage },
]; ];
// Use temperature from story settings (default 1.3) // Use temperature from story settings (default 0.9 for balanced creative writing)
return sendMessage(messages, story.temperature || 1.3); return sendMessage(messages, story.temperature || 0.9);
} }
/** /**
@@ -372,7 +377,7 @@ export async function generateStoryResponseStream(
{ role: "user", content: userMessage }, { role: "user", content: userMessage },
]; ];
return sendMessageStream(messages, story.temperature || 1.3, onChunk, signal); return sendMessageStream(messages, story.temperature || 0.9, onChunk, signal);
} }
/** /**