Onyx
企业搜索 / RAG / AI Chat / Agent 平台,Python 3.13 + FastAPI + Celery + PostgreSQL + React 19 + Next.js;与 BodySense 技术栈重合度最高的完整 Python AI 产品。本篇记录其模块边界、测试结构与阅读重点。
[!info] related notes
- 所属 MOC:源码阅读 MOC
- 同栈并列:PydanticAI(Python AI 写法样板)· Dify(Python+Go+React 全家桶)· Langflow(React+Python 图形化)
- BodySense 对照目录:
apps/ai-service/(FastAPI + PostgreSQL/pgvector + Redis + LangGraph + OpenAI + uv)- 工程说明:仓库自带
AGENTS.md
Onyx
这是什么
企业搜索、RAG、AI Chat、Agent 平台(约 30k stars,有正式版本发布)。它和 BodySense 的重合度最高:同样是 Python 后端 + React 前端,同样围绕 LLM / RAG / 检索 / 回答生成组织代码。
核心技术栈(实测自仓库 pyproject.toml / web/package.json):
Python 3.13
FastAPI
SQLAlchemy + Alembic
Celery
PostgreSQL
Redis
LangChain + LiteLLM
React 19 + Next.js(web/)
[!warning] 它是大型商业化产品 代码并非每处都像教材一样漂亮,且含 CE/EE 双版本(
backend/ee/)。不要从根目录顺序阅读,不要复制全部目录结构,不要照搬 Celery/搜索/权限体系。
在你三层参考架构里的位置
用户定位:学习「完整 Python AI 产品怎样工程化」的首选。和 BodySense 可直接逐模块对照——FastAPI 应用与 Celery worker 的分离、RAG 链路、provider 集中管理、分层测试体系。
版本快照
| 项 | 值 |
|---|---|
| 分支 | main |
| commit | f7b9d64a32f5(2026-08-11) |
| 抓取日期 | 2026-08-11 |
| 语言 | Python >=3.13(根 pyproject.toml:requires-python = ">=3.13") |
| 前端 | React 19 + Next.js(web/) |
| 包管理 | uv(后端 uv.lock)/ bun(前端 bun.lock) |
仓库鸟瞰:顶层目录结构
onyx/
├── backend/ # Python 后端(核心)
│ ├── onyx/ # 真正的应用代码
│ ├── ee/ # 企业版(双版本)
│ ├── alembic/ # 数据库迁移
│ ├── model_server/ # 模型服务
│ ├── tests/ # 分层测试
│ └── uv.lock
├── web/ # React 19 + Next.js 前端
├── cli/ # Go 写的 CLI(go.mod 存在)
├── mobile/ # React Native 移动端
├── desktop/ # Tauri 桌面端
├── widget/ # 嵌入组件
├── deployment/ # docker_compose / helm / terraform
├── docs/ loadtest/ extensions/ tools/ examples/
backend/onyx/(核心应用,depth 1,节选关键领域):
backend/onyx/
├── main.py # 应用入口
├── chat/ # chat 处理主循环(llm_loop / process_message / compression)
├── llm/ # 模型 provider 抽象(factory / multi_llm / interfaces)
├── document_index/ # 索引抽象(vespa / opensearch 适配)
├── connectors/ # 数据源连接器(github / slack / gmail / notion … 几十种)
├── indexing/ # 入库流水线(chunker / embedder / vector_db_insertion)
├── db/ # SQLAlchemy 模型与 DAL
├── server/ # FastAPI 路由(query_and_chat / documents / kg / auth …)
├── tools/ # 工具实现与 runner
├── background/ # Celery 任务(indexing / periodic_poller)
├── redis/ # Redis 协调(connector / doc perm sync)
├── file_processing/ # 文件抽取
├── file_store/ # 文件存储(s3 / gcs / azure / postgres)
├── evals/ # 评估
├── tracing/ # 可观测(langfuse / braintrust)
└── utils/ configs/ prompts/ skills/ voice/ deep_research/ …
顶层边界职责
| 顶层目录 | 回答什么问题 | 备注 |
|---|---|---|
backend/onyx/chat/ | 一次对话怎么被处理 | llm_loop.py 是主循环 |
backend/onyx/llm/ | 模型 provider 怎么集中管理 | factory.py + multi_llm.py |
backend/onyx/indexing/ + document_index/ | 文档怎么入库、索引、检索 | RAG 完整链路 |
backend/onyx/connectors/ | 外部数据源怎么接 | 几十种,是噪音重灾区 |
backend/onyx/server/ | API 路由怎么组织 | FastAPI 按域分路由器 |
backend/onyx/background/ | 异步任务怎么跑 | Celery worker |
web/ | React AI Chat 怎么协作 | Next.js App Router |
分层与依赖方向
flowchart TB
WEB[web/ React] --> API[server/ FastAPI]
API --> CHAT[chat/ 主循环]
CHAT --> LLM[llm/ provider 抽象]
CHAT --> TOOLS[tools/]
CHAT --> IDX[document_index/ + indexing/]
IDX --> DB[(PostgreSQL)]
IDX --> VEC[(Vespa/OpenSearch)]
BG[background/ Celery] --> IDX
BG --> REDIS[(Redis 协调)]
关键入口与调用链
| 入口 | 路径 | 说明 |
|---|---|---|
| 应用入口 | backend/onyx/main.py | FastAPI app 装配 |
| Chat 主循环 | backend/onyx/chat/llm_loop.py | 一次对话的 LLM 步进 |
| 入库流水线 | backend/onyx/indexing/indexing_pipeline.py | 文档 → chunk → embed → 入库 |
| 模型工厂 | backend/onyx/llm/factory.py | provider 集中管理 |
| 路由 | backend/onyx/server/query_and_chat/ | 对话/检索 API |
| 迁移 | backend/onyx/alembic/ | 数据库演进 |
阅读路线(用户建议:只看五部分)
chat/(对话主循环与 LLM 步进)llm/(provider 抽象与集中管理)document_index/+indexing/(RAG 链路)server/(FastAPI 路由组织)tests/(分层测试体系)
深挖一条线:一次 chat 请求穿过 RAG 链路
选「用户问一个问题,带检索增强的回答」作为主线——它同时暴露 FastAPI 路由、chat 主循环、provider 抽象、RAG 检索四块,且和 BodySense 的咨询流直接对应。
web/ React(Next.js)发问
→ backend/onyx/server/query_and_chat/ FastAPI 路由(对话/检索 API)
→ backend/onyx/chat/llm_loop.py process_message / llm_loop(一次对话主循环)
→ backend/onyx/llm/factory.py provider 工厂(集中管理 OpenAI/Anthropic/...)
→ backend/onyx/tools/ tool runner
→ backend/onyx/document_index/ + indexing/ 检索增强(Vespa/OpenSearch)
→ PostgreSQL + 向量库
→ 结构化/流式响应回前端
[异步] backend/onyx/background/(Celery) indexing_pipeline.py 入库(chunk→embed→入库)
跟读要点:
chat/llm_loop.py是「一次对话怎么被处理」的核心,断在循环体看 LLM 步进与工具调用如何交替llm/factory.py看 provider 如何被集中管理(对照 BodySenseai/providers/的分散)document_index/与indexing/是 RAG 链路两端:一个管检索、一个管入库;background/的 Celery 负责离线入库- 测试分类是额外看点:
backend/tests/下unit / external_dependency_unit / integration / regression / evals
自检:一次 chat 里,LLM 调用发生在哪、检索发生在哪、两者如何在 llm_loop 汇合?BodySense 的咨询流能否照这个切分对齐?
值得偷师 / 不建议照抄
| 做法 | 评价 | 我的判断 |
|---|---|---|
| FastAPI 应用与 Celery worker 分离 | 强 | BodySense 可直接对照 |
| API / LLM / RAG / connector / index 清晰模块边界 | 强 | 与 BodySense 逐模块对应 |
provider 集中管理(llm/factory.py) | 强 | 避免散落各处 |
测试明确分 unit / external_dependency_unit / integration / regression / evals / Playwright E2E | 强 | BodySense 缺这套分类 |
| 真实集成测试优先 | 强 | 验证”真实 PG/Redis”而非纯逻辑 |
| CE/EE 双版本、几十种 connector | 中/弱 | 噪音大,不要照搬 |
| 整个仓库规模 | 弱 | 不要复制目录结构 |
我的疑问与待验证
backend/tests/的external_dependency_unit/与integration/如何区分”真实 PG/Redis”与”mock”?BodySense 想建同类分类时可直接参考其 conftest 划分。ee/(企业版)与 CE 的耦合方式是否值得 BodySense 当前阶段借鉴?(大概率不值得,先记下)
沉淀出的笔记
相关链接 / 官方入口
| 入口 | 地址 |
|---|---|
| 仓库 | https://github.com/onyx-dot-app/onyx |
| 工程说明 | https://raw.githubusercontent.com/onyx-dot-app/onyx/main/AGENTS.md |
| 测试结构 | https://github.com/onyx-dot-app/onyx/tree/main/backend/tests |