Files
digital-me-history/digital-me-backend/docs/talents/README.md
T
admin 0593ff7e62
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
数字我 Digital Me:全量入库(大文件走 Git LFS)
2026-10-10 16:24:43 +08:00

78 lines
4.9 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 天赋系统契约(Talent System Contract)
天赋树 = **Prompt + 模型行为的控制平面**,不是游戏成长系统。
- **主天赋(唯一)** = 身份:决定 System Prompt / 是否走 RAG / 合规安全等级 / 默认模型。主天赋 **就是 `twin.profession`**,不另存一套 id。
- **副天赋(≤N)** = 风格软技能:**后置改写**,只碰成稿、**绝不改事实**。
实现见 [`../../src/talents.js`](../../src/talents.js)。本目录是与线上代码对齐的**契约**,也是将来搬 DB 的蓝本。
## 文件
| Schema | 描述 | 对应代码 |
|---|---|---|
| [main-talent.schema.json](main-talent.schema.json) | 主天赋身份节点 | `mainTalent(profId)` |
| [sub-talent.schema.json](sub-talent.schema.json) | 副天赋注册表项 | `SUB_REGISTRY` |
| [user-talent-instance.schema.json](user-talent-instance.schema.json) | 分身选定的天赋 | `twin.talents` |
| [talent-registry.schema.json](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→craft
- `compliance → 安全`:none→{2,无} / soft→{5,软免责} / strict→{9,强免责+关键词+需审核}
新增一个职业只改 `professions.js` 一处;换某原型的行为只改 `ARCH_BEHAVIOR` 一处。
## 校验规则(服务端必须兜底,不信前端)
1. **主天赋唯一**:`main_talent` 必须 ∈ 职业表(`getProfession`),否则 400 `unknown-main-talent`;`null`/无 → `general` 兜底身份。
2. **副天赋合法性**:每个 id 必须 ∈ `SUB_REGISTRY`;去重;顺序保留。
3. **副天赋槽位**:数量 ≤ `maxSubs(level) = min(3, 1 + level)`(level 来自 `computeSkillTree`)。超出**静默截断**(`validateSubs`),不报错。
4. **副天赋不改事实**:所有 style/constraint 副天赋合并成**一次**后置改写,指令强约束"不改变任何事实/数字/结论/引用";hobby 型走前置注入。
5. **审核门(软门)**:`main.audit_required && !twin.verified` → `twin.talentAudit='pending'`,**不拦截**(分身仍可用),但运行时 Guardrail 强制免责。已 `verified` → `'approved'`。
6. **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`):
```jsonc
{
"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(两字段都可选,可单独改):
```jsonc
{ "main_talent": "lawyer", // 可选:切身份(=profession),带 audit 门
"sub_talents": ["humor","concise"] } // 可选:仅当为数组时才更新;截到 maxSubs
```
返回同 `GET`。
## DB 化迁移(留了缝,MVP 不做)
1. `SUB_REGISTRY` → 集合 `talent_sub_registry`(一项一文档)。
2. 主天赋映射(ARCH_BEHAVIOR / COMPLIANCE / ARCH_MODEL)→ 集合 `talent_main_config`,或物化 `talent_main_talents`(一职业一行)。
3. 每个节点加 `talent-registry.schema.json#/$defs/versioning`(`version/active/gray_pct`)→ 支持**灰度放量 + 一键回滚**。
4. `talents.js` 的纯函数签名不变,只把三张 `const` 表换成带缓存的 DB 读取;`describeTalents/resolveTalents/guardrail` 全部复用。
## 留坑不做(架构留得住)
天赋升级 lv2/3(`level` 字段已在)· 冲突检测(医生+算命❌)· 天赋市场(官方/共创)· 会话级动态天赋 · 按天赋真路由模型/计量返佣(`model_preference` + `chat(opts.model)` 缝已在)。