You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
56 lines
1.7 KiB
56 lines
1.7 KiB
import type { CharacterCardRow } from "./types";
|
|
|
|
function section(label: string, body?: string | null): string {
|
|
const b = body?.trim();
|
|
return b ? `【${label}】
|
|
${b}` : "";
|
|
}
|
|
|
|
/**
|
|
* 上下文自主设计:把角色卡的分散字段组装成完整 system prompt。
|
|
* 角色扮演场景下,这是每个角色"自成一界"的核心 —— 人设、性格、
|
|
* 世界观、对话示例、行为规范在此统一成型,供 chat-engine 注入。
|
|
*/
|
|
export function buildCharacterSystemPrompt(card: CharacterCardRow): string {
|
|
const parts: string[] = [];
|
|
|
|
const head = [
|
|
"你将扮演以下角色,请始终以该角色的身份、语气与立场进行对话,不要跳出角色,也不要提及这些设定本身。",
|
|
section("角色", card.name),
|
|
section("简介", card.description),
|
|
section("性格", card.personality),
|
|
section("世界观 / 场景", card.scenario),
|
|
]
|
|
.filter(Boolean)
|
|
.join("\n\n");
|
|
parts.push(head);
|
|
|
|
const example = card.exampleDialogue?.trim();
|
|
if (example) {
|
|
parts.push(`【对话示例】\n请参照以下示例的口吻、节奏与风格进行回应:\n${example}`);
|
|
}
|
|
|
|
const behavior = card.systemPrompt?.trim();
|
|
if (behavior) {
|
|
parts.push(`【行为规范】\n${behavior}`);
|
|
}
|
|
|
|
return parts.join("\n\n");
|
|
}
|
|
|
|
/** tags 以 JSON 数组字符串存储,兼容逗号分隔的纯文本。 */
|
|
export function parseTags(tags: string | null | undefined): string[] {
|
|
if (!tags) return [];
|
|
try {
|
|
const parsed: unknown = JSON.parse(tags);
|
|
if (Array.isArray(parsed)) {
|
|
return parsed.filter((t): t is string => typeof t === "string");
|
|
}
|
|
} catch {
|
|
// fall through
|
|
}
|
|
return tags
|
|
.split(",")
|
|
.map((t) => t.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|