feat: M4 文风 + M5 生成/多provider/Skill + Kimi Code 订阅接入 + 本地联调修复
M4(文风): style-auditor 双轨(提取指纹/漂移第四审)+ jobs 长任务框架(zombie reaper) + 回炉 refine + GET /style read-back。 M5(生成+扩展): worldbuilder/character-gen(入库 continuity 409 gate + partition_writes 白名单 + schema→JSONB 形变); 网关多 provider 回退链/熔断/能力降级(Anthropic/Gemini 适配器);Skill registry + 表权限沙箱 + 规则; 前端 角色生成器/世界观/Codex/规则页/技能库/⌘K 命令面板。 K1(Kimi Code 订阅接入): OAuth device-flow(kimi-code)+ 静态 Console key(kimi-code-key)两路径; coding 端点 KimiCLI 伪造头(实测 UA allow-list 门禁,缺则 403)+ JSON 模式结构化(thinking ⊥ tool_choice)。 本地联调修复: CORS 中间件;assemble 注入 premise+「写第N章」指令(修空 prompt 400); GET /outline·/draft read-back + 大纲/工作台/审稿页重载;写页 client/server 常量边界 + notFound 健壮化; 字数 toLocaleString locale 水合;审稿页终稿从已存草稿 seed(修 accept 422)。 门禁: backend ruff/mypy(157)/alembic 无漂移/pytest 451 · frontend lint/tsc/vitest/build。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -147,3 +147,154 @@ class PaceReview(BaseModel):
|
||||
default_factory=list,
|
||||
description="逐段爽点节拍强度序列(整数,供前端节拍图可视化)",
|
||||
)
|
||||
|
||||
|
||||
# ---- 文风提取轨结构化输出(ARCH §5.4 style-auditor「提取」轨 / §6.9)----
|
||||
|
||||
|
||||
class StyleDimension(BaseModel):
|
||||
"""单维文风指纹:维度名 + 取值 + 原文证据引用(ARCH §6.9)。
|
||||
|
||||
每维必须带原文证据(quotes),便于作者核验「这条文风结论来自哪句」。
|
||||
"""
|
||||
|
||||
name: str = Field(description="文风维度名(如句长节奏 / 叙事人称 / 用词风格)")
|
||||
value: str = Field(description="该维度在样本中的取值/概括")
|
||||
evidence: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="原文证据:支撑该维度判定的样本原句摘录",
|
||||
)
|
||||
|
||||
|
||||
class StyleFingerprintResult(BaseModel):
|
||||
"""文风指纹提取产出:16 维文风指纹清单(ARCH §5.4 提取轨)。
|
||||
|
||||
声明式 writes(不变量 #3):本结构是从样本提取的纯产物,落 `style_fingerprint` 表
|
||||
经端点(T4.3),不在 agent 节点直接写库。16 维 = 9 通用 + 7 中文网文专有。
|
||||
"""
|
||||
|
||||
dimensions: list[StyleDimension] = Field(
|
||||
default_factory=list,
|
||||
description="文风维度清单(每维带原文证据);无则空列表",
|
||||
)
|
||||
|
||||
|
||||
# ---- 文风漂移轨结构化输出(ARCH §5.4 style-auditor「打分」轨 = 第四审)----
|
||||
|
||||
|
||||
class StyleDriftSegment(BaseModel):
|
||||
"""单个漂移段:段索引 + 相似度分 + 可选标签(ARCH §5.4 打分轨)。
|
||||
|
||||
`idx` 是本章段索引(0 起),`score` 是该段相对文风指纹的相似度(0–100,越低越偏);
|
||||
`label` 可缺(如「机翻腔」「叙述拖沓」等漂移类型说明)。
|
||||
"""
|
||||
|
||||
idx: int = Field(description="本章段索引(0 起)")
|
||||
score: int = Field(description="该段相对文风指纹的相似度(0–100,越低越偏离)")
|
||||
label: str | None = Field(default=None, description="漂移类型标签(如「机翻腔」);可缺")
|
||||
|
||||
|
||||
class StyleDriftReview(BaseModel):
|
||||
"""文风漂移续审结构化产出:整体相似度 + 低相似段(ARCH §5.4 / 第四审)。
|
||||
|
||||
只读(不变量 #3)。`score` 是整章相对文风指纹的整体相似度(0–100)。
|
||||
**无指纹优雅降级**:材料中无文风指纹时返回 `score=100, segments=[]`(默认值),
|
||||
不报错、不阻塞其余审(§5.2 失败隔离之外的内容性兜底)。
|
||||
"""
|
||||
|
||||
score: int = Field(default=100, description="整章相对文风指纹的整体相似度(0–100)")
|
||||
segments: list[StyleDriftSegment] = Field(
|
||||
default_factory=list,
|
||||
description="低相似度(疑似漂移)段清单;无则空列表(含无指纹降级)",
|
||||
)
|
||||
|
||||
|
||||
# ---- worldbuilder 结构化输出(ARCH §5.4 worldbuilder 行 / §6.5 / §4.5)----
|
||||
|
||||
|
||||
class WorldEntityCard(BaseModel):
|
||||
"""单个世界观实体(ARCH §5.4:`{type,name,rules}` 硬规则显式)。
|
||||
|
||||
`type`(势力/地理/力量体系/物品…)+ `name` + `rules`(**显式硬规则**清单:
|
||||
不可违背的设定,供后续 continuity 续审引用比对)。映射 `world_entities` 表
|
||||
(type/name 列 + rules 入 JSONB);落库经入库端点(T5.2,不变量 #3)。
|
||||
"""
|
||||
|
||||
type: str = Field(description="实体类型(势力 / 地理 / 力量体系 / 物品 / 概念 等)")
|
||||
name: str = Field(description="实体名")
|
||||
rules: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="该实体的硬规则清单(显式不可违背设定,供 continuity 校验引用)",
|
||||
)
|
||||
|
||||
|
||||
class WorldGenResult(BaseModel):
|
||||
"""worldbuilder 结构化产出:世界观实体清单(ARCH §5.4 writes=world_entities)。
|
||||
|
||||
声明式 writes(不变量 #3):本结构是 worldbuilder 的纯产物,落 `world_entities` 表
|
||||
经入库端点(T5.2),不在 agent 节点直接写库。
|
||||
"""
|
||||
|
||||
entities: list[WorldEntityCard] = Field(
|
||||
default_factory=list,
|
||||
description="生成的世界观实体清单;无则空列表",
|
||||
)
|
||||
|
||||
|
||||
# ---- character-gen 结构化输出(ARCH §5.4 character-gen 行 / §6.5 / §4.5)----
|
||||
|
||||
|
||||
class CharacterRelation(BaseModel):
|
||||
"""单条人物关系(写入 `characters.relations` JSONB 冗余)。
|
||||
|
||||
`name`(关系对象角色名)+ `kind`(宿敌 / 师徒 / CP / 同盟 …)+ 可选 `note`。
|
||||
双向边由编排器在入库时统一维护(§4.5 三关键能力之三),本 schema 仅声明本侧。
|
||||
"""
|
||||
|
||||
name: str = Field(description="关系对象的角色名")
|
||||
kind: str = Field(description="关系类型(宿敌 / 师徒 / CP / 同盟 / 工具人 等)")
|
||||
note: str | None = Field(default=None, description="关系说明(可缺)")
|
||||
|
||||
|
||||
class CharacterCard(BaseModel):
|
||||
"""单张结构化角色卡(ARCH §5.4 character-gen 行:name/role/traits/backstory/arc/...)。
|
||||
|
||||
映射 `characters` 表列(name/role/backstory + traits/arc/speech_tics/tags/relations
|
||||
入 JSONB);落库经入库端点(T5.2,不变量 #3)。`role` = 角色定位(主角/CP/对手/导师/
|
||||
工具人,§4.5 网文专属)。
|
||||
"""
|
||||
|
||||
name: str = Field(description="角色名(取名风格契合世界观)")
|
||||
role: str = Field(description="角色定位(主角 / CP / 对手 / 导师 / 工具人 等)")
|
||||
traits: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="性格特质清单(核心-表层-阴影 / 动机 / 欲望 / 恐惧)",
|
||||
)
|
||||
backstory: str = Field(description="背景故事(出身、关键经历、创伤/转折点)")
|
||||
arc: str = Field(description="人物弧光(起点 → 转变 → 终点,与剧情挂钩)")
|
||||
speech_tics: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="口癖/语言风格(用词偏好、口头禅,喂给文风一致性)",
|
||||
)
|
||||
tags: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="人设标签/萌点(网文专属,辅助检索与差异化)",
|
||||
)
|
||||
relations: list[CharacterRelation] = Field(
|
||||
default_factory=list,
|
||||
description="关系网:与已有/同批角色建边;无则空列表",
|
||||
)
|
||||
|
||||
|
||||
class CharacterGenResult(BaseModel):
|
||||
"""character-gen 结构化产出:一组角色卡(ARCH §5.4 writes=characters / §4.5 群像)。
|
||||
|
||||
声明式 writes(不变量 #3):本结构是 character-gen 的纯产物,落 `characters` 表
|
||||
经入库端点(T5.2),且**入库前过编排器 continuity 校验**(§6.5)。单生成 → 1 张卡;
|
||||
批量群像 → 多张(防雷同:生成时注入「已生成卡 + 已有角色」要求差异化)。
|
||||
"""
|
||||
|
||||
cards: list[CharacterCard] = Field(
|
||||
default_factory=list,
|
||||
description="生成的角色卡清单;无则空列表",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user