- 新增功能总览一条:纸感+夜读双主题、专注模式、⌘K 命令面板、应用内帮助页 /help - 角色卡去掉不存在的『目标』字段,改为按 Character 模型实有的 性格/背景(motive/traits/backstory/arc/speech_tics)
161 lines
8.7 KiB
Markdown
161 lines
8.7 KiB
Markdown
# 网文创作工作流(Writer Work Flow)
|
||
|
||
> AI 辅助的**中文网文写作工作流**,以 Web 应用形态交付。核心理念:**把写长篇当软件工程做**——先立架构(世界观 / 角色 / 大纲),对着规格逐章生成,每章写完即测(多维审查),全程维护单一真相源(数据库)。
|
||
|
||
作者不再让 AI「一口气瞎写十万字」,而是像写代码一样:需求(立项)→ 架构(设定库)→ 建模(角色卡)→ 接口(大纲)→ 实现(逐章生成)→ 测试(写完即审)→ 集成(验收更新全局状态)→ 回归(全书一致性)。AI 是「灵感增幅器 + 质检员」,作者始终掌控创意。
|
||
|
||
---
|
||
|
||
## 功能总览
|
||
|
||
- **引导式立项** — 一句灵感走向连载:选题材 / 基调 / 结局走向 / 叙事视角,AI 起草世界观、主角、金手指、总纲方案,一键建库。
|
||
- **设定库(Codex)** — 结构化的单一真相源:
|
||
- 角色卡(外貌 / 动机 / 性格 / 背景 / 口癖 / 性格弧光 / 人物关系图)
|
||
- 世界观(力量体系 / 势力 / 地理 / 词条)
|
||
- **大纲 / 细纲** — AI 排分卷分章骨架,逐层细化到场景清单,并提示伏笔回收窗口。
|
||
- **写章(SSE 流式)** — 注入设定 + 文风指纹,按 genre-aware 的网文写作教条(黄金三章、章末钩子、爽点密度)流式产出本章草稿。
|
||
- **五审(写完即审)** — 一致性 / 伏笔 / 文风 / 节奏 四审 + 人物塑造(advisory 建议性)。审查器**只读**,不静默改稿。
|
||
- **验收事务(HITL)** — 人在环中:作者裁决冲突后,唯一写入路径提交;未解决冲突阻断验收。章节摘要从**最终已验收文本**抽取,绝不污染真相源。
|
||
- **创作工具箱(15 个生成器)** — 声明式 skill 框架,「加生成器 = 加一份声明」:脑洞 / 书名 / 简介 / 取名 / 金手指 / 词条 / 黄金开篇 / 细纲 / 续写 / 扩写 / 降 AI / 拆书,外加世界观 / 角色 / 大纲。
|
||
- **模板库** — 复用与沉淀常用创作模板。
|
||
- **多 Provider LLM 网关** — 路由 / 回退 / 熔断的自建薄网关;Agent 只声明能力 tier,网关按配置映射到 provider+model;支持 Kimi Code 订阅 OAuth(device flow)。
|
||
- **沉浸式写作体验** — 纸感暖色 + 夜读双主题(`data-theme` 切换)、写作台专注模式(隐藏侧栏加宽正文)、`⌘K` 命令面板(跨页跳转 / 执行命令)、应用内帮助页 [`/help`](http://localhost:4000/help)(功能介绍 + 新手上手)。UI 对标编辑部式暖奶油设计语言,全程尊重 `prefers-reduced-motion` 与 WCAG AA。
|
||
|
||
---
|
||
|
||
## 技术栈(已锁定)
|
||
|
||
| 层 | 选型 |
|
||
|---|---|
|
||
| 前端 | **Next.js + TypeScript**(仅 UI;经 OpenAPI 生成的 TS 客户端调后端,无手写共享类型) |
|
||
| 后端 | **Python + FastAPI**(async,SSE) |
|
||
| 编排 | **LangGraph**(写→审→验收 图,Postgres checkpointer 可恢复) |
|
||
| LLM 访问 | 自建**薄网关**,覆盖 `anthropic` + `openai`(baseURL 兼容 DeepSeek/Kimi/Qwen/GLM)+ `google-genai` |
|
||
| 结构化输出 | **Pydantic + instructor** |
|
||
| ORM / 迁移 | **SQLAlchemy 2.0(async)+ Alembic** |
|
||
| 存储 | **Postgres**(原型不启用 pgvector) |
|
||
| 长任务 | FastAPI BackgroundTasks + `jobs` 表(原型不引入独立队列) |
|
||
|
||
工具链:**uv**(Python workspace,8 个成员)+ **pnpm**(前端)。Python 3.12+,Node 22。
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
前置:Python 3.12+ · Node 22 · [uv](https://docs.astral.sh/uv/) · pnpm · Docker
|
||
|
||
> **本地端口(宿主已 +1000,防与其他项目冲突)**:前端 **http://localhost:4000** · 后端 **http://localhost:9000**(API 文档 `/docs`)· Postgres **localhost:6432**。容器内部端口不变(3000 / 8000 / 5432),只改宿主发布端口;要改回默认各减 1000 即可。接线:前端 `apps/web/.env.local` 的 `NEXT_PUBLIC_API_BASE=http://localhost:9000` 指向后端;后端 `.env` 的 `CORS_ORIGINS` 放行 `http://localhost:4000`、`DATABASE_URL` 指向 `localhost:6432`。
|
||
|
||
```bash
|
||
# 1. 克隆后,安装后端依赖(仓库根,uv workspace)
|
||
uv sync
|
||
|
||
# 2. 安装前端依赖
|
||
cd apps/web && pnpm install && cd ../..
|
||
|
||
# 3. 配置环境变量(CREDENTIAL_ENC_KEY 为必填的凭据加密 Fernet key,启动即校验)
|
||
cp .env.example .env
|
||
# 生产请重新生成:
|
||
# uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||
|
||
# 4. 起 Postgres 并跑迁移
|
||
docker compose up -d pg
|
||
uv run alembic upgrade head
|
||
|
||
# 5. 起后端 API(http://localhost:9000,文档 /docs)— 宿主端口 +1000
|
||
uv run uvicorn ww_api.main:app --port 9000 --reload
|
||
|
||
# 6. 起前端(另开终端,http://localhost:4000)— pnpm dev 已内置 -p 4000
|
||
cd apps/web && pnpm dev
|
||
```
|
||
|
||
或一键起全套(pg + api + web,宿主端口均已 +1000):
|
||
|
||
```bash
|
||
docker compose up # web → :4000 · api → :9000 · pg → :6432
|
||
```
|
||
|
||
> **LLM API Key 不放 `.env`**:在应用设置页 **`/settings/providers`** 录入,密文存于数据库凭据库(用 `CREDENTIAL_ENC_KEY` 加密)。`.env` 里只有那把加密主密钥本身。
|
||
|
||
---
|
||
|
||
## 工具链 & 门禁
|
||
|
||
改动声明「完成」前须全绿(TDD 先红后绿,覆盖率 ≥ 80%)。
|
||
|
||
**后端**(仓库根):
|
||
|
||
```bash
|
||
uv run ruff check . # lint
|
||
uv run ruff format . # format
|
||
uv run mypy packages apps # 类型
|
||
uv run pytest -q # 单元 + 集成(需 pg:docker compose up -d pg)
|
||
uv run alembic check # 改过模型后校验无迁移漂移
|
||
uv run pytest -q --cov --cov-report=term-missing --cov-fail-under=80 # 覆盖率门禁
|
||
```
|
||
|
||
**前端**(`apps/web`):
|
||
|
||
```bash
|
||
pnpm lint
|
||
pnpm typecheck
|
||
pnpm test # vitest(范围 lib/**:纯逻辑 + hooks)
|
||
pnpm build
|
||
pnpm test:coverage # 覆盖率门禁(阈值 80%)
|
||
```
|
||
|
||
**改过后端 schema** 后重生成 TS 客户端:
|
||
|
||
```bash
|
||
cd apps/web && pnpm gen:api
|
||
```
|
||
|
||
CI 见 `.github/workflows/ci.yml`(backend job 带 pg service 跑 ruff/mypy/alembic/pytest;frontend job 跑 gen:api/lint/typecheck/test)。
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
apps/
|
||
api/ FastAPI 应用:路由 / service / 请求响应 schema / SSE 端点
|
||
web/ Next.js 前端:Server Components 读视图 + Client 编辑器/流式交互
|
||
packages/
|
||
shared/ 跨栈 Pydantic 契约 schema(前端经 OpenAPI 消费)
|
||
config/ 应用配置(Settings,环境变量边界)
|
||
db/ SQLAlchemy 2.0 模型 / Alembic 迁移 / Repository
|
||
llm_gateway/ 多 provider 网关:路由 / 回退 / 熔断 / adapter / 计费台账
|
||
agents/ 声明式 AgentSpec + 外置 prompt(Agent 只声明能力 tier)
|
||
core/ domain 领域逻辑 · memory 记忆真相源(确定性选择注入)· orchestrator LangGraph 图
|
||
skills/ 工具箱注册表 + skill 注册(声明驱动的生成器)
|
||
```
|
||
|
||
---
|
||
|
||
## 文档地图
|
||
|
||
四份 spec 分层,每层细化上一层;实现暴露的规格缺口须回写对应 spec。
|
||
|
||
| 文档 | 回答什么 | 何时读 |
|
||
|---|---|---|
|
||
| [`PRODUCT_SPEC.md`](./PRODUCT_SPEC.md) | 是什么 & 为什么 —— 问题、功能(含 P0/P1/P2 优先级)、数据模型、端点、Agent | 理解范围或某功能 |
|
||
| [`UX_SPEC.md`](./UX_SPEC.md) | 长什么样 —— 信息架构、用户流、页面线框、组件、视觉 token(纸感 / warm-cream 主题) | 做任何 UI |
|
||
| [`ARCHITECTURE.md`](./ARCHITECTURE.md) | 怎么实现 —— 完整 DDL、网关内部、编排引擎、API 契约、横切关注点 | 实现后端 / 数据 / 网关 |
|
||
| [`DEV_PLAN.md`](./DEV_PLAN.md) | 按什么顺序 —— Phase 0–5,每个任务标注学科 skill | 挑下一个任务 |
|
||
| [`PROGRESS.md`](./PROGRESS.md) | 交付到哪了 —— 权威状态台账 + 变更日志 | 开工前必读 |
|
||
|
||
冲突裁决:更具体 / 更靠后的文档为准(`ARCHITECTURE` > `UX_SPEC`/`DEV_PLAN` > `PRODUCT_SPEC`)。协作与开发规范见 [`CLAUDE.md`](./CLAUDE.md)。
|
||
|
||
---
|
||
|
||
## 测试与原型边界
|
||
|
||
- **测试**:TDD 强制(先写失败测试);三层——单元(一个节点/函数/Repository,mock IO)→ 集成(FastAPI 端点 + DB + mock 网关)→ E2E(写→审→验收,mock 网关)。**所有测试一律 mock LLM,绝不命中真实 LLM API**。覆盖率门禁 ≥ 80%。
|
||
|
||
原型作用域,以下**明确不做**(勿误用于生产):
|
||
|
||
- **单用户,无 auth / 多租户** —— `users` / `owner_id` 为占位桩。
|
||
- **无向量检索 / pgvector** —— 记忆注入是确定性按需选择(显式点名 + 主要角色 + 最近 N 章),非向量搜索(向量检索列 P2)。
|
||
- **无独立任务队列** —— 长任务走 FastAPI BackgroundTasks + `jobs` 表。
|
||
- 不做模型微调、内容分发 / 发布平台对接、移动原生 App。
|