Wiki 生成
Wiki 生成是长任务:采集资料 → 压缩 → 规划目录 → 并发生成每一页 → 生成总览页 → 整套落库。它的难点不在单页文案,而在「一次生成 4–10 页、每页可能被续写补全、部分页失败不能拖垮整套」这条工程链上。
阶段顺序固定:规划先于生成、总览最后写;任何一页失败都会进入警告集合,而不是中断整套。
触发与任务模型
| 端点 | 说明 |
POST /api/wiki/projects/{projectId}/generate | 入队整套生成,请求体 { modelId? } |
POST /api/wiki/{id}/regenerate | 重生成单页,复用该页规划阶段的 Brief |
GET /api/wiki · GET /api/wiki/sets · GET /api/wiki/{id} | 页面列表 / 套件列表 / 单页详情,均可按 projectId 过滤 |
GET /api/wiki/jobs · GET /api/wiki/jobs/{id} | 生成任务列表与详情(阶段、进度、错误、警告) |
GET /api/wiki/sets/{setId}/export | 导出 zip:每页一个 Markdown(00-…md、01-…md)+ 一个 README.md 索引 |
DELETE /api/wiki/{id} · DELETE /api/wiki/sets/{setId} | 删除单页 / 整套 |
后台任务类型是 WikiGenerate,模型 id 通过任务元数据传递(Guid.TryParse(item.Metadata))。同一个项目若已有排队中或运行中的生成任务,EnqueueGenerateAsync 直接返回那条任务,不重复排队。前端在项目页跳转 /wiki?project=…&generate=1 会进入后自动触发一次生成并清掉参数;模型选择器只列非 embedding 用途的模型,留空表示用默认补全模型。
资料采集与压缩
- 采集器负责把「受管项目」变成资料:本地目录或远端工作项目、基础资料与代码上下文。
- 代码语义索引可用时按语义命中取片段,每页约 10 条(
SemanticHitsPerPage = 10);索引不可用时回退源码采样。
- 送进模型前对
BaseContext 与 rawCodeContext 各跑一次压缩管道(同样受 Enabled / Mode / 节点配置影响)。
- 采集失败会直接返回错误且不入后台队列:本地目录不存在、远端连接失败、工作项目未找到、目录为空各有独立文案。
规划阶段
| 项 | 取值 |
| 返回结构 | { chapters: [{ title, pages: [{ title, brief }] }] } |
| 规模约束 | 2–4 章,每章 1–3 页,总 4–10 页(上限常量 MaxModulePages = 10) |
| 规划 token 上限 | 3072 |
| 规划失败 | 异常被捕获后回退默认四页:项目概述与技术栈 / 目录结构 / 核心模块详解 / 快速开始与配置,不阻塞整套生成 |
Brief 会落库,成为该页的写作要点;单页重生成时直接复用它,因此重生成不会偏离原规划。
生成阶段
| 机制 | 取值 / 行为 |
| 并发 | MaxPageConcurrency = 4 |
| 单页输出上限 | ContentMaxTokens = 8192 |
| 续写触发 | 结束原因是 length / max_tokens,或代码围栏未闭合(围栏计数为奇数) |
| 续写上限 | MaxContinueRounds = 4,续写提示会带上已生成的全部内容 |
| 续写容错 | 续写结果里出现「已有内容」/「未提供」/「无法判断」等元话术时直接丢弃这一段 |
| 单页重试 | PageRetryCount = 1,退避 800ms |
| 正文要求 | Markdown、中文、只能依据资料不得编造、结构/流程/模块关系必须配 Mermaid 图、目录树用 text 代码块、路径与类型用行内代码 |
| 页间协作 | 提示词会列出同套其他页面,允许相互引用 |
总览页单独生成:要求含项目简介、核心特性、技术栈、## 总体架构(必须带 Mermaid graph / flowchart)与末节 ## 文档导航(按章节层级原样列出)。总览页失败时回退为纯文本总览(项目简介 + 文档导航)。
落库、套件与过期判定
| 字段 / 规则 | 说明 |
WikiDocument | ProjectId · SetId · SortOrder · Title · Chapter · Brief · Content |
WikiGenerationJob | Status(0 排队 / 1 运行 / 2 完成 / 3 失败) · Stage · Progress · TotalPages · DonePages · ErrorMessage · WarningMessage · ModelId · SetId · CompletedAt |
| 写入顺序 | 先把主题页生成完并汇总,再生成总览页,最后一次性写库:总览 SortOrder = 0,主题页 = 规划序 + 1 |
| 套件聚合 | GetAllAsync 按 SetId 分组、组内按 SortOrder 排序,总览页恒在最前 |
| 过期判定 | GetSetsAsync 调用上下文采集器的过期计算,填充 IsStale 与 StaleFileCount(项目文件变动后提示重新生成) |
失败与降级
| 情况 | 行为 |
| 没有可用模型 | 任务失败,记录 wiki.modelNotConfigured |
| 单页内容为空 | 记警告并按 PageRetryCount 重试;仍为空则该页失败,进入 failedPages |
| 部分页失败 | 整套仍写库,失败页写入 WarningMessage(前端橙色提示),不影响已成功的页 |
| 全部主题页失败 | 抛 wiki.allPagesFailed |
| 总览页失败 | 回退纯文本总览(项目简介 + 文档导航) |
| 单页重生成失败 | 返回 wiki.regenerateFailed |
| 后台任务被停止打断 / 主动取消 | 同图谱任务:停止则重新排队,主动取消记失败 |
观测
- 前端任务条:
stage + donePages/totalPages + 百分比;失败红色条带 errorMessage;部分失败橙色提示带 warningMessage。
- 阶段文案来自本地化键:
wiki.stageQueued、stageStarting、stageCollecting、stagePlanning、stageGeneratingPages、stageOverview、stageCompleted。
- 用量来源
Wiki:输入 token、压缩后 token、延迟。
- 没有页面级耗时字段:目前只有任务级的进度与阶段,页级排查看日志。
实作要点
- 规划质量决定整套质量:规划若是泛泛而谈,后面每页都会泛。想调整结构,先改规划阶段的提示词与规模约束。
- 续写是「补全」不是「重写」:它把已生成内容一并送回模型,所以
ContentMaxTokens 越小续写轮次越多、上下文越贵。
- 部分页失败不是事故:整套仍可用,直接对失败页点「重生成」即可。
- 导出 zip 的文件名以序号开头(
00-、01-),保证在文件管理器里与站内顺序一致。
- 换了压缩管道配置会改变送进模型的资料,从而影响 Wiki 内容;排查「内容不如以前」时把这条算进去。