天赋系统契约(Talent System Contract)
天赋树 = Prompt + 模型行为的控制平面,不是游戏成长系统。
- 主天赋(唯一) = 身份:决定 System Prompt / 是否走 RAG / 合规安全等级 / 默认模型。主天赋 就是
twin.profession,不另存一套 id。 - 副天赋(≤N) = 风格软技能:后置改写,只碰成稿、绝不改事实。
实现见 ../../src/talents.js。本目录是与线上代码对齐的契约,也是将来搬 DB 的蓝本。
文件
| Schema | 描述 | 对应代码 |
|---|---|---|
| main-talent.schema.json | 主天赋身份节点 | mainTalent(profId) |
| sub-talent.schema.json | 副天赋注册表项 | SUB_REGISTRY |
| user-talent-instance.schema.json | 分身选定的天赋 | twin.talents |
| talent-registry.schema.json | 注册表整体 | 派生/静态表 |
派生关系(主天赋怎么来的)
不逐个职业手写主天赋,而是三张映射表交叉派生(talents.js):
profession(professions.js) ──cat──▶ ARCH_BY_CAT ──▶ arch ──▶ ARCH_BEHAVIOR(行为基线) + ARCH_MODEL(模型偏好)
└─compliance─▶ COMPLIANCE ──▶ safety_level + block_keywords + disclaimer + audit_required
cat → arch:content→creator, pro/health/biz/life/other→expert, edu→teacher, art→artist, sport→sport, craft→craftcompliance → 安全:none→{2,无} / soft→{5,软免责} / strict→{9,强免责+关键词+需审核}
新增一个职业只改 professions.js 一处;换某原型的行为只改 ARCH_BEHAVIOR 一处。
校验规则(服务端必须兜底,不信前端)
- 主天赋唯一:
main_talent必须 ∈ 职业表(getProfession),否则 400unknown-main-talent;null/无 →general兜底身份。 - 副天赋合法性:每个 id 必须 ∈
SUB_REGISTRY;去重;顺序保留。 - 副天赋槽位:数量 ≤
maxSubs(level) = min(3, 1 + level)(level 来自computeSkillTree)。超出静默截断(validateSubs),不报错。 - 副天赋不改事实:所有 style/constraint 副天赋合并成一次后置改写,指令强约束"不改变任何事实/数字/结论/引用";hobby 型走前置注入。
- 审核门(软门):
main.audit_required && !twin.verified→twin.talentAudit='pending',不拦截(分身仍可用),但运行时 Guardrail 强制免责。已verified→'approved'。 - Guardrail(运行时,输出前):
block_keywords命中 → 软化替换;safety_level >= 5且回答未含免责 → 追加disclaimer到结尾。
运行时管线(services/twin.js → ask())
用户输入
→ 组装 System Prompt:身份(mainPromptBlock) + 前置注入(injectBlock) + 人设/记忆/RAG
→ (RAG 检索,main.rag)
→ LLM 主回答 chat(messages) ← 主天赋出稿
→ 副天赋后置改写 chat([restyleInstruction, draft]) ← 合并 1 次;无副天赋则跳过
→ Guardrail guardrail(text, main) ← 屏蔽词 + 免责
→ 输出
成本:每轮 1 次主调用 + 至多 1 次改写调用(不是每个副天赋一次)。
API 契约
GET /api/twins/:id/talents
返回(describeTalents):
{
"main": { "id","name","emoji","entity","arch","compliance","safety_level",
"rag_required","audit_required","audit_ok","behavior" },
"subs": { "selected": ["humor"], "max": 1,
"options": [{ "id","name","subtype","desc" }] },
"growth": { "level": 0, "maxSubs": 1 }
}
PUT /api/twins/:id/talents
Body(两字段都可选,可单独改):
{ "main_talent": "lawyer", // 可选:切身份(=profession),带 audit 门
"sub_talents": ["humor","concise"] } // 可选:仅当为数组时才更新;截到 maxSubs
返回同 GET。
DB 化迁移(留了缝,MVP 不做)
SUB_REGISTRY→ 集合talent_sub_registry(一项一文档)。- 主天赋映射(ARCH_BEHAVIOR / COMPLIANCE / ARCH_MODEL)→ 集合
talent_main_config,或物化talent_main_talents(一职业一行)。 - 每个节点加
talent-registry.schema.json#/$defs/versioning(version/active/gray_pct)→ 支持灰度放量 + 一键回滚。 talents.js的纯函数签名不变,只把三张const表换成带缓存的 DB 读取;describeTalents/resolveTalents/guardrail全部复用。
留坑不做(架构留得住)
天赋升级 lv2/3(level 字段已在)· 冲突检测(医生+算命❌)· 天赋市场(官方/共创)· 会话级动态天赋 · 按天赋真路由模型/计量返佣(model_preference + chat(opts.model) 缝已在)。