Files
writer-work-flow/packages/skills/ww_skills/toolbox_registry.py
Yaojia Wang 452bd56d95 feat(agents,core,config): 写章 craft 教条块 + genre-aware 片段 + 开篇黄金三章特判
- 新增 write_craft.md 品类无关写章 craft 内核(网文语域/show-don't-tell/对话 voice/
  反注水/结构性文字质感,灵活原则非穷举清单)+ load_craft_doctrine()(import 期读盘,
  不入 SPECS/金标准)
- build_write_request 把 craft 教条作为最前的 cache=True system 块注入(craft→stable_core,
  守缓存前缀 #9,tier=writer 不写 model)
- 新增 packages/config GENRE_CRAFT 题材片段表,assemble 按 project.genre 注入 stable_core;
  ProjectSpecView + SqlProjectSpecRepo 透传 genre
- 开篇前 3 章在 volatile 注入黄金三章提示(含章号→每章易变,不进缓存前缀)
- 修正 toolbox_registry 注释:11 条 → 15 条(legacy 3 + 新 8 + Scope B 4)
2026-07-06 14:29:43 +02:00

250 lines
8.5 KiB
Python
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.

"""T6 创作工具箱 · 生成器注册表(`TOOLBOX`:把每个生成器声明成一条 `GeneratorTool`)。
「加一个生成器」= 在本表加一份声明descriptor 在代码、不进 DB——保 Pydantic schema
为真类避免迁移DB `skills` 表与只读注册表/权限故事不变)。
两类形态:
- **legacy**(已上架的 世界观/人设/大纲):`spec=None`,带 `legacy_route` 指向现有更丰富的
入库/冲突页面,前端据 `legacy_route` 直接跳页,不回归既测代码(通用 generate/ingest
端点对它们返 404/422
- **新工具**8 个):带 `spec`§5.1 声明)+ `output_schema`(结构化产物真类)+
`context_strategy`(注入策略)+ `input_fields`(声明式表单),走通用执行器;声明 `ingest`
者可经通用 ingest 端点入库(复用既有 continuity 预检 + 白名单 gate不变量 #3
不变量 #2只声明 tierspec 已守)/ #3AI 产出入库必经验收 gate预览不写库
"""
from __future__ import annotations
from ww_agents import SPECS
from ww_agents.schemas import (
BlurbResult,
BookTeardownResult,
ContinuationResult,
DeAiResult,
DetailedOutlineResult,
GlossaryResult,
GoldenFingerResult,
IdeaListResult,
NameListResult,
OpeningResult,
PolishResult,
TitleListResult,
)
from ww_skills.toolbox import GeneratorTool, IngestSpec, InputField
# 复用的常见输入字段DRY每个生成器都有「一句话需求」textarea
_BRIEF_FIELD = InputField(
name="brief",
label="一句话需求",
type="textarea",
required=False,
help="描述创作方向/约束;留空则按作品设定与题材自由发散",
)
def _chapter_no_field() -> InputField:
"""按章展开的生成器(开篇/细纲)所需的章号输入。"""
return InputField(
name="chapter_no",
label="章号",
type="number",
required=True,
default="1",
help="要生成/展开的章节号(读取该章大纲节拍)",
)
# 原文输入(扩写/降AI率/拆书样本所需的大段正文)。
_SOURCE_TEXT_FIELD = InputField(
name="text",
label="原文",
type="textarea",
required=True,
help="待处理的正文/样本片段(扩写/降AI 的原文;拆书的章节样本)",
)
# 创作工具箱注册表key → 描述符。15 条legacy 3 + 新 8 + Scope B 4续写/扩写/降AI/拆书)。
TOOLBOX: dict[str, GeneratorTool] = {
# ---- legacyspec=None前端走 legacy_route 跳现有页面)----
"worldbuilding": GeneratorTool(
key="worldbuilding",
title="世界观生成器",
subtitle="构建内部自洽的世界观与硬规则",
spec=None,
output_schema=None,
context_strategy="with_project",
input_fields=[],
legacy_route="/projects/{id}/codex?gen=world",
),
"character": GeneratorTool(
key="character",
title="人设生成器",
subtitle="群像防雷同的结构化角色卡",
spec=None,
output_schema=None,
context_strategy="with_world",
input_fields=[],
legacy_route="/projects/{id}/codex?gen=character",
),
"outline": GeneratorTool(
key="outline",
title="大纲生成器",
subtitle="分卷分章 + 伏笔回收窗口",
spec=None,
output_schema=None,
context_strategy="with_project",
input_fields=[],
legacy_route="/projects/{id}/outline",
),
# ---- 新工具(走通用执行器)----
"brainstorm": GeneratorTool(
key="brainstorm",
title="脑洞生成器",
subtitle="突破想象,脑洞大开",
spec=SPECS["brainstorm"],
output_schema=IdeaListResult,
context_strategy="brief_only",
input_fields=[_BRIEF_FIELD],
),
"book-title": GeneratorTool(
key="book-title",
title="书名生成器",
subtitle="一秒生成抓人书名",
spec=SPECS["book-title"],
output_schema=TitleListResult,
context_strategy="brief_only",
input_fields=[_BRIEF_FIELD],
),
"blurb": GeneratorTool(
key="blurb",
title="简介生成器",
subtitle="多版差异化书页文案",
spec=SPECS["blurb"],
output_schema=BlurbResult,
context_strategy="with_project",
input_fields=[_BRIEF_FIELD],
),
"name": GeneratorTool(
key="name",
title="名字生成器",
subtitle="契合世界观的人/物/地命名",
spec=SPECS["name"],
output_schema=NameListResult,
context_strategy="with_world",
input_fields=[
_BRIEF_FIELD,
InputField(
name="kind",
label="命名对象",
type="text",
required=False,
help="人物 / 势力 / 地点 / 功法 / 物品 等",
),
],
),
"golden-finger": GeneratorTool(
key="golden-finger",
title="金手指生成器",
subtitle="自洽机制 + 成长 + 限制代价",
spec=SPECS["golden-finger"],
output_schema=GoldenFingerResult,
context_strategy="with_world",
input_fields=[_BRIEF_FIELD],
ingest=IngestSpec(table="world_entities"),
),
"glossary": GeneratorTool(
key="glossary",
title="词条生成器",
subtitle="带硬规则的世界观术语表",
spec=SPECS["glossary"],
output_schema=GlossaryResult,
context_strategy="with_world",
input_fields=[_BRIEF_FIELD],
ingest=IngestSpec(table="world_entities"),
),
"opening": GeneratorTool(
key="opening",
title="黄金开篇生成器",
subtitle="多版高代入感开篇正文",
spec=SPECS["opening"],
output_schema=OpeningResult,
context_strategy="with_outline_chapter",
input_fields=[_chapter_no_field(), _BRIEF_FIELD],
),
"fine-outline": GeneratorTool(
key="fine-outline",
title="细纲生成器",
subtitle="把章节粗节拍展开为场景序列",
spec=SPECS["fine-outline"],
output_schema=DetailedOutlineResult,
context_strategy="with_outline_chapter",
input_fields=[_chapter_no_field(), _BRIEF_FIELD],
ingest=IngestSpec(table="outline"),
),
# ---- 竞品快赢Scope B续写/扩写/降AI率 preview-only拆书 F1 可落库 rules ----
"continue": GeneratorTool(
key="continue",
title="续写生成器",
subtitle="承接前文,无缝续写下文",
spec=SPECS["continue"],
output_schema=ContinuationResult,
context_strategy="with_prior_chapter",
input_fields=[
InputField(
name="chapter_no",
label="续写章号",
type="number",
required=False,
help="续写的目标章号(读取该章已写正文承接;缺则按设定起笔)",
),
_BRIEF_FIELD,
],
),
"expand": GeneratorTool(
key="expand",
title="扩写生成器",
subtitle="在原文基础上丰富细节铺陈",
spec=SPECS["expand"],
output_schema=PolishResult,
context_strategy="text_input",
input_fields=[_SOURCE_TEXT_FIELD, _BRIEF_FIELD],
),
"de-ai": GeneratorTool(
key="de-ai",
title="降 AI 率生成器",
subtitle="去机翻腔,更自然的人写质感",
spec=SPECS["de-ai"],
output_schema=DeAiResult,
context_strategy="text_input",
input_fields=[_SOURCE_TEXT_FIELD, _BRIEF_FIELD],
),
"teardown": GeneratorTool(
key="teardown",
title="拆书生成器",
subtitle="拆解主题/原型/结构/钩子套路",
spec=SPECS["teardown"],
output_schema=BookTeardownResult,
context_strategy="text_input",
input_fields=[
InputField(
name="kind",
label="书名",
type="text",
required=False,
help="待拆解作品的书名(供拆解对照)",
),
_SOURCE_TEXT_FIELD,
_BRIEF_FIELD,
],
ingest=IngestSpec(table="rules"), # F1拆书结论拍平为项目 rules 条目落库
),
}
def get_tool(key: str) -> GeneratorTool | None:
"""按 key 取生成器描述符;未知 key → None端点据此返 404"""
return TOOLBOX.get(key)