type ParsedStoryNpc = { name: string; title: string; role: string; description: string; personality: string; motivation: string; }; type ParsedLandmark = { name: string; description: string; dangerLevel: string; }; type ParsedProfile = { name: string; settingText: string; storyNpcs: ParsedStoryNpc[]; landmarks: ParsedLandmark[]; }; export const CUSTOM_WORLD_SCENE_NPC_SYSTEM_PROMPT = '你是游戏世界编辑器的场景 NPC 生成器。你必须只返回可解析 JSON,不要输出解释、前言或 Markdown。'; export function buildCustomWorldSceneNpcPrompt( profile: ParsedProfile, landmark: ParsedLandmark, sceneNpcs: ParsedStoryNpc[], otherNpcs: ParsedStoryNpc[], ) { const sceneNpcSummary = sceneNpcs.length ? sceneNpcs .map( (npc, index) => `${index + 1}. ${npc.name} / ${npc.title || npc.role} / ${npc.description || '无描述'} / 性格:${npc.personality || '未写'} / 动机:${npc.motivation || '未写'}`, ) .join('\n') : '当前场景还没有已加入 NPC。'; const reserveNpcSummary = otherNpcs.length ? otherNpcs .slice(0, 8) .map( (npc, index) => `${index + 1}. ${npc.name} / ${npc.title || npc.role} / ${npc.description || '无描述'}`, ) .join('\n') : '暂无其他场景角色参考。'; const landmarkSummary = profile.landmarks .slice(0, 10) .map( (entry, index) => `${index + 1}. ${entry.name} / 危险度:${entry.dangerLevel || '中'} / ${entry.description || '无描述'}`, ) .join('\n'); return [ `世界名:${profile.name}`, `世界设定:${profile.settingText || '未提供额外设定文本。'}`, `当前目标场景:${landmark.name}`, `场景描述:${landmark.description || '未填写'}`, `危险度:${landmark.dangerLevel || '中'}`, `当前场景已加入 NPC:\n${sceneNpcSummary}`, `其他可参考 NPC:\n${reserveNpcSummary}`, `世界内其他场景概览:\n${landmarkSummary}`, '请生成 1 名适合加入当前场景的新 NPC。', '要求:', '- 必须与当前场景气质、危险度、已有 NPC 分工互补,不要和已有 NPC 重复。', '- 角色要像真正可落地到游戏里的场景角色,不要写成抽象设定。', '- 关系钩子、技能、初始物品都要可直接进入编辑器。', '- 返回 JSON,不要额外解释。', 'JSON 结构:', '{', ' "npc": {', ' "name": "角色名",', ' "title": "头衔",', ' "role": "身份",', ' "description": "一句到两句角色描述",', ' "backstory": "背景",', ' "personality": "性格",', ' "motivation": "动机",', ' "combatStyle": "战斗风格",', ' "initialAffinity": 6,', ' "relationshipHooks": ["关系钩子1", "关系钩子2", "关系钩子3"],', ' "tags": ["标签1", "标签2", "标签3"],', ' "publicSummary": "公开背景摘要",', ' "chapterTeasers": ["表层来意", "旧事裂痕", "隐藏执念", "最终底牌"],', ' "chapterContents": ["对应正文1", "对应正文2", "对应正文3", "对应正文4"],', ' "skills": [', ' { "name": "技能1", "summary": "说明", "style": "风格" },', ' { "name": "技能2", "summary": "说明", "style": "风格" },', ' { "name": "技能3", "summary": "说明", "style": "风格" }', ' ],', ' "initialItems": [', ' { "name": "物品1", "category": "分类", "quantity": 1, "rarity": "rare", "description": "说明", "tags": ["标签"] },', ' { "name": "物品2", "category": "分类", "quantity": 1, "rarity": "uncommon", "description": "说明", "tags": ["标签"] },', ' { "name": "物品3", "category": "分类", "quantity": 1, "rarity": "rare", "description": "说明", "tags": ["标签"] }', ' ]', ' }', '}', ].join('\n'); }