Skip to content

架构

KaaS 采用三层架构:React Web UI、Go 后端、Python AI 引擎。单个 Docker 镜像打包所有组件——无需 sidecar 容器。

概览

KaaS 系统架构

技术职责
Web UIReact 19 + Vite + shadcn/uiChat、Submit、Wiki、Status
后端Go (net/http + go-zero/conf)REST API、Worker Pool、任务队列、MCP 端点
AI 引擎Python (kb-ai daemon)LLM 编译流水线、检索、问答
存储SQLite(默认)任务队列、编译状态

Web UI 层

前端是基于 React 19Viteshadcn/ui 的单页应用,包含四个页面:

  • Chat — SSE 流式对话,附带指向 wiki 文章的来源引用
  • Submit — 提交内容(粘贴文本、拖入文件、输入 URL)
  • Wiki — 浏览编译产出的 wiki 文章,Markdown 渲染
  • Status — 实时监控编译进度

UI 内置中英文国际化和明暗主题切换。直连 Go 后端 REST API,无鉴权层(设计为本地/内网部署)。

Go 后端层

Go 后端是整个系统的编排中枢。使用标准库 net/http(而非 go-zero 的 rest.Server),以避免 SSE 流式传输与写超时的冲突。

核心组件:

  • REST API — 处理 /api/submit/api/tasks/api/wiki/api/chat,并在 / 提供内嵌 Web UI
  • Worker Pool — Dispatcher + Extract workers + Pipeline workers,并发编译加速
  • Circuit Breaker — LLM 连续失败后自动熔断(可配置阈值 + 冷却时间)
  • Lease Recovery — 基于心跳的租约续期;异常退出后自动恢复孤立任务
  • MCP 端点 — 将 /mcp 反向代理到 Python MCP server,供远程 agent 接入
  • SQLite Store — 持久化任务队列、编译状态和任务元数据

Python AI 引擎

Python AI 引擎(kb-ai)负责所有 LLM 交互:

  • 编译流水线 — Extract → Classify → Write → Index(4 阶段 Markdown 生成)
  • 检索 — LLM 迭代式:读 master-index → LLM 选页 → 读取完整文章(无嵌入向量)
  • 问答 — 流式对话,支持 prompt caching 和引用溯源
  • MCP Server — 通过 stdio 或 streamable-http 暴露 ask 工具

Go 后端将 Python 引擎作为常驻守护进程启动,通过多路复用的 stdin/stdout JSON 协议通信(见下文)。

Go-Python 通信

Go-Python 通信协议

KaaS 使用自定义的多路复用协议,基于守护进程的 stdin/stdout 管道。相比 HTTP 方案,避免了网络开销和冷启动延迟,同时支持并发请求。

协议格式

请求(Go → Python,通过 stdin,每行一个 JSON):

json
{"id": "3", "cmd": "chat", "payload": {"query": "...", "kb_dir": "./data"}}

响应(Python → Go,通过 stdout,每行一个 JSON):

json
{"id": "3", "ok": true, "data": {"extraction": {...}, "cost": {...}}}

流式响应(同一 id 的多行输出):

json
{"id": "3", "stream": true, "event": {"type": "delta", "text": "..."}}
{"id": "3", "stream": true, "event": {"type": "done"}, "final": true}

关键设计要素

要素说明
id 字段每个请求携带唯一 id。Go 端的 readLoop 根据 id 将响应分发到对应的等待 goroutine。
并发控制Go 使用信号量限制在途请求数。Python 将命令分发到 ThreadPoolExecutor 并发执行。
流式传输流式命令(chatpipeline-stream)发送多个 {"stream": true} 事件,直到 "final": true
取消机制Go 发送 {"cmd": "cancel", "payload": {"target_id": "3"}} 中止正在执行的流。Python 使用每请求的 cancel_registry 通知线程。
就绪信号Python 初始化完成后向 stderr 输出 __READY__。Go 收到此信号后才开始发送命令。
线程安全Python 的 _write_response 写入 stdout 前获取锁,防止并发写入导致 JSON 行交错。

生命周期

  1. Go 通过 exec.Cmd 启动 kb-ai daemon 子进程
  2. Python 初始化完毕,向 stderr 输出 __READY__
  3. Go 发送 init 命令传递 LLM 凭证
  4. 正常运行:stdin/stdout 上的多路复用请求/响应
  5. 关闭时:Go 关闭 stdin → Python 的 readline 循环退出
  6. 崩溃时:Go supervisor 检测到进程退出,自动重启(最多 MaxRestarts 次)

存储

KaaS 默认使用 SQLite,实现零依赖部署:

  • 任务队列 — 任务元数据、状态、租约信息
  • 编译状态 — 内容哈希,支持增量编译

所有 wiki 产出以纯 Markdown 文件形式存储在 kb_dir 目录(默认 ./data):

data/
├── wiki/          # 编译产出的 wiki 文章(Markdown)
├── raw/           # 原始输入内容
├── index/         # master-index + topic-index
└── kaas.db        # SQLite 数据库

部署

KaaS 以单个 Docker 镜像交付,包含:

  • 预构建的 React UI(Go 作为静态文件服务)
  • 静态链接的 Go 二进制
  • Python 运行时 + kb-ai 包(通过 uv)
bash
docker run -d --name kaas \
  -p 8080:8080 \
  -v ./data:/app/data \
  -e LLM_API_KEY=sk-xxx \
  kaas

仅暴露端口 8080。Go 后端处理所有外部流量——REST API、内嵌 Web UI 和 MCP 端点。Python 守护进程在内部运行,无网络暴露面。