分析时间:2026年7月
仓库:onyx-dot-app/onyx(⭐ ~31K+,190+ 贡献者,MIT License CE)
参考来源:DeepWiki、官方文档、源码分析
技术栈:Python (FastAPI) + TypeScript (Next.js) + PostgreSQL + Vespa + Redis + MinIO + Celery
一、整体架构概览
Onyx 是一个开源企业级 AI 知识管理与对话平台,核心定位为 LLM 的应用层,提供从数据摄入到 AI 对话的完整闭环。
核心服务组成
| 服务 |
技术 |
职责 |
| Web Frontend |
Next.js(standalone build) |
Chat UI、Admin Dashboard、Connector 管理、Agent 编辑器 |
| Backend API |
FastAPI |
REST API、WebSocket/SSE 流式、LLM 编排、鉴权 |
| Background Workers |
Celery(6 类 Worker Pool) |
文档抓取、解析、嵌入、索引同步、权限同步、定时调度 |
| Task Scheduler |
Celery Beat + DynamicTenantScheduler |
多租户定时任务调度 |
| Document Index |
Vespa 8 / OpenSearch 3.4 |
混合检索(Dense Vector + BM25)、ACL 过滤 |
| Metadata Store |
PostgreSQL 15 |
连接器配置、凭证、文档元数据、用户/租户管理 |
| Coordination |
Redis |
分布式锁(OnyxRedisLocks)、Fence 模式、任务状态管理 |
| Object Storage |
MinIO(S3 兼容) |
原始文件持久化 |
架构特点
┌─────────────────────────────────────────────────────────────┐
│ Next.js Web UI │
│ (Chat / Admin / Agent Editor / Projects) │
└──────────────────────┬──────────────────────────────────────┘
│ REST / SSE / WebSocket
┌──────────────────────▼──────────────────────────────────────┐
│ FastAPI Backend │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Auth │ │ Chat/LLM │ │ Search │ │ Connector │ │
│ │(OIDC/ │ │ Loop │ │ Pipeline │ │ CRUD API │ │
│ │ SAML/ │ │ │ │ │ │ │ │
│ │ OAuth) │ │ │ │ │ │ │ │
│ └─────────┘ └──────────┘ └──────────┘ └─────────────┘ │
└──────────┬───────────┬───────────┬───────────┬──────────────┘
│ │ │ │
┌─────▼────┐ ┌────▼────┐ ┌───▼───┐ ┌────▼─────┐
│PostgreSQL│ │ Vespa │ │ Redis │ │ MinIO │
│ (元数据) │ │(索引+ │ │(协调) │ │(文件存储)│
│ │ │ 检索) │ │ │ │ │
└──────────┘ └─────────┘ └───┬───┘ └──────────┘
│
┌─────────────▼──────────────┐
│ Celery Workers │
│ (6 类专用 Worker Pool) │
│ DocFetching / DocProcessing │
│ Primary / Light / Heavy │
│ UserFileProcessing │
└─────────────────────────────┘
二、Connector 架构(数据源连接器)
2.1 三层抽象体系
Onyx 的 Connector 框架基于三个核心实体和四种摄入模式构建:
核心实体:
| 实体 |
说明 |
源码 |
| Connector |
数据源类型定义 + 配置参数(如哪些仓库要索引) |
backend/onyx/db/models.py |
| Credential |
认证信息(API Key / OAuth Token / SAML) |
web/src/lib/connectors/credentials.ts |
| CCPair (ConnectorCredentialPair) |
Connector + Credential 的绑定,构成一个独立的索引单元 |
backend/onyx/db/models.py:94 |
四种摄入模式:
| InputType |
对应接口 |
说明 |
适用场景 |
load_state |
LoadConnector |
全量加载 + 状态管理,connector 自行追踪增量状态 |
Web 爬虫、Airtable、File Upload |
poll |
PollConnector / CheckpointedConnector |
定时轮询,框架传入 start/end 时间窗口进行增量拉取 |
Slack、GitHub、Confluence、Google Drive 等大部分 SaaS |
event |
EventConnector |
事件驱动,外部系统推送变更通知 |
Webhook 触发场景 |
slim_retrieval |
SlimConnector / SlimConnectorWithPermSync |
轻量检索,仅获取文档 ID 列表(用于权限同步/剪枝) |
权限同步、增量剪枝 |
2.2 工厂模式与注册机制
# backend/onyx/connectors/factory.py — 核心工厂函数
identify_connector_class(source, input_type)
→ _load_connector_class() # 懒加载模块,缓存到 _connector_cache
→ _validate_connector_supports_input_type() # 校验接口实现
instantiate_connector(...) # 主入口
→ identify_connector_class()
→ connector.load_credentials() # 初始化 API 客户端(如 MSAL for Teams)
→ connector.validate_connector_settings() # 校验 API 可达性
→ 绑定回调: raw_file_callback(文件持久化)、indexing_heartbeat(心跳)
ValidSources 枚举(web/src/lib/types.ts)定义了所有支持的数据源,作为单一真相来源。前端和后端共享同一枚举,涵盖 60+ 数据源:
| 类别 |
代表 Connector |
| Wiki/文档 |
Confluence、Notion、BookStack、Outline、Coda、Slab、Guru、Google Sites |
| 云存储 |
Google Drive、Dropbox、S3、R2、Google Cloud Storage、Egnyte、OCI Storage |
| 代码 |
GitHub、GitLab、Bitbucket |
| 消息 |
Slack、Teams、Gmail、Discord、Zulip |
| 工单/项目 |
Jira、Zendesk、Linear、Asana、ClickUp、Freshdesk、TestRail |
| 数据 |
Airtable、Salesforce、HubSpot |
| 通用 |
Web Crawler、File Upload、Ingestion API |
2.3 新建 Connector 的开发模式
以 TeamsConnector 为例的标准模板:
class TeamsConnector(PollConnector, SlimConnector):
"""每个 Connector 实现 1-3 个接口"""
def __init__(self, teams: list[str] = [], ...):
# 配置参数由前端表单传入
self.teams = teams
def load_credentials(self, credentials: dict) -> None:
# 初始化 API 客户端(如 MSAL Token)
self.client = MSALClient(credentials["client_id"], ...)
def validate_connector_settings(self) -> None:
# 校验 API 可达性
self.client.test_connection()
def poll_source(self, start: SecondsSinceUnixEpoch, end: ...) -> GenerateDocumentsOutput:
# 增量拉取:框架传入时间窗口
for message in self.client.get_messages(after=start, before=end):
yield Document(
id=message.id,
sections=[Section(text=message.body, link=message.url)],
source=DocumentSource.TEAMS,
metadata={"channel": message.channel},
)
def retrieve_all_slim_documents(self) -> GenerateSlimDocumentOutput:
# 权限同步时仅返回 ID 列表
for doc_id in self.client.list_all_doc_ids():
yield SlimDocument(id=doc_id, perm_sync_data={...})
前端配置系统:ConnectionConfiguration(web/src/lib/connectors/connectors.tsx)支持动态表单生成,字段类型包括 text、select、checkbox、tab,如 GitHub 用 tab 切换"特定仓库"与"全部仓库"。
2.4 权限同步机制
三种访问控制模式:
| 模式 |
说明 |
| Public |
组织内所有人可见 |
| Private |
限定用户/用户组 |
| Sync |
从源系统同步权限(SlimConnectorWithPermSync),每个文档的 ACL 写入 Vespa,查询时强制过滤 |
Indexed vs Federated:
- Indexed:文档被抓取、嵌入、存入 Vespa,支持全功能语义搜索
- Federated:实时从源 API 查询(如 Slack),延迟更高,搜索质量较低
三、触发机制(定时 / 事件 / 手动)
3.1 Celery Beat 定时调度
Onyx 基于 Celery Beat + 自定义 DynamicTenantScheduler 实现多租户定时任务调度。
beat_task_templates(backend/onyx/background/celery/tasks/beat_schedule.py)定义了所有周期性任务:
| 任务 |
默认周期 |
Worker Pool |
说明 |
check_for_indexing |
15 秒 |
primary |
检查是否有 CCPair 需要索引 |
check_for_vespa_sync |
5 秒 |
primary |
检查 PG ↔ Vespa 元数据同步 |
check_for_pruning |
1 小时 |
heavy |
删除源系统中已不存在的文档 |
check_for_connector_deletion |
20 秒 |
primary |
处理 CCPair 删除清理 |
check_for_doc_permissions_sync |
30 秒 |
heavy |
权限同步 |
monitor_* |
各异 |
primary |
监控任务健康(僵尸任务清理、Fence 回收) |
DynamicTenantScheduler(backend/onyx/background/celery/apps/beat.py):
- 继承 Celery PersistentScheduler
- 周期性重新加载任务调度表
- 多租户环境下为每个 tenant 动态生成任务实例
CLOUD_BEAT_MULTIPLIER_DEFAULT = 8.0 用于云环境缩放任务频率
3.2 事件驱动触发
EventConnector 接口:支持外部系统通过 Webhook 推送变更事件
- Ingestion API:
POST /api/ingestion 允许外部程序直接推送文档到索引流水线
- MCP Server:Onyx 可作为 MCP Server 暴露搜索能力,也可连接外部 MCP Server 作为 Tool
3.3 手动触发
- Admin Dashboard:一键触发"Re-index"重新索引特定 CCPair
- REST API:
POST /api/manage/admin/connector/run-once 手动触发单次索引
3.4 增量状态管理
IndexAttemptSnapshot {
new_docs_indexed: number // 本次新增文档数
total_docs_indexed: number // 累计文档数
error_msg: string | null // 错误信息
status: "not_started" | "in_progress" | "success" | "failed" | "canceled"
time_started: string
}
- PollConnector:框架传入
(start, end) 时间窗口,connector 只拉取该区间变更
- CheckpointedConnector:更先进的增量方式,connector 自行管理 checkpoint 状态(支持断点续传)
- LoadConnector:connector 自行管理 load_state,框架不干预
四、Pipeline(文档处理流水线)
4.1 全链路数据流
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Celery │ │ Connector│ │ 文档解析 │ │ Chunking │ │ Embedding│
│ Beat │───▶│ 拉取文档 │───▶│ + 清洗 │───▶│ 分块 │───▶│ 向量化 │
│ (调度) │ │ (DocFetch│ │ (DocProc │ │ │ │ │
│ │ │ Worker) │ │ Worker) │ │ │ │ │
└─────────┘ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘
│
┌─────▼─────┐
│ Vespa │
│ 写入 + │
│ ACL 同步 │
└───────────┘
4.2 六阶段处理流水线
| 阶段 |
Worker Pool |
核心处理 |
| ① 调度触发 |
Beat (primary) |
check_for_indexing 检查所有 CCPair 是否到达轮询间隔 |
| ② 文档抓取 |
docfetching |
instantiate_connector() → poll_source() / load_from_state() 生成 Document 对象 |
| ③ 文档解析 |
docprocessing |
多格式解析(PDF/DOCX/PPTX/HTML/Markdown)、OCR(图片/表格)、格式归一化 |
| ④ 分块 |
docprocessing |
基于 Section 边界的 Chunking,生成带 chunk_id 的子文档 |
| ⑤ 向量嵌入 |
docprocessing |
调用嵌入模型(OpenAI / Cohere / 本地模型)生成 dense vector |
| ⑥ 索引写入 |
light (Vespa sync) |
写入 Vespa(向量 + BM25 + 元数据 + ACL),PG 更新文档状态 |
4.3 Celery Worker Pool 分工
| Worker Pool |
队列 |
职责 |
设计目标 |
celery_worker_primary |
celery |
监控 + 调度检查 + 僵尸任务清理 |
轻量快速,不阻塞 |
celery_worker_light |
vespa_metadata_sync / connector_deletion / doc_permissions_upsert |
Vespa 元数据同步、权限单条写入、connector 删除 |
高频短任务 |
celery_worker_heavy |
connector_pruning / connector_doc_permissions_sync |
文档剪枝、批量权限同步 |
低频长任务 |
celery_worker_docfetching |
connector_doc_fetching |
从外部源抓取文档 |
I/O 密集 |
celery_worker_docprocessing |
docprocessing |
解析、分块、嵌入 |
CPU/GPU 密集 |
celery_worker_user_file_processing |
user_file_processing |
用户上传文件处理 |
隔离用户负载 |
4.4 分布式协调:Fence 模式
Onyx 使用自研的 Fence 模式 管理分布式任务生命周期:
# Redis Fence 模式
DOCUMENT_SYNC_FENCE_KEY # 文档同步 fence
ACTIVE_FENCES # 全局 fence 集合(OnyxRedisConstants)
# 流程:
# 1. 任务启动前设置 fence key
# 2. 生成 taskset(多个子任务)
# 3. 子任务完成后 decrement fence counter
# 4. counter 归零 → fence 释放
# 5. Beat 监控 → 清理过期 fence
Redis 锁注册表(OnyxRedisLocks):
CHECK_VESPA_SYNC_BEAT_LOCK — Vespa 同步互斥
CELERY_INDEXING_LOCK — 索引任务互斥
CELERY_PRUNING_LOCK — 剪枝任务互斥
CHECK_CONNECTOR_DELETION_BEAT_LOCK — 删除任务互斥
4.5 Pipeline 的局限性
Onyx 的 Pipeline 不可自定义(L1 级):
- 解析→分块→嵌入→写入的流程是固定的
- 无法插入自定义处理步骤(如自定义 NER、自定义摘要生成)
- Chunking 策略不可配置(固定基于 Section 边界)
- 嵌入模型可切换,但嵌入逻辑不可修改
五、存储架构
5.1 多层存储体系
| 存储层 |
引擎 |
存储内容 |
特点 |
| 元数据层 |
PostgreSQL 15 |
Connector/Credential/CCPair 配置、用户/租户/权限、文档状态、索引记录 |
Alembic 管理 schema migration |
| 索引检索层 |
Vespa 8 |
文档向量 + BM25 倒排 + 元数据 + ACL |
原生混合检索,支持 YQL |
| 索引检索层(备选) |
OpenSearch 3.4 |
同上 |
标准化 pipeline 归一化分数 |
| 文件存储层 |
MinIO (S3 兼容) |
原始文件(PDF/DOCX/图片等) |
Postgres fallback 可选 |
| 协调层 |
Redis |
分布式锁、Fence 状态、任务队列 |
Celery broker + 自研协调 |
5.2 数据模型
ConnectorCredentialPair (CCPair)
├── connector_id → Connector(数据源类型 + 配置)
├── credential_id → Credential(认证信息,加密存储)
├── last_successful_index_time
├── indexing_status: "not_started" | "in_progress" | "success" | "failed"
├── access_type: "public" | "private" | "sync"
└── documents → [Document]
├── document_id (全局唯一)
├── semantic_identifier (人可读标题)
├── source_type (来源系统)
├── sections → [Section]
│ ├── text (原始文本)
│ └── link (来源链接)
├── metadata (自定义 KV)
└── doc_updated_at (源系统时间戳)
5.3 多租户数据隔离
- Schema 级隔离:每个 tenant 独立 PostgreSQL schema(
MULTI_TENANT 模式)
- Alembic migration:每个 schema 独立执行迁移脚本
- TenantAwareTask:Celery Task 基类,自动设置
CURRENT_TENANT_ID_CONTEXTVAR
- TenantRedisClient:Redis 客户端自动添加 tenant 前缀,实现键空间隔离
- Vespa:文档级 ACL 字段,查询时通过 YQL 强制过滤
5.4 数据持久化与迁移
| 方面 |
实现 |
| Schema 迁移 |
Alembic(PG schema 级别) |
| 数据导出 |
pg_dump + Vespa snapshot + MinIO bucket 分别导出 |
| 数据卷 |
Docker Compose 持久化卷 / K8s PVC |
| 索引重建 |
删除 Vespa 索引 → 重新触发全量索引 |
六、开放扩展能力
6.1 Agent / Persona 扩展
Onyx 通过 Persona(AI Assistant)系统提供高度可配置的 Agent:
| 配置维度 |
说明 |
| System Prompt |
自定义系统提示词(角色定义、行为约束) |
| Knowledge Scoping |
限定可搜索的 Document Sets / Hierarchy Nodes / 特定文档 |
| Tool Selection |
选择可用工具(Search / Web Search / Code Execution / MCP / Custom) |
| LLM Model |
选择特定 LLM 模型(支持 OpenAI / Anthropic / Azure / 本地模型) |
| Visibility |
public / private / user-specific |
6.2 Tool 扩展机制
| Tool 类型 |
说明 |
| SearchTool |
内置内部文档搜索(Vespa) |
| WebSearchTool |
内置 Web 搜索 |
| PythonTool (Craft) |
内置 Code Execution(沙箱环境) |
| Custom OpenAPI Tool |
用户通过 OpenAPI spec 定义自定义工具 |
| MCP Server Tool |
连接外部 MCP Server,自动发现并注册工具 |
| ImageGenerationTool |
内置图片生成 |
6.3 Connector 扩展
新增数据源只需:
- 在
ValidSources 枚举中添加新值
- 实现
PollConnector / LoadConnector 接口(Python 类)
- 在
connectorConfigs 中添加前端表单配置
- 在
SOURCE_METADATA_MAP 中添加 UI 元数据(图标、分类、文档链接)
6.4 不可扩展的部分
- 索引 Pipeline:解析→分块→嵌入→Vespa 写入的流程不可插拔自定义步骤
- Chunking 策略:不可自定义分块大小或分块算法
- 存储后端:Vespa / OpenSearch 二选一,不可替换为其他向量数据库
- 检索排序:RRF 融合权重可配但排序逻辑不可自定义
七、检索能力
7.1 混合检索架构
Onyx 支持 Dense Vector + BM25 原生混合检索,由 Vespa 引擎直接支持:
用户查询
│
▼
┌─────────────────┐
│ Query 扩展 │ LLM 生成多个查询变体:
│ (Multi-Query) │ - semantic_query_rephrase(语义重写)
│ │ - keyword_query_expansion(关键词扩展)
└────────┬────────┘
│ N 个加权查询
┌────▼────┐
│ Vespa │ 每个查询执行:
│ Hybrid │ - Dense Vector(embedding 余弦相似度)
│ Search │ - BM25(倒排索引关键词匹配)
│ │ - ACL Filter(权限过滤)
│ │ - DocumentSet Filter(知识域过滤)
└────┬────┘
│ 多路结果
┌────▼────────────┐
│ Weighted RRF │ 加权倒数排序融合
│ (reciprocal │ deduplicate_queries 去重 + 权重求和
│ rank fusion) │
└────┬────────────┘
│
┌────▼────────────┐
│ Chunk Merge │ merge_individual_chunks
│ (相邻块合并) │ → InferenceSection 对象
└────┬────────────┘
│
┌────▼────────────┐
│ LLM Selection │ select_chunks_for_relevance
│ (相关性过滤) │ LLM 判断最相关的 sections
└────┬────────────┘
│
┌────▼────────────┐
│ Context Expand │ expand_section_with_context
│ (上下文扩展) │ 拉取周围 chunk 补全上下文
└────┬────────────┘
│
┌────▼────────────┐
│ Prompt Build │ JSON → LLM / Rich Object → UI
└─────────────────┘
7.2 Vespa 查询细节
- YQL(Vespa Query Language)支持复杂过滤:ACL、Document Set、时间范围、Source 类型
- Normalization Pipeline:OpenSearch 备选方案使用归一化 pipeline 统一不同查询类型的分数
- InferenceChunk:检索结果的核心对象,包含
document_id、source_type、match_highlights、content、chunk_id
- InferenceSection:一个或多个相邻 InferenceChunk 合并后的结果
7.3 SearchTool 五阶段 Pipeline
SearchTool(backend/onyx/tools/tool_implementations/search/search_tool.py)是 Onyx 检索的核心实现:
| 阶段 |
处理 |
关键函数/常量 |
| Multi-Query |
LLM 生成多个查询变体(语义重写 + 关键词扩展) |
semantic_query_rephrase, keyword_query_expansion |
| Parallel Search |
对每个查询并行执行 Vespa 混合检索 |
Vespa YQL / OpenSearch DSL |
| RRF Fusion |
加权倒数排序融合 + 去重 |
weighted_reciprocal_rank_fusion, deduplicate_queries |
| LLM Selection |
LLM 判断最相关的文档块 |
select_chunks_for_relevance |
| Context Expansion |
拉取选中块的上下文邻居 |
expand_section_with_context |
八、上下文注入与对话系统
8.1 Chat 处理流程
POST /chat/send-chat-message
│
▼
handle_send_chat_message()
│
├── check_token_rate_limits() // 速率限制
├── verify LLM cost limits // 成本控制
│
▼
stream_chat_message()
│
├── construct_message_history() // 构建对话历史
│ └── compress_chat_history() // Token 溢出时压缩
│
▼
run_llm_loop() // 多轮 LLM 循环
│
├── 决定 tool_choice: AUTO / REQUIRED / NONE
├── 调用 LLM → 判断是否需要 tool call
│ ├── SearchTool → 内部文档搜索
│ ├── WebSearchTool → Web 搜索
│ ├── PythonTool → 代码执行(沙箱)
│ ├── Custom/MCP Tool → 自定义工具
│ └── _try_fallback_tool_extraction() // XML/JSON fallback
├── Tool 结果 → 注入上下文 → 再次调用 LLM
└── 循环直到 LLM 生成最终回答
│
▼
DynamicCitationProcessor // 引用追踪
│
└── 监听 LLM 流式输出 → 提取引用标记 → 映射到 SearchDoc → 生成 CitationInfo
8.2 两条上下文注入路径
| 路径 |
条件 |
实现 |
| In-Context Loading |
附件文件尺寸在 LLM 上下文窗口内 |
build_file_context() 直接注入 prompt |
| Tool-Mediated Retrieval |
大文件或通用查询 |
SearchTool 语义搜索 → 合并相邻 chunk → 注入 prompt |
8.3 对话历史压缩
- Token 预算:上下文窗口的 75% 作为触发阈值
- 压缩策略:
compress_chat_history() 保留 system_prompt + 最新消息,截断/摘要中间历史
additional_context:支持临时附加上下文(不进入持久化历史)
8.4 Deep Research 模式
用户复杂问题
│
▼
Clarification Stage(可选)
│ LLM 通过 clarification_tool 向用户确认细节
▼
Orchestrator Agent(ORCHESTRATOR_PROMPT)
│ 分解问题为多个子任务
│
├── Research Agent 1 ──► SearchTool + WebSearchTool + OpenURLTool
│ └── generate_intermediate_report()
├── Research Agent 2 ──► ...
│ └── generate_intermediate_report()
└── Research Agent N ──► ...
└── generate_intermediate_report()
│
▼
generate_final_report()
│ 合并所有中间报告 → 生成带引用的长文档
▼
最终回答(Long-form cited document)
8.5 知识域限定
Persona 可通过以下方式限定知识范围:
| 方式 |
说明 |
| Document Sets |
绑定特定 Connector 的文档集合 |
| Hierarchy Nodes |
指定特定文件夹/空间/频道 |
| Individual Documents |
固定特定文档 ID |
| User Files |
用户上传文件(通过 FileReaderTool 处理) |
| Project Files |
项目级别共享文件(project_id_filter) |
九、鉴权与多租户
9.1 认证方式
| 方式 |
说明 |
| basic |
用户名/密码 |
| google_oauth |
Google OAuth 2.0 |
| oidc |
OpenID Connect(通用 SSO) |
| saml |
SAML 2.0(企业 SSO) |
9.2 企业级多租户
MULTI_TENANT 模式:每个 tenant 独立 PG schema
DynamicTenantScheduler:为每个 tenant 动态生成 Beat 任务
TenantAwareTask:Celery 任务自动绑定 tenant 上下文
- 文档级 ACL:每个文档在 Vespa 中存储
access_control_list 字段
十、部署架构
10.1 部署方式
| 方式 |
说明 |
| Docker Compose |
标准部署,docker-compose.yml 包含所有服务 |
| Kubernetes (Helm) |
生产级部署,支持 HPA、PVC、Ingress |
| Cloud Providers |
AWS / GCP / Azure 一键部署模板 |
10.2 服务依赖
# Docker Compose 服务列表
services:
api_server: # FastAPI 后端
web_server: # Next.js 前端
background: # Celery Worker(多 pool)
celery_beat: # 定时调度器
postgres: # 元数据存储
vespa: # 文档索引 + 检索
redis: # 任务队列 + 分布式协调
minio: # 文件存储(可选 Postgres fallback)
model_server: # 嵌入模型服务(可选)
十一、Admin Dashboard(管理后台)
Onyx Admin 是 完全开源 的(MIT License CE),与 Chat UI 共属同一个 Next.js 工程,源码位于 web/src/app/admin/ 目录。
11.1 功能模块总览
| 模块 |
路由 |
核心功能 |
| Connector 管理 |
/admin/connectors/[connector] |
新增/编辑/删除数据源连接器,动态表单配置 |
| 索引状态 |
/admin/indexing/status |
所有 CCPair 的索引进度、文档数、错误监控 |
| CCPair 详情 |
/admin/connector/[ccPairId] |
单个连接器的详细管理:手动触发 Re-index、调整频率、查看错误 |
| Agent/Persona 编辑 |
/admin/agents (AgentEditorPage) |
创建/编辑 AI 助手:Prompt、知识域、工具选择、LLM 模型 |
| Document Sets |
/admin/documents/sets |
创建/管理文档集合(绑定 CCPair 的知识域) |
| LLM 配置 |
/admin/models |
配置 LLM Provider(OpenAI/Anthropic/Azure/本地模型) |
| Embedding 配置 |
/admin/embeddings |
配置嵌入模型 |
| 用户管理 |
/admin/users |
用户列表、角色分配、邀请 |
| Chat 偏好 |
/admin/chat-preferences (ChatPreferencesPage) |
全局对话偏好设置 |
| Tool 管理 |
/admin/tools |
Custom OpenAPI Tool + MCP Server 管理 |
| 性能/使用统计 |
/admin/performance |
查询量、响应时间、Token 消耗等指标 |
11.2 Connector 管理 — 动态表单生成系统
Admin 中最核心的设计是 声明式配置驱动的动态表单,新增一个 Connector 无需写任何前端代码。
三层配置体系:
┌────────────────────────────┐
│ SOURCE_METADATA_MAP │ UI 元数据层
│ (图标、分类、文档链接、 │ web/src/lib/sources.ts
│ 是否支持 OAuth/Federated) │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ connectorConfigs │ 表单配置层
│ (ConnectionConfiguration) │ web/src/lib/connectors/connectors.tsx
│ 字段类型: text/select/ │
│ checkbox/tab/list │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ credentialTemplates │ 凭证模板层
│ (API Key / OAuth Token / │ web/src/lib/connectors/credentials.ts
│ Service Account JSON) │
└────────────────────────────┘
ConnectionConfiguration Schema(web/src/lib/connectors/connectors.tsx:114-143):
interface ConnectionConfiguration {
description: string; // 连接器描述
subtext?: string; // 辅助说明
values: ConnectionConfigurationValue[]; // 表单字段列表
advanced_values?: ConnectionConfigurationValue[]; // 高级选项
overrideDefaultFreq?: number; // 覆盖默认轮询频率
}
// 字段类型
interface ConnectionConfigurationValue {
type: "text" | "select" | "checkbox" | "tab" | "list" | "file" | "zip";
query: string; // 字段标签
label: string; // 表单 name
optional?: boolean;
description?: string;
default?: any;
options?: SelectOption[]; // select 类型的选项
tabs?: TabOption[]; // tab 类型的切换页
}
GitHub Connector 配置示例:
connectorConfigs["github"] = {
description: "Configure GitHub connector",
values: [], // 基础字段为空
advanced_values: [
{
type: "tab",
query: "Choose indexing scope",
label: "indexing_scope",
tabs: [
{ label: "Specific Repository", fields: [
{ type: "text", query: "Repository Owner", label: "repo_owner" },
{ type: "text", query: "Repository Name", label: "repo_name" },
]},
{ label: "Everything", fields: [] }, // 索引所有仓库
]
}
]
};
11.3 索引状态监控
Indexing Status Dashboard(web/src/app/admin/indexing/status/):
| 组件 |
功能 |
CCPairIndexingStatusTable |
所有 CCPair 的汇总表格 |
SummaryRow |
单行摘要:Connector 名称、状态、文档数 |
ConnectorRow |
可点击跳转到详情页 |
CCPairStatus |
状态标签(Running / Success / Failed / Paused) |
每行展示的信息:
- 状态:当前索引状态(颜色编码)
- Last Success Time:上次成功索引时间
- Access Type:Public / Private / Sync(继承源系统权限)
- Document Count:已索引文档总数
- Error Count:错误数量(可点击查看详情)
CCPair 详情页(/admin/connector/[ccPairId]):
| 操作 |
说明 |
| Trigger Re-index |
手动触发重新索引 |
| Edit Frequency |
调整 refresh_freq(轮询频率)和 prune_freq(剪枝频率),Yup 校验 |
| View Errors |
IndexAttemptErrorsModal 弹窗展示具体错误信息 |
| Delete |
删除 CCPair(触发后台 check_for_connector_deletion_task 清理) |
11.4 Agent/Persona 编辑器
AgentEditorPage(web/src/refresh-pages/AgentEditorPage.tsx):
| 配置项 |
说明 |
| Name & Description |
Agent 名称和描述 |
| System Prompt |
自定义系统提示词 |
| LLM Model |
选择特定模型或使用默认 |
| Tools |
勾选可用工具:SEARCH_TOOL_ID(内部搜索)、WEB_SEARCH_TOOL_ID(Web 搜索)、PYTHON_TOOL_ID(代码执行/Craft)、Custom OpenAPI、MCP Server |
| Knowledge Sources |
Document Sets(文档集)、Hierarchy Nodes(特定目录/频道)、Individual Documents(固定文档) |
| Visibility |
Public / Private / 指定用户组 |
11.5 RBAC 角色体系
UserRole 枚举(backend/onyx/auth/schemas.py:11):
| 角色 |
权限范围 |
| ADMIN |
全权管理:Connector/Agent/用户/LLM 配置/系统设置 |
| GLOBAL_CURATOR |
跨组管理:管理所有 Document Sets 和 Connector |
| CURATOR |
组内管理:管理所属 User Group 的 Document Sets |
| BASIC |
普通用户:使用 Chat/Search,管理个人 Agent |
| LIMITED |
受限用户:仅基础对话 |
| SLACK_USER |
Slack 集成用户 |
| EXT_PERM_USER |
外部权限同步用户(源系统 ACL) |
权限检查机制:
backend/onyx/server/auth_check.py 定义了公开端点白名单(PUBLIC_ENDPOINT_SPECS)
- Admin API 路由通过
current_admin_user 依赖注入强制校验 ADMIN 角色
- Curator API 通过
validate_ccpair_for_user() 校验用户对特定 CCPair 的操作权限
IsPublicGroupSelector(web/src/components/IsPublicGroupSelector.tsx)组件处理 Connector 的 Public/Private/User Group 分配
11.6 CE vs EE 功能对比
| 功能 |
CE(MIT 开源) |
EE(商业许可) |
| Connector CRUD |
✅ |
✅ |
| 索引状态监控 |
✅ |
✅ |
| Agent/Persona 编辑 |
✅ |
✅ |
| Document Sets 管理 |
✅ |
✅ |
| LLM/Embedding 配置 |
✅ |
✅ |
| 基础用户管理 |
✅ |
✅ |
| Custom Tool/MCP 管理 |
✅ |
✅ |
| SAML/SSO |
❌ |
✅ |
| User Groups 精细权限 |
❌ |
✅ |
| 审计日志 |
❌ |
✅ |
| 高级分析 |
❌ |
✅ |
| 多租户管理 |
❌ |
✅ |
| 白标/定制品牌 |
❌ |
✅ |
EE 代码位于 backend/ee/ 和 web/src/ee/ 路径下,虽代码可见但受商业许可约束。
11.7 Admin API 架构
Admin 后台由 FastAPI 路由模块提供 API 支持:
| Router |
路径前缀 |
职责 |
connector_router |
/api/manage/connector |
Connector CRUD |
cc_pair_router |
/api/manage/admin/cc-pair |
CCPair 管理 |
persona_router |
/api/admin/persona |
Agent/Persona CRUD |
document_set_router |
/api/manage/admin/document-set |
Document Set 管理 |
llm_router |
/api/admin/llm |
LLM Provider 配置 |
user_router |
/api/manage/users |
用户管理 |
tool_router |
/api/admin/tool |
工具管理 |
关键实现细节:
- 所有 Admin 路由挂载在
APP_API_PREFIX 下(backend/onyx/main.py:75-135)
- 认证通过
fastapi_users 库实现,支持 Session + Bearer Token(移动端)
- 前端使用 SWR 进行数据获取和缓存,保持 Dashboard 状态实时更新
- Admin 组件库使用内部 Opal Library(
web/lib/opal)
十二、总结:优势与局限
优势
| 维度 |
评价 |
| Connector 广度 |
60+ 内置 Connector,开源项目第一 |
| 企业就绪 |
多租户、RBAC/SSO/SAML、文档级 ACL、审计日志 |
| 混合检索 |
Vespa 原生 Dense Vector + BM25,无需外部向量库 |
| 完整平台 |
Chat UI + Agent + Search + Admin + Projects + Deep Research |
| Connector 开发体验 |
标准化接口(4 种 InputType)+ 工厂模式 + 前端配置自动生成 |
| 触发机制 |
Celery Beat 定时 + Event Webhook + API 手动 + 多租户动态调度 |
| 运维成熟 |
Docker Compose / K8s Helm / Alembic migration / 健康检查 |
局限
| 维度 |
评价 |
| Pipeline 不可编程 |
解析→分块→嵌入→写入流程固定,不可插入自定义步骤(L1 级) |
| 存储不可插拔 |
只支持 Vespa / OpenSearch,不可替换为 Qdrant / Milvus / PGVector 等 |
| 无长期记忆演化 |
无 Agent 记忆层(不跨 session 学习/进化) |
| 多服务依赖 |
必须部署 PG + Vespa + Redis + MinIO(最少 4 个外部服务) |
| 非中间件定位 |
是完整应用平台而非可嵌入的 SDK/库 |
对我们的借鉴价值
| 借鉴方向 |
具体参考 |
| Connector 三层抽象 |
LoadConnector / PollConnector / EventConnector + 工厂模式 + ValidSources 枚举 |
| 增量同步机制 |
CheckpointedConnector 断点续传 + SlimConnector 轻量权限同步 |
| 触发调度 |
DynamicTenantScheduler 多租户定时 + Fence 模式分布式协调 |
| 混合检索 Pipeline |
Multi-Query → RRF Fusion → LLM Selection → Context Expansion |
| 权限同步 |
SlimConnectorWithPermSync 从源系统同步 ACL → 文档级过滤 |
| 前端配置自动化 |
ConnectionConfiguration schema → 动态表单生成 |
| Admin 管理后台 |
声明式三层配置体系(元数据 + 表单 + 凭证)、RBAC 7 级角色、CCPair 索引状态监控 |
📎 核心源码路径索引
| 模块 |
路径 |
| Connector 接口 |
backend/onyx/connectors/interfaces.py |
| Connector 工厂 |
backend/onyx/connectors/factory.py |
| Beat 调度表 |
backend/onyx/background/celery/tasks/beat_schedule.py |
| 动态调度器 |
backend/onyx/background/celery/apps/beat.py |
| SearchTool |
backend/onyx/tools/tool_implementations/search/search_tool.py |
| Chat LLM Loop |
backend/onyx/chat/llm_loop.py |
| Deep Research |
backend/onyx/deep_research/dr_loop.py |
| 引用处理 |
backend/onyx/chat/citation_processor.py |
| Redis 协调 |
backend/onyx/configs/constants.py (OnyxRedisLocks) |
| 数据模型 |
backend/onyx/db/models.py |
| 前端 Source 定义 |
web/src/lib/sources.ts |
| 前端 Connector 配置 |
web/src/lib/connectors/connectors.tsx |
| Vespa 查询 |
backend/onyx/context/search/pipeline.py |
| 对话压缩 |
backend/onyx/chat/compression.py |
| Admin Connector 页 |
web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx |
| CCPair 状态表 |
web/src/app/admin/indexing/status/CCPairIndexingStatusTable.tsx |
| CCPair 详情页 |
web/src/app/admin/connector/[ccPairId]/page.tsx |
| Agent 编辑器 |
web/src/refresh-pages/AgentEditorPage.tsx |
| 权限检查 |
backend/onyx/server/auth_check.py |
| 角色定义 |
backend/onyx/auth/schemas.py |
| Credential 模板 |
web/src/lib/connectors/credentials.ts |
一、整体架构概览
Onyx 是一个开源企业级 AI 知识管理与对话平台,核心定位为 LLM 的应用层,提供从数据摄入到 AI 对话的完整闭环。
核心服务组成
架构特点
二、Connector 架构(数据源连接器)
2.1 三层抽象体系
Onyx 的 Connector 框架基于三个核心实体和四种摄入模式构建:
核心实体:
backend/onyx/db/models.pyweb/src/lib/connectors/credentials.tsbackend/onyx/db/models.py:94四种摄入模式:
load_stateLoadConnectorpollPollConnector/CheckpointedConnectorstart/end时间窗口进行增量拉取eventEventConnectorslim_retrievalSlimConnector/SlimConnectorWithPermSync2.2 工厂模式与注册机制
ValidSources枚举(web/src/lib/types.ts)定义了所有支持的数据源,作为单一真相来源。前端和后端共享同一枚举,涵盖 60+ 数据源:2.3 新建 Connector 的开发模式
以
TeamsConnector为例的标准模板:前端配置系统:
ConnectionConfiguration(web/src/lib/connectors/connectors.tsx)支持动态表单生成,字段类型包括text、select、checkbox、tab,如 GitHub 用tab切换"特定仓库"与"全部仓库"。2.4 权限同步机制
三种访问控制模式:
SlimConnectorWithPermSync),每个文档的 ACL 写入 Vespa,查询时强制过滤Indexed vs Federated:
三、触发机制(定时 / 事件 / 手动)
3.1 Celery Beat 定时调度
Onyx 基于 Celery Beat + 自定义
DynamicTenantScheduler实现多租户定时任务调度。beat_task_templates(backend/onyx/background/celery/tasks/beat_schedule.py)定义了所有周期性任务:check_for_indexingcheck_for_vespa_synccheck_for_pruningcheck_for_connector_deletioncheck_for_doc_permissions_syncmonitor_*DynamicTenantScheduler(backend/onyx/background/celery/apps/beat.py):CLOUD_BEAT_MULTIPLIER_DEFAULT = 8.0用于云环境缩放任务频率3.2 事件驱动触发
EventConnector接口:支持外部系统通过 Webhook 推送变更事件POST /api/ingestion允许外部程序直接推送文档到索引流水线3.3 手动触发
POST /api/manage/admin/connector/run-once手动触发单次索引3.4 增量状态管理
(start, end)时间窗口,connector 只拉取该区间变更四、Pipeline(文档处理流水线)
4.1 全链路数据流
4.2 六阶段处理流水线
check_for_indexing检查所有 CCPair 是否到达轮询间隔docfetchinginstantiate_connector()→poll_source()/load_from_state()生成Document对象docprocessingdocprocessingdocprocessinglight(Vespa sync)4.3 Celery Worker Pool 分工
celery_worker_primarycelerycelery_worker_lightvespa_metadata_sync/connector_deletion/doc_permissions_upsertcelery_worker_heavyconnector_pruning/connector_doc_permissions_synccelery_worker_docfetchingconnector_doc_fetchingcelery_worker_docprocessingdocprocessingcelery_worker_user_file_processinguser_file_processing4.4 分布式协调:Fence 模式
Onyx 使用自研的 Fence 模式 管理分布式任务生命周期:
Redis 锁注册表(
OnyxRedisLocks):CHECK_VESPA_SYNC_BEAT_LOCK— Vespa 同步互斥CELERY_INDEXING_LOCK— 索引任务互斥CELERY_PRUNING_LOCK— 剪枝任务互斥CHECK_CONNECTOR_DELETION_BEAT_LOCK— 删除任务互斥4.5 Pipeline 的局限性
Onyx 的 Pipeline 不可自定义(L1 级):
五、存储架构
5.1 多层存储体系
5.2 数据模型
5.3 多租户数据隔离
MULTI_TENANT模式)CURRENT_TENANT_ID_CONTEXTVAR5.4 数据持久化与迁移
六、开放扩展能力
6.1 Agent / Persona 扩展
Onyx 通过 Persona(AI Assistant)系统提供高度可配置的 Agent:
6.2 Tool 扩展机制
6.3 Connector 扩展
新增数据源只需:
ValidSources枚举中添加新值PollConnector/LoadConnector接口(Python 类)connectorConfigs中添加前端表单配置SOURCE_METADATA_MAP中添加 UI 元数据(图标、分类、文档链接)6.4 不可扩展的部分
七、检索能力
7.1 混合检索架构
Onyx 支持 Dense Vector + BM25 原生混合检索,由 Vespa 引擎直接支持:
7.2 Vespa 查询细节
document_id、source_type、match_highlights、content、chunk_id7.3 SearchTool 五阶段 Pipeline
SearchTool(backend/onyx/tools/tool_implementations/search/search_tool.py)是 Onyx 检索的核心实现:semantic_query_rephrase,keyword_query_expansionweighted_reciprocal_rank_fusion,deduplicate_queriesselect_chunks_for_relevanceexpand_section_with_context八、上下文注入与对话系统
8.1 Chat 处理流程
8.2 两条上下文注入路径
build_file_context()直接注入 prompt8.3 对话历史压缩
compress_chat_history()保留 system_prompt + 最新消息,截断/摘要中间历史additional_context:支持临时附加上下文(不进入持久化历史)8.4 Deep Research 模式
8.5 知识域限定
Persona 可通过以下方式限定知识范围:
project_id_filter)九、鉴权与多租户
9.1 认证方式
9.2 企业级多租户
MULTI_TENANT模式:每个 tenant 独立 PG schemaDynamicTenantScheduler:为每个 tenant 动态生成 Beat 任务TenantAwareTask:Celery 任务自动绑定 tenant 上下文access_control_list字段十、部署架构
10.1 部署方式
docker-compose.yml包含所有服务10.2 服务依赖
十一、Admin Dashboard(管理后台)
Onyx Admin 是 完全开源 的(MIT License CE),与 Chat UI 共属同一个 Next.js 工程,源码位于
web/src/app/admin/目录。11.1 功能模块总览
/admin/connectors/[connector]/admin/indexing/status/admin/connector/[ccPairId]/admin/agents(AgentEditorPage)/admin/documents/sets/admin/models/admin/embeddings/admin/users/admin/chat-preferences(ChatPreferencesPage)/admin/tools/admin/performance11.2 Connector 管理 — 动态表单生成系统
Admin 中最核心的设计是 声明式配置驱动的动态表单,新增一个 Connector 无需写任何前端代码。
三层配置体系:
ConnectionConfigurationSchema(web/src/lib/connectors/connectors.tsx:114-143):GitHub Connector 配置示例:
11.3 索引状态监控
Indexing Status Dashboard(
web/src/app/admin/indexing/status/):CCPairIndexingStatusTableSummaryRowConnectorRowCCPairStatus每行展示的信息:
CCPair 详情页(
/admin/connector/[ccPairId]):refresh_freq(轮询频率)和prune_freq(剪枝频率),Yup 校验IndexAttemptErrorsModal弹窗展示具体错误信息check_for_connector_deletion_task清理)11.4 Agent/Persona 编辑器
AgentEditorPage(
web/src/refresh-pages/AgentEditorPage.tsx):SEARCH_TOOL_ID(内部搜索)、WEB_SEARCH_TOOL_ID(Web 搜索)、PYTHON_TOOL_ID(代码执行/Craft)、Custom OpenAPI、MCP Server11.5 RBAC 角色体系
UserRole枚举(backend/onyx/auth/schemas.py:11):权限检查机制:
backend/onyx/server/auth_check.py定义了公开端点白名单(PUBLIC_ENDPOINT_SPECS)current_admin_user依赖注入强制校验 ADMIN 角色validate_ccpair_for_user()校验用户对特定 CCPair 的操作权限IsPublicGroupSelector(web/src/components/IsPublicGroupSelector.tsx)组件处理 Connector 的 Public/Private/User Group 分配11.6 CE vs EE 功能对比
EE 代码位于
backend/ee/和web/src/ee/路径下,虽代码可见但受商业许可约束。11.7 Admin API 架构
Admin 后台由 FastAPI 路由模块提供 API 支持:
connector_router/api/manage/connectorcc_pair_router/api/manage/admin/cc-pairpersona_router/api/admin/personadocument_set_router/api/manage/admin/document-setllm_router/api/admin/llmuser_router/api/manage/userstool_router/api/admin/tool关键实现细节:
APP_API_PREFIX下(backend/onyx/main.py:75-135)fastapi_users库实现,支持 Session + Bearer Token(移动端)web/lib/opal)十二、总结:优势与局限
优势
局限
对我们的借鉴价值
LoadConnector/PollConnector/EventConnector+ 工厂模式 + ValidSources 枚举CheckpointedConnector断点续传 +SlimConnector轻量权限同步DynamicTenantScheduler多租户定时 + Fence 模式分布式协调SlimConnectorWithPermSync从源系统同步 ACL → 文档级过滤ConnectionConfigurationschema → 动态表单生成📎 核心源码路径索引
backend/onyx/connectors/interfaces.pybackend/onyx/connectors/factory.pybackend/onyx/background/celery/tasks/beat_schedule.pybackend/onyx/background/celery/apps/beat.pybackend/onyx/tools/tool_implementations/search/search_tool.pybackend/onyx/chat/llm_loop.pybackend/onyx/deep_research/dr_loop.pybackend/onyx/chat/citation_processor.pybackend/onyx/configs/constants.py(OnyxRedisLocks)backend/onyx/db/models.pyweb/src/lib/sources.tsweb/src/lib/connectors/connectors.tsxbackend/onyx/context/search/pipeline.pybackend/onyx/chat/compression.pyweb/src/app/admin/connectors/[connector]/AddConnectorPage.tsxweb/src/app/admin/indexing/status/CCPairIndexingStatusTable.tsxweb/src/app/admin/connector/[ccPairId]/page.tsxweb/src/refresh-pages/AgentEditorPage.tsxbackend/onyx/server/auth_check.pybackend/onyx/auth/schemas.pyweb/src/lib/connectors/credentials.ts