编译流水线
编译流水线通过四个顺序执行的 LLM 阶段将原始内容转化为结构化 wiki 文章。Go 后端负责编排并发执行;Python AI 引擎(kb-ai)执行实际的 LLM 调用。
流水线概览
┌─────────┐ ┌──────────┐ ┌───────┐ ┌───────┐
│ Extract │───▶│ Classify │───▶│ Write │───▶│ Index │
└─────────┘ └──────────┘ └───────┘ └───────┘
并行执行 顺序执行 顺序执行 顺序执行Extract 阶段在 worker 池中并行运行。一批任务提取完成后,剩余阶段在 Pipeline Worker 中按用户顺序执行。
阶段 1:Extract(提取)
目标:从原始文本中提取结构化信息。
Extract 阶段读取提交的内容,产出结构化提取结果,包含:
- 概念和实体
- 决策及其依据
- 行动项和责任人
- 关键事实和关联关系
提取策略
| 策略 | 适用场景 | 工作方式 |
|---|---|---|
chunked | 短到中等长度文档 | 分块后独立提取每个块 |
summarize | 长文档、会议转写 | 先用便宜模型分块摘要,再从摘要中提取 |
auto | 默认策略 | 根据 chunk 数量自动选择 chunked 或 summarize |
summarize 策略对长内容(会议记录、大型文档)显著更省成本,因为摘要阶段使用更小的模型,将压缩后的文本再交给提取模型处理。
并行执行
Go Dispatcher 将 Extract 任务分配给 worker 池(默认 4 个)。每个 worker 独立调用 Python AI 引擎的 /extract 端点。多个文档同时提取,受 Dispatcher 信号量约束。
阶段 2:Classify(分类)
目标:决定每个提取项在 wiki 中的归属。
Classify 阶段检查提取结果和当前 wiki 结构,然后:
- 将提取项映射到现有 wiki 文章(用于合并)
- 识别需要新建文章的项
- 对相关项进行分组,避免碎片化
该阶段读取当前 master-index.md 以了解现有 wiki 拓扑结构。
阶段 3:Write(写入)
目标:生成或更新 Markdown 文章。
根据分类结果,Write 阶段执行:
- 创建——从提取项生成新的 Markdown 文章
- 合并——将新信息融入现有文章,去重并重新组织结构
输出为规范的 Markdown,含标题、列表和互链——设计上兼顾人类阅读和 LLM 消费。
阶段 4:Index(索引)
目标:保持导航索引最新。
文章写入后,Index 阶段更新:
master-index.md——顶层目录,供 LLM 检索时导航- Topic indexes——按主题分组的相关文章索引
- People stubs——提到的人物的简要参考页
master-index 是关键产物:它是所有 LLM 迭代检索查询的入口。
增量编译
KaaS 只重新编译新增或变更的内容。当提交与现有 wiki 内容重叠的材料时:
- Extract 仅处理新提交的内容
- Classify 识别与现有文章的重叠
- Write 执行合并(非替换)——保留现有内容的同时整合新信息
- Index 仅刷新受影响的条目
这意味着提交 10 个文档不会重新处理之前的 100 个。
并发与加速
Dispatcher(调度器)
Dispatcher 是中央协调器:
- 按可配置间隔轮询任务队列(
poll_interval_ms) - 以租约方式认领任务(防止重复处理)
- 通过 Go channel 信号量强制并发上限
- 断路器打开时暂停认领
Extract Worker Pool(提取工作池)
多个 goroutine 并行处理 Extract 任务:
- 默认并发度:4 个 worker(配置项
extract_workers) - 每个 worker 通过 HTTP 调用 Python 的
/extract端点 - 进度通过 SSE 流式推送到前端
Pipeline Worker(流水线工作器)
提取完成后,单个 Pipeline Worker 按用户批次执行剩余阶段:
- Classify → Write → Index 顺序执行
- 将同一用户所有待处理的提取结果批量处理
- 调用 Python 的
/pipeline-stream端点(SSE 进度)
Circuit Breaker(断路器)
防御 LLM 供应商故障:
| 参数 | 默认值 | 说明 |
|---|---|---|
cb_failure_threshold | 5 | 连续失败次数阈值,触发打开状态 |
cb_cooldown_sec | 30 | 打开后进入半开探针的冷却秒数 |
状态机:
- Closed(关闭)——正常运行;失败递增计数器
- Open(打开)——所有调用立即拒绝;Dispatcher 停止认领任务
- Half-Open(半开)——冷却期后允许一个探针请求;成功则关闭断路器,失败则重新打开
Lease & Heartbeat(租约与心跳)
每个认领的任务携带一个带超时的租约(lease_timeout_sec,默认 300 秒)。Worker 通过心跳定期续约。如果 worker 崩溃:
- 租约到期
- Dispatcher 的
RecoverExpired扫描将任务重新入队 - 另一个 worker 接手处理
这保证了至少一次(at-least-once)处理,无需人工干预。
配置参考
所有编译流水线设置位于 etc/kaas.toml 的 [worker] 节:
[worker]
extract_workers = 4 # Extract 并行 worker 数
pipeline_concurrency = 2 # Pipeline worker 并发度
poll_interval_ms = 1000 # 队列轮询间隔(ms)
lease_timeout_sec = 300 # 租约超时后恢复(s)
cb_failure_threshold = 5 # 连续失败多少次打开断路器
cb_cooldown_sec = 30 # 断路器冷却期(s)