最近看到onyx-dot-app/onyx这个仓库频繁出现在技术社区的讨论里,星标涨得很快,文档也写得很完整。我自己因为一直在评估企业内部知识库方案,从它前身 Danswer 时期就开始关注,改名 Onyx 之后又完整部署了一遍。这篇文章不打算复述 README,而是把实际部署、数据源接入、检索调优的过程讲清楚,包括那些文档里不会明说的坑。如果你正在考虑给团队搭一个私有化 AI 问答系统,这篇文章值得往下看。
1. Onyx 到底是什么:从 Danswer 改名说起
1.1 一个“改头换面”后爆发的开源项目
如果你关注开源 AI 应用,应该对 Danswer 这个名字有印象。它在 2024 年正式改名为 Onyx,仓库也迁移成了onyx-dot-app/onyx。改名的背后不只是换个名字,整个项目的定位也在从“企业搜索工具”往“企业生成式 AI 助手”转变。
Onyx 要做的事情非常清晰:把散落在企业内部各种工具里的知识统一索引起来,然后通过一个类似 ChatGPT 的聊天界面和搜索框,让员工用自然语言快速找到答案,并且每个答案后面都附上来源引用。
它和直接用 ChatGPT、Claude 这类通用对话产品最大的区别,不在模型本身,而在“知识来源”。通用对话工具对你的企业内部文档一无所知,而 Onyx 把连接器、索引、权限、引用这一整条链路串起来,让大模型在你自己的知识范围内回答问题。对很多公司来说,这恰恰是能不能把 AI 落地到内部知识管理的关键。
1.2 它要解决的真实痛点
企业内部知识通常是分散的:网盘里躺着政策文档,Wiki 里记着技术方案,Slack 或企业微信里散落着历史讨论,工单系统里沉淀了排查经验。员工遇到问题时往往要在三四个工具里来回搜索,还不一定能找到准确的版本。
我见过不少企业尝试用通用 AI 助手来解决这个问题,结果都不太理想,原因很简单:模型没有权限访问内部资料,回答全靠“猜”。Onyx 这类工具的价值不是把搜索框做得更好看,而是把搜索入口变成一个问答入口,并且让回答有据可查。
具体来说,它解决三个层面的问题:
- 信息查找成本:员工不用再记“资料放在哪个系统”,直接问就行。
- 新员工上手:很多团队事务性问题,比如“报销流程是什么”“测试环境怎么部署”,属于重复问答,新员工问不到人就成了阻塞。
- 知识沉淀利用:散落的历史文档和讨论可以被重新组织和检索,不再是一次性产物。
1.3 什么样的团队适合用它
从我自己的使用体验来看,Onyx 适合下面几类场景:
- 团队没有预算购买商业版企业搜索或知识库产品,需要一个开源替代方案。
- 数据不能出内网,或者对数据隐私有明确要求,需要自托管。
- 想快速验证 RAG(检索增强生成)在团队内部的效果,而不是花几个月从零搭一套。
- 对连接器数量有要求,比如要统一索引网盘、Wiki、工单、IM 等内容源。
反过来,如果你期望 AI 回答 100% 准确,或者希望系统能自动解决所有权限问题,那任何工具都做不到。这类系统在技术上再完善,也仍然需要人工校验和持续调优。对这类预期,需要先做好管理。
对技术人员来说,Onyx 还有一个价值:它相当于一个开箱即用的企业级 RAG 架构样例。项目结构清晰,你能从里面学到连接器、索引、权限、检索和生成是怎么组织在一起的,光看代码就能获得不少架构灵感。
2. 核心机制拆解:连接器、混合检索与权限三件套
2.1 连接器:让数据先“流”进来
Onyx 的体系里,连接器(Connector)是第一环。它负责把外部数据源的内容拉取进来,统一处理成可以被索引的格式。官方支持的连接器数量很多,覆盖了最常见的办公协作工具。我在实际部署中接触过的常见连接器包括:
| 类型 | 典型连接器 |
|---|---|
| 文档与网盘 | Google Drive、SharePoint、OneDrive、本地文件 |
| 团队协作 | Slack、Teams、Confluence、Notion |
| 研发工具 | GitHub、GitLab、Jira、Linear |
| 业务系统 | Salesforce、Zendesk、Gmail、Outlook |
连接器的核心工作流程是:授权 → 拉取 → 解析 → 切片 → 向量化 → 写入索引。
整套流程里最容易出问题的集中在三个阶段:
授权阶段:很多服务商的 token 会过期,尤其是 Google Workspace 这种权限体系复杂的,过期之后连接器会静默失败,表现出来就是“同步任务一直成功,但文件不更新”。
解析阶段:同样是 PDF,扫描件和文本型 PDF 的处理难度完全不同。扫描件不经过 OCR,索引进去的内容就是一页页“白纸”,搜索永远召回不到。这个问题在真实知识库里极其常见,后文会详细展开。
切片阶段:切片(chunking)直接影响回答质量。切小了,每个片段的上下文不够,模型看不出在说什么;切大了,一个片段塞进太多无关内容,既增加 token 消耗,也会稀释检索精度。真实项目里没有一套参数能通吃所有文档,必须抽样检查。
2.2 混合检索:为什么不能只用向量搜索
Onyx 的检索链路不是单靠向量搜索,而是“关键字检索 + 向量语义检索”的混合方案。这是我在实际使用中最认可的设计之一。
简单对比一下两类检索方式:
| 检索方式 | 擅长 | 容易翻车的场景 |
|---|---|---|
| 向量语义检索 | 同义改写、语义相近的内容 | 精确型号、编号、人名、拼写 |
| 关键字检索 | 专有名词、精确 ID、术语 | 语义相关但字面完全不同的内容 |
只用向量搜索,你问“打印机的报错代码是什么”,如果文档里写的是“HP LaserJet 运行异常代码 49.4”,向量检索可能匹配不到;只用关键字搜索,你搜“年假怎么算”,文档里写的是“Annual Leave Policy”或者“休假制度”,也可能召回不全。
混合检索的思路是把两类结果融合排序,先召回一批候选,再做精排。整个过程可以理解为“先海选,再复试”。第一轮检索目的是召回率,宁可多召回一些候选;第二轮用更重的排序模型重新打分,取最相关的 top k 送给大模型生成回答。
在实际调优里,重排(reranking)对最终答案质量的影响非常大。如果省略重排这一步,哪怕第一轮召回结果里有正确答案,排序也可能把错误结果放在前面。加上重排之后,虽然会增加一点延迟,但回答的相关性会有明显提升,尤其是在文档量大的场景下,性价比很高。
2.3 文档级权限控制:自托管 AI 的关键信任点
企业知识库和公开互联网搜索一个很大的区别在于:不是所有内容对所有用户可见。Onyx 在索引文档时会同步写入访问控制信息,查询时根据当前用户身份过滤检索结果。简单说,文件权限不允许你看的内容,不仅不会被搜出来,也不会作为回答的上下文。
这套逻辑看起来简单,但落到真实场景里很复杂。同一个 Google Drive 文件夹里,不同子目录对不同人可见;Confluence 页面有空间级和页面级权限;Slack 私密频道的消息只能让频道成员看到。这些信息需要在索引时就准确提取并保存下来,否则权限控制就是一句空话。
在生产环境里,这一步牵涉到认证方式的选择。如果只是试用,用 basic auth 把所有员工都当成一个账号登录,那权限控制基本等于没有。只要文档里存在敏感信息,就一定要尽早接 OIDC/SSO,让每个用户的真实身份贯穿查询全过程。
我个人的建议是:在接入第一个正式数据源之前,先把权限方案规划好,用两个不同权限的测试账号验证一遍,再谈上线。这个环节省不掉,也别侥幸。
3. 自部署实录:用 Docker Compose 跑通 Onyx 的过程
3.1 部署前的资源评估
Onyx 支持多种部署方式,最常见的是 Docker Compose,适合试用和内部小范围使用;生产环境数据量大时,建议走 Kubernetes/Helm 或按官方文档拆分组件部署。
先说资源。官方文档给的建议偏保守,但根据我的实际体验,如果是试用,4 核 8GB 内存起步比较稳。要全量索引一个大团队的网盘或 Slack 历史消息,建议 8 核 16GB 以上。磁盘预留也是常见问题,纯文本类文档占不了多少空间,但如果涉及大量 PDF、图片解析,索引临时文件会膨胀得很快,建议至少预留 50GB 以上。
还有一点容易被忽略:服务器所在地和网络环境。Onyx 本身可以配置不同的大模型服务地址,无论是调用外部 API,还是内网自建的模型服务,都需要确保服务器能访问到对应地址。
3.2 配置模板与关键环境变量
克隆仓库之后,第一步是复制环境变量模板。仓库会自带一个.env模板,我习惯先复制一份再慢慢改。
git clone https://github.com/onyx-dot-app/onyx.git cd onyx cp .env.template .env vim .env.env里需要重点关注几类配置:
- 认证方式:试用阶段可以先用简单认证,进入生产前必须切换成 OIDC/SSO。
- 数据库/缓存密码:Postgres 和 Redis 的密码,首次启动后不要随意改,改密码时所有依赖它的容器都需要重启。
- 应用密钥:用于 session 加密,必须设置成一个足够随机的值,不要用默认值。
- 大模型配置:包括 chat 模型和 embedding 模型的 Provider、API Key、模型名称。
- 基础 URL 配置:如果你的部署域名不是默认值,需要提前设置,否则前端回调地址会不对。
填好之后,直接启动:
docker compose up -d第一次启动会拉取较多镜像,等所有容器变成 healthy 状态再访问界面。启动完成后,在浏览器里打开对应端口的地址,会进入初始化页面,创建第一个管理员账号,然后就可以在管理后台配置数据源了。
这里有一个细节我踩过坑:.env里有些配置项看起来是“可选”,但不填会在后面某个环节报错。比如模型列表配置,如果不显式写明要使用的模型名称,界面可能显示为空或者加载失败。所以部署时不要跳着看模板,所有带说明的项都确认一遍。
3.3 接入第一个数据源:验证一个完整闭环
新版本的管理后台基本是引导式操作,创建一个数据源连接器,然后授权或填 API Key,指定要同步的范围,保存后再触发索引任务。
以最常见的文档型数据源为例,整个闭环大概是:
- 创建连接器:选择类型,填写访问凭证。
- 指定范围:比如只索引某个文件夹、某个空间,而不是全公司所有文档。
- 触发首次索引:观察任务执行状态,等待索引任务跑完。
- 验证检索:在聊天界面提问,看是否能返回相关结果和引用。
- 验证权限:用一个普通账号提问同样的问题,确认无权访问的文档不会出现在结果里。
首次全量索引的耗时往往超过预期,这是正常的。很多连接器为了保证不遗漏,首次同步会把历史数据都拉一遍,跑到一半日志里看起来像卡住了,其实只是慢。判断标准是看任务队列里是否还有待处理的任务,而不是看日志是否一直在输出。
4. 接入 LLM、调优检索质量:我踩过的几个坑
4.1 LLM 与 embedding:把“读得懂”和“答得出”分开考虑
Onyx 的一个设计我很喜欢:chat 模型和 embedding 模型是分开配置的。这意味着你可以用能力强的商业模型做最终回答生成,而用开源 embedding 模型做本地向量化,两者并不冲突。
实际使用时,embedding 模型负责“读懂文本语义”,chat 模型负责“组织回答语言”。我见过不少人在部署时只关心 chat 模型,忽略 embedding 模型的选择。如果你的知识库里有大量中文内容,embedding 模型对中文的支持就至关重要。试想一下,文档里写的是“报销流程”,你问的是“怎么申请报销”,如果 embedding 模型不认识这两个表达之间的语义关系,检索阶段就直接跑偏了。
在选择 embedding 模型时,中文场景下可以优先考虑对中文支持比较好的开源模型,比如 bge 系列、m3 系列,具体按官方文档支持的情况来。这里的原则是:知识库以中文为主,就别只盯着英文场景的 embedding 模型。
还有一点,如果对数据隐私要求严格,embedding 阶段最好也走本地模型,避免把文档向量化后发送到外部服务。向量本身虽然看不出原文,但严格说它也是文档内容的加工产物,慎重点没坏处。
4.2 索引质量:文件解析和 chunk 切分的坑
这一节是我踩坑最多的地方,展开讲讲。
先说文件解析。真实企业知识库里最多的文件类型大概是 PDF、Word、PPT 和 Excel。PDF 里最坑的就是扫描件。没有 OCR 模块的默认配置下,扫描件索引进去的内容是一堆空白页,表面上索引任务显示成功,实际上一个字都搜不到。这个问题你在界面上看不到任何报错,只能通过“索引进度完成后,搜一个明确出现在文档里的词,结果为空”来判断。遇到这种情况,要么给文档源加 OCR 预处理,要么后期将扫描件统一替换成带文本层的 PDF。
再说表格类文件。Excel 和带复杂表格的 PDF,默认切片会按顺序切文本,表格结构很容易被拆散。比如一个“员工职级与薪资范围对照表”,切片后上下文丢失,模型根本看不出表格逻辑。我的处理办法是:这类高价值表格先转换成 PDF 或 Markdown 格式再导入,让表格结构尽量保留。
最后说 chunk 参数。Onyx 这类系统通常允许你配置分块大小和重叠大小,但别指望有一组万能参数。我自己的经验是:
- 文本规整的文档,分块可以略大,保留足够上下文。
- 代码、日志、结构化内容,分块要小,避免一个块里混入太多不同主题。
- 调参之后一定要抽样看切出来的片段,你很快会发现“预想中”的切片效果和真实结果差距很大。
一个比较隐蔽的问题是:切片之后,文档的上下文可能被截断,比如一个简写术语在某个切片里没有全称介绍。这类问题靠参数很难完全解决,更实际的办法是在文档侧做好规范,比如首次出现术语时写全称。
4.3 连接器和同步:token 过期与增量拉取
连接器接入数量多了以后,真正令人头疼的不是初次配置,而是日常同步。
Google Drive 的授权 token 会过期,过期之后连接器不一定报错,就是悄悄不更新文件。我在测试时发现某个文件夹新增了文档,但搜索一直查不到,排查了半天才发现是 token 失效了。解决办法只有定时检查连接器状态,或者写个脚本监控同步任务最近一次成功时间。
Slack 这类 IM 连接器,问题在于数据量。一个活跃团队的历史消息量可能是文档的几十倍,全量索引非常耗时。关键不在于索引速度快慢,而在于它对资源的占用会影响线上其他服务。建议只选择需要检索的频道,不要无脑全选,尤其是私密频道和归档频道,先想清楚是否真的需要进入知识库。
Confluence 页面结构复杂,页面嵌套、宏、附件都会影响切片质量。一个页面如果包含大量宏生成的动态内容,切出来的 chunk 可能非常碎片化。这种问题没有统一解法,只能先小范围接入,抽看切片质量,再逐步扩大索引范围。
4.4 资源与性能:给容器“瘦身”
自托管应用总会遇到资源瓶颈,Onyx 也不例外。内存占用最大的通常是索引服务、任务队列 worker,以及本地 embedding 模型。如果你发现系统越跑越卡,先执行docker stats看看谁在吃内存,不要盲目加配置。
我踩过的一个典型问题是:数据源同步任务并发太高,几个大规模连接器同时全量索引,直接把内存打满了。后面调整为“错峰同步”,重要的连接器增量同步每隔几小时跑一次,全量索引放在夜间,系统就稳定多了。
还有一个小技巧:不需要的连接器及时停掉或删除。我有一个测试用的连接器一直开着,它每天跑同步任务,白白占了一部分 worker 资源。清理之后整个系统的响应速度明显改善。
下面是我在实际使用中总结的常见问题排查表,遇到问题时可以先对照一遍:
| 症状 | 可能原因 | 处理方式 |
|---|---|---|
| 回答没有引用来源 | 检索阶段没召回相关文档 | 检查文件是否索引成功,调整切片或重排配置 |
| 搜索结果为空 | 连接器同步失败或权限过滤 | 查看连接器日志,重新授权,检查测试账号权限 |
| 答案质量差 | embedding 或 chat 模型配置不合适 | 换 embedding 模型,增加重排,优化切片参数 |
| 系统卡顿 | 内存不足或并发过高 | 减少连接器并发,错峰同步,扩大资源规格 |
5. 落地建议:从技术验证到企业内部上线
5.1 先跑垂直场景,再横向铺开
如果你准备在团队里正式推行 Onyx,我的建议很明确:先别想着把所有数据源一次性接进来,先选一个知识边界清晰、问答频次高的垂直场景跑通。
我推荐优先选择 IT 支持或 HR 政策这两个场景。原因很简单:这类问题重复性高,答案相对固定,而且文档基础通常比较好。比如“如何申请测试环境权限”“年假可以累计吗”,在文档里能找到明确答案,验证效果直观。
这个阶段不要接二十个连接器,先接两三个高质量数据源,把回答质量调到“能真正使用”的程度。评估指标不用复杂,就看两条:
- 回答是否总是附着有效引用来源。
- 员工遇到问题时,是先去工具里翻文档,还是先来问这个机器人。
如果第二个问题的答案是后者,说明它真的在发挥作用。
5.2 和 SSO/IM 打通后的体验形态
技术验证完成后,进入正式上线阶段,有两件事越早做越好。
第一件事是接 OIDC/SSO。前面反复提到权限控制,而这套权限体系的根基就是身份认证。没有真实的用户身份,文档级权限控制无从谈起。接好 SSO 之后,每个用户检索和提问时都会自动带上身份,系统才能正确过滤无权访问的内容。
第二件事是把问答能力接入团队日常使用的 IM 工具。Onyx 开放了 API,你可以把问答能力接到 Slack、Teams、企业微信或钉钉上。员工在聊天框里直接发问,机器人返回答案和引用链接,整个使用门槛会大大降低。很少有人愿意为了问一个问题专门打开一个后台界面,但在 IM 里顺手发条消息就是天然高频场景。
这里有个细节值得注意:IM 机器人返回答案时,尽量保留引用来源的链接展示。内部知识场景里,没有出处的回答很难赢得信任。哪怕答案是对的,员工也会怀疑;但只要有清晰的引用,说服成本立刻降下来。
5.3 长期维护清单
系统上线不是终点,而是运营的起点。根据我自己的体验,长期维护需要关注几件事:
- 连接器同步监控:隔一段时间检查各数据源的最近同步时间,及时发现 token 过期、限流等静默失败问题。
- 回答质量抽样:每月抽十个真实提问,看回答是否准确、引用是否支撑结论,把效果差的问题沉淀成需要补充的文档清单。
- 知识库更新节奏:重要文档更新后,手动触发一次索引,或调高该数据源的同步频率,避免新内容迟迟不可搜。
- 备份策略:用户配置、连接器状态、Postgres 里的元数据都需要定期备份,别只备份索引数据而忘了数据库。
最后再分享一点个人经验。我折腾这一圈下来,最大的感受是:这类私有化知识问答系统的难点,从来不在“把大模型接进来”,而在数据接入、权限设计和检索质量调优。越深入越发现,连接器生态和权限设计才是决定项目成败的关键。
如果你也是第一次搭,先不要贪多,把一个核心文档源打通,把权限验证跑通,再逐步扩大范围,这个节奏最稳妥。另外,一个小技巧:部署完成后,先用两个不同权限的测试账号完整走一遍“提问—看引用—查权限”的流程,能帮你避免上线后才发现敏感信息越权可见的尴尬局面。