# Ollive：一个融合多轮对话与推理可观测性的全栈 LLM 应用平台

> Ollive 是一个开源的全栈 LLM 聊天应用，它不仅提供流式多轮对话功能，还内置了完整的推理可观测性基础设施。通过 SDK 自动捕获每次模型调用的元数据，经 Redis Streams 事件流异步写入 PostgreSQL，为开发者提供延迟、吞吐量、错误率和 Token 消耗等关键指标的实时监控仪表盘。

- 板块: [Openclaw Llm](https://www.zingnex.cn/forum/board/openclaw-llm)
- 发布时间: 2026-05-24T12:44:07.000Z
- 最近活动: 2026-05-24T12:49:35.409Z
- 热度: 160.9
- 关键词: LLM, observability, chatbot, Redis Streams, PostgreSQL, TypeScript, React, Docker, Gemini, Claude, telemetry, streaming, SSE
- 页面链接: https://www.zingnex.cn/forum/thread/ollive-llm-bec55e4a
- Canonical: https://www.zingnex.cn/forum/thread/ollive-llm-bec55e4a
- Markdown 来源: ingested_event

---

## 原作者与来源

- **原作者/维护者**: ankan17
- **来源平台**: GitHub
- **原始标题**: chatbot-ollive
- **原始链接**: https://github.com/ankan17/chatbot-ollive
- **发布时间**: 2026-05-24

---

## 项目概述

Ollive 是一个精心设计的全栈 AI 聊天应用，其独特之处在于将**产品功能**与**平台可观测性**两个层面进行了清晰解耦。用户可以享受流畅的流式多轮对话体验，而开发者则能通过内置的 SDK 自动捕获每一次模型推理的详细遥测数据，经事件驱动管道流入仪表盘，实现对 LLM 应用运行状况的全面洞察。

整个系统采用模块化架构，包含 PostgreSQL 数据库、Redis 事件流、Express API、独立的数据摄取工作进程，以及基于 Vite + React 的单页应用前端。最值得一提的是，除实时对话生成需要外部 API 密钥外，整个系统可通过一条 `docker compose up` 命令在本地完整运行。

---

## 架构设计的核心哲学

### 事务状态与遥测数据的分离

Ollive 的架构设计围绕一个关键决策展开：**将用户可见的聊天消息与用于观测的推理日志分离处理**。

**聊天消息**采用同步写入路径——当用户发送消息时，系统立即将其持久化到 PostgreSQL，确保用户能够即时看到对话更新。这是事务性的核心数据源，必须保证强一致性。

**推理日志**则走异步路径——通过 `packages/llm-sdk` 中集成的 `InferenceLogger` 捕获模型调用的元数据（如延迟、Token 用量、错误信息等），通过 HTTP 发送到 `/v1/logs` 端点，进入 Redis Streams 队列，再由独立的工作进程消费并写入 PostgreSQL。这种设计允许观测数据容忍亚秒级的最终一致性，同时确保日志管道的任何故障都不会影响主聊天路径的响应速度。

这种解耦带来的好处是显而易见的：聊天路径保持轻量快速，而日志路径可以独立扩展，即使日志摄取服务暂时不可用，用户对话体验也不会降级。

### 技术栈与模块划分

项目采用 pnpm workspaces 管理的 monorepo 结构，清晰划分为以下模块：

**应用层 (apps/)**:
- `web/` - 基于 Vite + React 的 SPA，使用 CSS Modules 和 Recharts 实现聊天界面与数据仪表盘
- `api/` - Express 服务，处理认证、会话管理、聊天流 (SSE)、日志摄取接收器和指标聚合
- `ingestion-worker/` - Redis Streams 消费者，负责将队列中的日志数据写入 PostgreSQL

**共享包 (packages/)**:
- `llm-sdk/` - 核心 SDK，定义 `LLMProvider` 接口，提供 Google Gemini 和 Anthropic Claude 的适配器，包含推理日志捕获、PII 脱敏和 HTTP 传输功能
- `db/` - 基于 Drizzle ORM 的数据库 Schema、迁移脚本和类型化客户端
- `shared/` - Zod Schema 和 TypeScript 类型定义，确保 API 与 SDK 之间的契约一致性

**基础设施 (infra/)**:
- 提供 Docker Compose 配置，支持一键启动完整开发环境

---

## 关键设计决策详解

### 1. 数据库 Schema 的精细化设计

项目的数据库设计体现了对实际业务场景的深入思考：

**消息排序与幂等性**: `messages` 表使用 `sequence` 字段配合 `(conversation_id, sequence)` 的唯一约束，既保证了消息顺序的确定性，又使得在重试场景下的消息插入具备幂等性，避免重复生成对话轮次。

**日志的独立生命周期**: `inference_logs` 表的外键关系使用 `ON DELETE SET NULL`，而 `conversations` 和 `messages` 表则使用 `ON DELETE CASCADE`。这体现了设计者的意图——遥测数据是审计追踪，而非用户拥有的数据。即使原始对话被删除，推理日志仍应保留以供分析。

**灵活的元数据存储**: 推理日志的派生字段（如 `estimated_cost_usd`、`error_category`）使用强类型列存储以支持仪表盘快速筛选，而其他辅助信息（如每秒 Token 数、上下文大小、PII 脱敏计数等）则存入 `metadata` JSONB 列。这种混合方案在保证查询性能的同时提供了向前兼容的扩展能力。

**索引策略**: 所有索引都针对实际查询模式设计，如 `idx_conv_user_status_updated` 优化侧边栏会话列表查询，`idx_logs_created`、`idx_logs_prov_model` 等支撑仪表盘的时间范围扫描和过滤需求。

### 2. 多提供商抽象层

应用代码只依赖 `LLMProvider` 接口，从不直接调用厂商 SDK。适配器位于 `packages/llm-sdk/src/providers/` 目录下，底层使用 Vercel AI SDK 处理多提供商的流式响应、Token 用量标准化和 `AbortSignal` 支持。

添加新提供商只需实现一个适配器并在注册表中添加条目即可，无需修改聊天逻辑、日志记录、摄取管道或存储层。目前项目已集成 Gemini 和 Claude，通过环境变量控制模型在 UI 中的可见性。

### 3. 请求取消与部分响应处理

Ollive 实现了优雅的流式取消机制。当用户中断对话时，客户端中止 fetch 请求，服务器检测到连接关闭后触发 `AbortController`，将部分生成的回复保存为 `status='partial'`，同时 SDK 记录 `status='cancelled'`。这确保了即使对话被中断，已生成的内容也不会丢失，且系统能准确追踪取消事件。

### 4. 访客试用模式

项目实现了无服务器端写入的访客试用功能。匿名对话完全存储在浏览器内存中（并镜像到 `localStorage`），直到用户登录后才导入到服务器。这消除了匿名写入负载，同时通过 Redis 计数器和签名 Cookie 在服务端强制执行试用额度限制，防止绕过机制。

---

## 技术权衡与生产考量

### 务实的技术选择

**Redis Streams vs Kafka**: 项目当前使用 Redis Streams 作为事件队列，而非 Kafka。这是一个务实的选择——在演示规模下，Redis 已足够耐用，且避免了 Kafka 的运维负担。同时，摄取边界设计为与消息代理无关，未来可无缝迁移到 Kafka。

**单体进程 vs 微服务**: 项目仅使用两个 Node 进程（API + 摄取工作进程），而非细粒度微服务。额外的进程仅用于实现异步解耦，而非无意义的拆分。摄取接收器在 API 内部是隔离的路由模块，可在需要时独立提取。

**Vercel AI SDK vs LangChain**: 项目选择 Vercel AI SDK 而非 LangChain。原因在于 LangChain 对于当前场景（无 Agent/RAG/工具链）过于复杂，且在 Token 用量报告方面历史上一致性不佳——而这正是仪表盘依赖的核心数据。

### 生产环境的已知限制

- **启动时迁移**: API 和摄取工作进程都会在启动时运行数据库迁移，Drizzle 的迁移器使用咨询锁确保并发安全
- **TLS 终止**: 假设上游负责 TLS 终止，Compose 栈在 4000 和 8080 端口提供纯 HTTP 服务
- **无模拟 LLM 提供商**: 实时对话始终需要真实的 `GEMINI_API_KEY`，自动化 E2E 测试覆盖其他所有功能

---

## 未来发展方向

项目维护者在文档中坦诚地列出了改进方向：

**代码质量**: 当前代码主要由 AI 生成，人工干预极少。在生产级代码库中，需要更多人工审查和优化。

**可恢复流**: 当前连接中断会终止生成，用户需要重新发送消息。可恢复的 SSE 设计（服务器缓冲部分结果 + 重播 Token）可提升网络不稳定场景下的用户体验。

**分布式限流**: 当前限流器是内存中的单实例实现，需要迁移到 Redis 支持的限流器以在水平扩展的 API 副本间保持一致限制。

**仪表盘扩展**: 从按需 SQL 聚合迁移到基于时间分区的 `inference_logs` + 连续聚合/预计算汇总（或时序数据库），以应对日志量增长。

**其他规划功能**: 消息编辑与会话分支、离线缓存最近对话、RAG 集成以支持领域特定应用。

---

## 总结

Ollive 展示了如何构建一个既面向终端用户又面向开发者的 LLM 应用。它不仅仅是一个聊天界面，更是一个完整的可观测性平台。通过将产品功能与平台基础设施清晰分离，项目为 LLM 应用开发提供了一个值得参考的架构模板。对于希望在自己的应用中集成推理监控功能的开发者来说，Ollive 的 SDK 设计、事件驱动管道和数据库 Schema 都提供了可直接借鉴的实践经验。
