Improve narrative rules, update temperature defaults, fix session character loading
This commit is contained in:
@@ -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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user