第八节 — 系统内部的进程与服务划分
这一节回答:FinBayes 内部分几个进程 / 服务单元?哪些同进程?哪些独立部署?
第一阶段的整体取向:单进程优先
FinBayes 第一阶段采用 单进程实现 + 多入口共享同一 runtime 实例 的部署形态。具体而言:
- CLI / TUI / Web API Server / MCP Server / Channel Adapter 都是同一 runtime 进程的入口适配
- 多入口共享同一 Core Runtime 实例
- State Store(本地数据库)通过同进程库访问,非独立服务
- LLM Provider Adapter 是 runtime 内的客户端模块,通过 HTTP / stdio 调外部 Provider
理由(来自架构目标与质量取舍章节):
- 个人用户量级 + 本地优先部署,不需要为大规模并发优化
- 跨入口的认知质量一致性靠"共享同一 runtime 实例"硬保证
- 单进程内的接口契约 = 函数调用,迭代成本低
- 接口契约本身仍版本化,未来按需拆分进程不破坏现有调用方
容器图
这张图表达什么:FinBayes 内部分为 入口适配 / Core Runtime / Provider Adapter Pool / 本地持久化 四类容器。所有入口适配同进程,共享同一个 Core Runtime 实例。Provider Adapter Pool 通过 HTTP / stdio 调外部 LLM 与数据 Provider。持久化分四类:State Store(用户状态资产)、Cache(L3 缓存 + 语义缓存)、Config Store(用户 Provider 配置)、Credential Store(用户的 Provider API key 等本机配置秘密)。
这张图特意不表达什么:每个容器内部组件(留给"每个子系统的内部组件"章节)、具体数据流(留给关键场景的流转图章节)、未来从单进程演化到多进程的拓扑(留给部署形态章节)。
怎么读这张图:上半是外部世界,下半是 FinBayes Runtime Process。中间的箭头是跨容器调用。同一 box(如 entries 子图)内的容器都在同一进程中。Provider Adapter Pool 是同一进程内的客户端层,不是独立服务。
各容器的职责简述
| 容器 | 职责 | 第一阶段实现 |
|---|---|---|
| CLI Adapter | 命令式终端入口;单次提问 / Provider readiness 检查 / Session 管理命令 / Watchlist 操作 / 等 | Python click / typer 等 CLI 框架 |
| TUI Adapter | 终端持续问答入口;用户可切换 Session、确认状态候选、复盘判断等 | Rich / Textual 等 TUI 框架 |
| Web API Server | HTTP / WebSocket 服务,供 Web UI 调用;task request / event stream / state action 等 contract 接口 | FastAPI / Starlette |
| MCP Server | 标准 MCP(Model Context Protocol)服务,让外部 Agent 调用 FinBayes runtime | stdio 协议(MCP 标准) |
| Channel Adapter | Telegram / Discord / 等社群 channel 集成;摘要式输出 + 回链到 Web Session | webhook 接收 + Provider SDK |
| Core Runtime | 任务编排 / 路由 / 综合判断 / 状态管理 / 主动信号 等核心认知能力 | Python class + asyncio |
| Provider Adapter Pool | LLM / 数据 Provider 统一接入层;Provider Registry + Routing Policy + 能力匹配 + Fallback | 通过 LiteLLM 或自实现统一接口 |
| State Store | 用户状态资产持久化(Session / Watchlist / Judgment Record / 动态画像 / 审计 trail) | SQLite(本地优先) |
| Cache | L3 语义缓存 + 精确缓存 | Redis(如本机有)或进程内 LRU 内存 |
| Config Store | 用户的 Provider 配置(哪些 Provider 启用、任务-Provider 映射、fallback 顺序等) | YAML / JSON 配置文件 |
| Credential Store | 用户的 Provider API key 等本机配置秘密 | OS Keychain(macOS / Windows / Linux)优先,环境变量次之,加密本地文件兜底 |
容器间的通信方式
| 通信关系 | 协议 / 形态 |
|---|---|
| 入口适配 → Core Runtime | 同进程函数调用(Python class method / asyncio 协程) |
| Core Runtime → Provider Adapter Pool | 同进程函数调用 |
| Provider Adapter Pool → 外部 LLM | HTTP / streaming(按 Provider 协议;Ollama / vLLM 用 OpenAI-compatible API) |
| Provider Adapter Pool → 外部数据 Provider | HTTP / SDK 调用 |
| Core Runtime → State Store | 同进程库调用(SQLite Python binding) |
| Core Runtime → Cache | 同进程(Redis 通过本地 Redis 客户端 / 进程内 LRU) |
| Web API Server ↔ Web UI | HTTP(task request / state action)+ WebSocket(task event stream) |
| MCP Server ↔ 外部 Agent | stdio(标准 MCP 协议) |
| Channel Adapter ↔ Channel 平台 | webhook / polling(按 Channel 协议) |
部署形态对容器选择的影响
详见部署形态章节,这里点要点:
- 本地优先单机部署:所有容器同进程,State Store 用 SQLite,Cache 可选 Redis 或内存,所有 Provider 配置在用户本机
- 本地 + 远程 Provider:Core Runtime 与持久化都在本机,仅 Provider Adapter Pool 调用远程 LLM / 数据 API(用户配置)
- 未来托管部署(不在第一阶段):Web API Server 可分离为独立进程;State Store 可迁移到远程数据库;其他容器按需扩展
第一阶段的接口契约设计不锁死本地——未来按需拆分进程不破坏现有调用方。
与工程仓的代码位置映射
本章容器在 FinBayes 工程仓中的代码组织遵循 Python 标准 src layout:所有业务代码在 src/finbayes/ 下,按 6 子系统 + 入口适配 分子目录。各容器与代码模块的精确映射详见 CHAP-27 代码仓位置映射 —— 本章不重复,避免双源漂移。
入口适配子目录约定(src/finbayes/io/entries/):
| 入口容器 | 子目录 |
|---|---|
| CLI Adapter | cli/ |
| TUI Adapter | tui/ |
| Web API Server | web/ |
| MCP Server | mcp/ |
| Channel Adapter | channels/ |
详细映射(业务对象 / 状态机 / 工具 / 配置 / 测试 / 评估 全部 7 张表)见 CHAP-27。