数字我 Digital Me:全量入库(大文件走 Git LFS)
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
This commit is contained in:
Executable
+77
@@ -0,0 +1,77 @@
|
||||
# 天赋系统契约(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)` 缝已在)。
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://digitalme.invoratec.cn/schemas/main-talent.json",
|
||||
"title": "MainTalent",
|
||||
"description": "主天赋 = 唯一身份单元。当前由 profession + archetype + compliance 派生(见 talents.js mainTalent());将来可整体搬入 DB 集合 talent_main_config。主天赋决定:身份 System Prompt / 是否走 RAG / 合规安全等级 / 默认模型。",
|
||||
"type": "object",
|
||||
"required": ["id", "name", "type", "system_prompt", "rag", "safety_level", "compliance", "audit_required"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "type": "string", "description": "= profession id(主天赋不另建一套 id,直接复用职业)。null 身份用 'general'。", "examples": ["lawyer", "game_blogger", "general"] },
|
||||
"name": { "type": "string", "description": "展示名", "examples": ["律师/法律顾问"] },
|
||||
"emoji":{ "type": "string" },
|
||||
"type": { "const": "main" },
|
||||
"level":{ "type": "integer", "minimum": 1, "default": 1, "description": "身份等级(MVP 恒为 1;lv2/3 留给未来天赋升级)。" },
|
||||
"arch": { "type": "string", "enum": ["expert", "creator", "teacher", "artist", "sport", "craft"], "description": "职业原型:决定行为基线(ARCH_BEHAVIOR)与默认模型。由 profession.cat 映射。" },
|
||||
"entity": { "type": "string", "description": "生命体称号", "examples": ["律师生命体"] },
|
||||
"system_prompt": { "type": "string", "minLength": 1, "description": "身份+行为基线,拼进 buildPersona。" },
|
||||
"rag": {
|
||||
"type": "object",
|
||||
"required": ["required", "top_k"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"required": { "type": "boolean", "description": "是否强要求基于私有知识库作答(expert 原型或非 none 合规 → true)。" },
|
||||
"top_k": { "type": "integer", "minimum": 1, "maximum": 20, "default": 5 },
|
||||
"scope": { "type": "array", "items": { "type": "string" }, "default": [], "description": "限定检索域(预留;MVP 为空=全库)。" }
|
||||
}
|
||||
},
|
||||
"model_preference": { "type": "array", "items": { "type": "string" }, "default": ["qwen"], "description": "模型偏好,路由缝。当前仅 'qwen'(符号名,非真实 model id),near-noop。" },
|
||||
"safety_level": { "type": "integer", "minimum": 0, "maximum": 10, "description": "越高越严。none=2 / soft=5 / strict=9。>=5 触发 Guardrail 强制免责。" },
|
||||
"block_keywords":{ "type": "array", "items": { "type": "string" }, "default": [], "description": "命中即被 Guardrail 软化替换。" },
|
||||
"disclaimer": { "type": "string", "default": "", "description": "safety>=5 且回答未含时,由 Guardrail 追加到结尾。" },
|
||||
"audit_required":{ "type": "boolean", "description": "专业强合规身份需资质审核(strict=true)。未认证→talentAudit=pending(软门,仍强制免责)。" },
|
||||
"compliance": { "type": "string", "enum": ["none", "soft", "strict"], "description": "合规等级,来源 professions.js。" }
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://digitalme.invoratec.cn/schemas/sub-talent.json",
|
||||
"title": "SubTalent",
|
||||
"description": "副天赋 = 风格/软技能,存于 SUB_REGISTRY(talents.js),将来搬 DB 集合 talent_sub_registry。两类接入点:style/constraint = 后置改写(只碰成稿,绝不改事实);hobby = 前置注入(进 System Prompt;机制预留,MVP 未铺货)。",
|
||||
"type": "object",
|
||||
"required": ["id", "name", "subtype", "desc"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "type": "string", "examples": ["humor", "concise"] },
|
||||
"name": { "type": "string", "examples": ["幽默感"] },
|
||||
"subtype": { "type": "string", "enum": ["style", "constraint", "hobby"], "description": "style/constraint→后置改写;hobby→前置注入。" },
|
||||
"desc": { "type": "string", "description": "给用户看的一句话说明。" },
|
||||
"rewrite_prompt": { "type": "string", "description": "subtype=style|constraint 必填:合并进单次后置改写指令的风格项。" },
|
||||
"inject_prompt": { "type": "string", "description": "subtype=hobby 必填:前置注入到 System Prompt 的兴趣/偏好项。" }
|
||||
},
|
||||
"allOf": [
|
||||
{ "if": { "properties": { "subtype": { "enum": ["style", "constraint"] } } }, "then": { "required": ["rewrite_prompt"] } },
|
||||
{ "if": { "properties": { "subtype": { "const": "hobby" } } }, "then": { "required": ["inject_prompt"] } }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://digitalme.invoratec.cn/schemas/talent-registry.json",
|
||||
"title": "TalentRegistry",
|
||||
"description": "天赋注册表。当前『按数据表形状』写在 talents.js(主由 professions 派生、副是 SUB_REGISTRY 数组);本 Schema 描述其逻辑形态,也是搬入 DB 后 talent_* 集合的契约。每个节点预留 version/active/gray_pct 以支持灰度与回滚。",
|
||||
"type": "object",
|
||||
"required": ["sub_talents"],
|
||||
"properties": {
|
||||
"main_talents": {
|
||||
"type": "array",
|
||||
"description": "主天赋表。MVP 由 professions.js × archetype × compliance 动态派生,不落库;搬 DB 时物化为一行一职业。",
|
||||
"items": { "$ref": "./main-talent.schema.json" }
|
||||
},
|
||||
"sub_talents": {
|
||||
"type": "array",
|
||||
"description": "副天赋注册表(当前 SUB_REGISTRY)。",
|
||||
"items": { "$ref": "./sub-talent.schema.json" }
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"versioning": {
|
||||
"description": "DB 化后每个节点附加的灰度/回滚字段(MVP 代码内暂无)。",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": { "type": "integer", "minimum": 1 },
|
||||
"active": { "type": "boolean", "default": true },
|
||||
"gray_pct": { "type": "number", "minimum": 0, "maximum": 100, "default": 100, "description": "灰度放量百分比。" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://digitalme.invoratec.cn/schemas/user-talent-instance.json",
|
||||
"title": "UserTalentInstance",
|
||||
"description": "一个分身(twin)当前选定的天赋。主天赋不重复存——它就是 twin.profession;这里只存副天赋选择与解锁时间。审核态存 twin.talentAudit。",
|
||||
"type": "object",
|
||||
"required": ["sub_talents"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"sub_talents": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true,
|
||||
"maxItems": 3,
|
||||
"description": "已选副天赋 id(必须 ∈ SUB_REGISTRY)。长度受 maxSubs(level)=min(3,1+level) 限制;服务端 validateSubs 兜底截断。"
|
||||
},
|
||||
"unlockedAt": { "type": ["string", "null"], "format": "date-time", "default": null, "description": "首次配置副天赋的时间。" }
|
||||
},
|
||||
"$comment": "关联字段(存在 twins 文档其它位置,非本对象):twin.profession = 主天赋 id;twin.talentAudit ∈ null|'pending'|'approved'(强合规身份的资质审核态);twin.verified = 蓝V(admin 置,audit 通过依据)。"
|
||||
}
|
||||
Reference in New Issue
Block a user