跳到主要内容

检索增强生成 (RAG)

注意

如果您使用的是 Ollama,请注意它默认将上下文长度设为 2048 个 token。这极大地限制了 检索增强生成 (RAG) 的性能,尤其是在进行网页搜索时,因为检索到的数据可能根本无法被使用,或者只被部分处理。

检索增强生成 (RAG) 是一种通过融入来自不同数据源的上下文来增强聊天机器人对话能力的技术。它的工作原理是从广泛的来源(例如本地和远程文档、网页内容,甚至是 YouTube 视频等媒体源)中检索相关信息。接着,检索到的文本会与预定义的 RAG 模板结合,并作为前缀添加到用户的提示词中,从而提供信息更丰富、上下文更契合的回复。

RAG 的核心优势之一是它能够访问并整合来自多种渠道的信息,这使其成为应对复杂对话场景的理想解决方案。例如,当用户提出与特定文档或网页相关的问题时,RAG 可以从该源中检索并将相关信息融入聊天回复中。此外,RAG 还可以从 YouTube 视频等媒体源中提取并整合信息。通过分析这些视频的转录文本或字幕,RAG 可以提取出相关信息并将其写入聊天回复。

本地与远程 RAG 集成

本地文档必须先通过 Workspace(工作区)区域的 Documents(文档)部分进行上传,才能在查询前使用 # 符号来访问它们。点击输入框上方出现的格式化 URL。选中后,Send a message(发送消息)上方会出现一个文档图标,表示已成功检索。

批量文件管理

需要清理多个已上传的文档或审计您的存储空间?您现在可以使用位于 Settings > Data Controls > Manage Files 的集中式 File Manager(文件管理器)。在此处删除文件将自动清理其对应的 RAG 嵌入 (embeddings)。

您也可以在提示词开头输入 # 并紧跟 URL,从而将文档及其访问权限加载到工作区中。这有助于直接将网页内容融入到您的对话中。

针对 RAG 的网页搜索

注意

面向 Ollama 用户的上下文长度警告: 即使在进行内容提取后,网页通常也包含 4,000 至 8,000+ 个 token(包括主体内容、导航元素、页眉、页脚及元数据)。如果只有 2048 个 token 可用,您能获取的页面内容还不到一半,往往会遗漏最相关的信息。甚至 4096 个 token 在进行全面的网页内容分析时也经常显得捉襟见肘。

如何解决此问题: 导航至 Admin Panel > Models > Settings(您的 Ollama 模型设置)> Advanced Parameters将上下文长度 (context length) 增加到 8192+(甚至大于 16000)个 token。此设置仅适用于 Ollama 模型。对于 OpenAI 及其他集成模型,请确保您使用的是具有足够内置上下文长度的模型(例如,拥有 128k token 的 GPT-4 Turbo)。

对于网页内容的整合,在对话查询时以 # 开头,后跟目标 URL。点击输入框上方出现的框中的格式化 URL。选中后,Send a message 上方会出现一个文档图标,表明已成功检索。如果可行,Open WebUI 会抓取并解析来自该 URL 的信息。

提示

网页通常包含导航和页脚等无关信息。为了获得更好的效果,请尽量链接到页面的原始文本 (raw) 或阅读器友好型版本。

RAG 模板自定义

通过 Admin Panel > Settings > Documents 菜单来自定义 RAG 模板。

Markdown 标题切分

启用此功能后,文档将首先通过 Markdown 标题 (H1-H6) 进行切分。这可以保留文档结构,并确保同一标题下的章节尽可能保持在一起。然后,生成的块 (chunks) 将由标准的字符或 token 切分器进行进一步处理。

提示

使用 Chunk Min Size Target(最小分块目标大小)设置(位于 Admin Panel > Settings > Documents),在进行 Markdown 切分后智能地合并较小的章节,从而提高检索的连贯性并减少数据库中的向量总数。

分块配置

Open WebUI 允许您精细调整将文档切分为块以进行嵌入 (embedding) 的方式。这对于获得最佳检索性能至关重要。

  • Chunk Size(分块大小):设置每个分块的最大字符数(或 token 数)。
  • Chunk Overlap(分块重叠度):指定相邻分块之间共享多少内容以维持上下文。
  • Chunk Min Size Target(分块最小目标大小):虽然 Markdown 标题切分 非常有利于保留结构,但它往往会产生微小、碎片化的块(例如,独立的子标题、目录条目、单句段落或简短的列表项),这些块缺乏足够的语义上下文来进行高质量的嵌入。您可以通过设置 Chunk Min Size Target 来智能地将这些小碎片与其邻近的内容合并,从而解决这一问题。

为什么使用最小块大小目标?

在 Markdown 切分后智能地合并小章节具有几个关键优势:

  • 提高 RAG 质量:消除微小、无意义的碎片,确保每个检索到的块中具有更好的语义连贯性。
  • 减小向量数据库大小:分块变少意味着需要存储的向量也变少,从而降低了存储成本和内存使用量。
  • 加快检索与嵌入速度:较小的索引搜索速度更快,且较少的分块也意味着需要较少的嵌入 API 调用(或较少的本地计算)。这大大加快了在将文件上传到聊天或知识库时的文档处理速度,因为需要进行向量化的数据变少了。
  • 效率与效果:测试表明,配置合理的阈值(例如,对于 2000 的分块大小,设置 1000 的最小目标大小)可以将分块数量减少 90% 以上,同时提高准确性、提升嵌入速度,并通过维持语义上下文来增强整体检索质量。
合并算法的工作原理(技术细节)

对于大多数用户来说,上面的解释就足够了:小块会与其邻近内容合并,从而在减少向量数量的同时带来更好的检索效果以及其他性能、成本和存储方面的好处。但如果您对其背后的确切逻辑和设计原理感到好奇,以下是它的底层工作原理。

为什么基于标题的切分需要合并

Markdown 标题切分是分块中较好的结构化方法之一,因为标题是文档作者放置的显式语义边界。您正在利用人类对一个话题何处结束、另一个话题何处开始的判断力,这通常比可能在中途截断段落或思路的固定大小窗口化方法产生更连贯的分块。

然而,实际文档经常存在结构上的奇特之处:目录、简短的引导性章节、拥有自己标题的单句段落,或者内容极少的深度嵌套子标题。这些情况会产生微小的分块,从而导致以下问题:

  • 当孤立地检索它们时,由于缺乏足够的上下文而毫无用处。
  • 可能会产生有噪的检索结果(在有限的信号上匹配,但无法贡献任何有用的信息)。
  • 极短的文本有时进行嵌入的可靠性较低。
  • 浪费向量存储并拖慢检索速度。
  • 许多分块比起较少的分块(在总内容相同的情况下)需要更长的嵌入时间。
  • 更多的嵌入操作意味着更多的 API 调用(成本)或更多的本地计算。

合并算法通过智能地组合尺寸过小的分块,同时尊重文档结构和大小限制来解决这一问题。

算法:单次前向传递

合并逻辑被设计得刻意简单 —— 对所有分块进行单次前向传递:

  1. 从第一个分块开始,作为“当前”累加器。
  2. 对于每个后续的分块,检查它是否可以被吸收到当前分块中。
  3. 如果满足以下所有三个条件,分块就可以被吸收:
    • 当前累加的内容仍低于 CHUNK_MIN_SIZE_TARGET
    • 合并不会超过最大限制 CHUNK_SIZE
    • 两个分块都属于同一个源文档。
  4. 如果可以吸收,则将它们合并(使用 \n\n 分隔以保留视觉结构),并继续检查下一个分块。
  5. 如果无法吸收,则完成当前分块,并以全新的下一个分块作为新的累加器重新开始。
  6. 重复此过程,直到处理完所有分块。

关键点:尺寸检查是针对累加的内容,而不是单个分块。这意味着多个连续的微小分块(例如包含许多小条目的目录)将持续折叠组合在一起,直到合并后的尺寸达到阈值,或者直到合并下一个分块会超过最大限制。

设计决策及其重要性

仅前向合并:小分块总是合并到下一个分块中,绝不向后合并。这使得逻辑保持简单和可预测,并保留了文档中常见的“本章节引出后续内容”的自然关系。一个简短的介绍章节前向合并到它所引入的内容中,在语义上是合乎情理的。

为什么不采用后向合并? 除了会增加代码复杂度之外,后向合并在很多情况下其实也会失败。当任何一个分块被最终确定时,它总是处于以下两种状态之一:要么它通过吸收增长到满足或超过了 CHUNK_MIN_SIZE_TARGET(因此它已经被“满足”,可用空间有限),要么因为它无法吸收下一个分块(因为那会超过 CHUNK_SIZE,所以它已经触及了上限)。无论哪种情况,后向合并尝试通常都会通不过尺寸检查,这意味着您将为了极少成功的事情去添加复杂的分支逻辑和状态跟踪。

严禁跨文档合并:即使两边都很小,也绝不会合并来自不同源文件的分块。这保留了清晰的文档边界,便于进行引用、来源归属和检索上下文。

严格遵守最大大小:如果合并两个分块会超过 CHUNK_SIZE,则两者会保持分离。绝不会丢弃内容来强行合并。

元数据继承:合并后的分块会继承合并序列中第一个分块的元数据。这与前向合并语义是一致的 —— 来源和标题信息反映了合并部分“开始”的位置,这对于检索和引用目的来说通常是正确的选择。

\n\n 分隔符:当分块合并时,它们通过双换行符进行拼接,而不是直接拼接。这在合并后的文本中保留了视觉和结构上的分隔,如果您要检查您的分块,这对于嵌入质量和人类可读性都非常重要。

边缘情况

连续的微小分块:自然处理。它们会持续累加到一个分块中,直到达到阈值或即将超过最大大小。

小分块后跟大分块:如果一个小分块后面跟着一个足够大以至于合并会超过 CHUNK_SIZE 的分块,那么该小分块将照原样完成,即使它依然尺寸过小。如果不进行后向合并或内容分割,这是不可避免的,但在实践中也很少见。它通常发生在自然的语义边界处(在密集章节前的简短过渡),而在该边界处让小分块保持独立其实也是合理的。

文档中的最后一个分块:如果最后一个分块尺寸过小,由于没有后续内容可以前向合并,它将保持尺寸过小的状态。这同样是不可避免的,并且通常没有问题 —— 文档结尾本就是自然的边界。

性能特征

该算法在时间复杂度上是相对于分块数量 O(n) 的 —— 只进行单次传递,不需要前瞻或回溯。这使得它即使对于庞大的文档集也能极快地运行。

合并带来的效率提升在某些方面是非线性增长的。对 45 个向量进行检索与对 588 个向量进行检索相比,不仅仅在原始计算上快了约 13 倍 —— 您还将获得更加干净的 top-k 结果,因为您排除了几乎为空的分块所带来的噪音,那些小分块可能会在部分关键词匹配上得分很高,但对 LLM 来说毫无用处。质量的提升通常比速度的提升更重要。

测试表明,配置合理的阈值(例如,对于 2000 的分块大小,设置 1000 的阈值)可以将分块数量减少 90% 以上,同时提高检索准确性,因为每个留下的分块都携带着有意义的语义上下文,而不是成为混淆嵌入模型和检索排名的碎片。作为积极的副作用,它还占用了向量数据库中更少的存储空间,并且需要更少的嵌入操作,如果外包给第三方嵌入服务,这可以节省可观的成本。

RAG 嵌入支持

直接在 Admin Panel > Settings > Documents 菜单中更改 RAG 嵌入模型。此功能支持 Ollama 和 OpenAI 模型,使您能够根据需求提升文档处理能力。

初始设置后更改 RAG 设置

如果您在文档已经索引后需要更改分块配置(分块大小、重叠度)或嵌入模型,了解需要采取哪些操作以及这些更改将产生什么影响非常重要。

更改分块大小与重叠度

新文档将自动使用更新后的分块大小和重叠度设置 —— 对于新上传的文件无需执行任何操作。

知识库中现有的文档将保留其原始分块,直到您运行重新索引 (re-index)。检索仍将适用于这些旧的分块(向量相似度搜索不依赖于分块大小),但如果旧文档和新文档的分块大小差异非常大,您可能会注意到检索质量不一致。

提示

如果您仅更改分块设置而不更改嵌入模型,则不严格要求重新索引 —— 旧文档仍将继续工作。但是,为了确保所有文档获得一致的检索质量,建议运行重新索引。

更改嵌入模型

更改嵌入模型需要对所有知识库文档重新索引。来自不同模型的嵌入存在于不同的向量空间中,彼此互不兼容。如果不重新索引,针对旧嵌入的检索将产生极差或毫无意义的结果。

Admin Panel > Settings > Documents 中更改嵌入模型后,导航至 Admin Panel > Settings > Documents 并点击 Reindex 按钮,以使用新模型重新对所有知识库文档进行嵌入处理。

重新索引的作用是什么?

重新索引过程对每个知识库执行以下步骤:

  1. 删除该知识库现有的向量集合。
  2. 使用当前的分块大小、重叠度和文本切分器设置重新切分所有文件。
  3. 使用当前配置的嵌入模型重新嵌入所有分块。

这意味着单次重新索引会同时应用分块设置的更改和嵌入模型的更改。

重新索引不涵盖聊天文件

重新索引操作仅处理属于知识库 (knowledge bases) 的文件。直接上传到聊天中(未添加到知识库)的文件拥有它们各自专属的单文件向量集合,重新索引不会影响它们。

如果您更改了嵌入模型,这些独立聊天文件的嵌入仍将使用旧模型,针对这些文件的检索质量将会下降。更新它们的唯一方法是重新上传文件。

总结

更改项新文档知识库文档(未重新索引)知识库文档(重新索引后)独立聊天文件
分块大小 / 重叠度✅ 使用新设置⚠️ 旧分块仍可工作,但质量可能参差不齐✅ 使用新设置重新分块⚠️ 仍为旧分块,需重新上传以更新
嵌入模型✅ 使用新模型❌ 旧嵌入,向量空间不兼容✅ 使用新模型重新嵌入❌ 仍为旧嵌入,需重新上传以更新

RAG 功能中的引用

RAG 功能允许用户通过添加参考点引用,轻松追踪输入给 LLM 的文档上下文。这确保了在您的聊天中使用外部来源时的透明度和可追溯性。

文件上下文 vs 内置工具

Open WebUI 提供了两种控制文件处理方式的独立能力。理解两者的区别对于正确配置模型至关重要。

文件上下文能力

File Context(文件上下文)能力控制 Open WebUI 是否对附加的文件执行 RAG(检索增强生成):

文件上下文 (File Context)行为
已启用(默认)附加的文件通过 RAG 进行处理。内容将被检索并注入到对话上下文中。
已禁用文件处理被完全跳过。无内容提取,无注入。模型不会接收到任何文件内容。

何时禁用文件上下文:

  • 完全绕过 RAG:当您根本不想让 Open WebUI 处理附加的文件时。
  • 仅使用内置工具:如果您更倾向于让模型通过诸如 query_knowledge_bases 之类的工具按需检索文件内容,而不是预先注入内容。
  • 调试/测试:用于隔离排查问题是否与 RAG 处理相关。
禁用文件上下文 = 无预注入内容

当文件上下文被禁用时,文件内容不会被自动提取或注入。Open WebUI 不会将文件转发给模型的原生 API。如果您禁用了此项,模型访问文件内容的唯一方式是使用内置工具(如果已启用)按需查询知识库或检索附加文件(智能体文件处理/agentic file processing)。

单文件检索模式

单个文件和知识库也可以通过开启 "Using Entire Document"(使用整个文档)开关来设为完全绕过 RAG。这将把完整的文件内容注入到每条消息中,而不受原生函数调用 (function calling) 设置的影响。详情请参阅 完整上下文 vs 聚焦检索

信息

文件上下文 (File Context) 开关仅在为模型启用了 File Upload(文件上传)时才会出现。

内置工具能力

Builtin Tools(内置工具)能力控制模型是否接收用于自主检索的原生函数调用工具:

内置工具 (Builtin Tools)行为
已启用(默认)在 Native Function Calling(原生函数调用)模式下,模型会接收诸如 query_knowledge_basesview_knowledge_filesearch_chats 等工具。
已禁用不注入任何内置工具。模型仅使用预先注入的上下文进行工作。

何时禁用内置工具:

  • 模型不支持函数调用:较小或较旧的模型可能无法处理 tools 参数。
  • 需要可预测的行为:您希望模型仅使用预先提供的内容工作。

结合这两种能力

这些能力彼此独立工作,为您提供细粒度的控制:

文件上下文内置工具结果
✅ 已启用✅ 已启用完全智能体模式 (Full Agentic Mode):注入 RAG 内容 + 模型可自主查询知识库
✅ 已启用❌ 已禁用传统 RAG:预先注入内容,不提供自主检索工具
❌ 已禁用✅ 已启用仅工具模式 (Tools-Only Mode):无预注入内容,但模型可以使用工具按需查询知识库或检索附加文件
❌ 已禁用❌ 已禁用无文件处理:忽略附加的文件,没有任何内容传递给模型
选择正确的配置
  • 绝大多数模型:保持两者启用(默认),以获得完整的功能。
  • 小型/本地模型:如果它们不支持函数调用,请禁用内置工具。
  • 仅按需检索:如果您希望模型自行决定检索什么内容,而不是预先注入所有内容,请禁用文件上下文并启用内置工具。

增强版 RAG 管道

我们的 RAG 嵌入功能所带的可切换混合搜索子功能,通过 BM25 增强了 RAG 功能,其重排 (re-ranking) 由 CrossEncoder 驱动,并带有可配置的相关性得分阈值。这为您特定的使用场景提供了更加精准和定制化的 RAG 体验。

KV 缓存优化(性能提示)🚀

对于专业和高性能的使用场景 —— 尤其是处理长文档或频繁进行追问时 —— 您可以通过启用 KV Cache Optimization(KV 缓存优化)来显著缩短响应时间。

问题所在:缓存失效

默认情况下,Open WebUI 将检索到的 RAG 上下文注入到用户消息中。随着对话的进行,后续的追问消息会改变该上下文在聊天历史记录中的位置。对于许多 LLM 引擎 —— 包括本地引擎(如 Ollama、llama.cpp 和 vLLM)以及云端提供商/模型即服务 (Model-as-a-Service) 提供商(如 OpenAI 和 Vertex AI) —— 这种位置的移动会导致 KV(键值)前缀缓存Prompt Cache(提示词缓存)失效,从而迫使模型为每一次回复都重新处理整个上下文。这会导致随着对话的增长,延迟增加,并可能产生更高的成本。

解决方案:RAG_SYSTEM_CONTEXT

您可以通过启用 RAG_SYSTEM_CONTEXT 环境变量来修复这一行为。

  • 工作原理:当 RAG_SYSTEM_CONTEXT=True 时,Open WebUI 将 RAG 上下文注入到系统消息 (system message) 中,而不是用户消息中。
  • 结果:由于系统消息始终处于提示词的绝对开头,且其位置永远不会改变,因此提供商可以高效地缓存已处理的上下文。这样,后续的追问就能受益于即时响应成本节约,因为“重度计算”(处理庞大的 RAG 上下文)仅执行一次。
推荐配置

如果您使用的是 Ollamallama.cppOpenAIVertex AI,并且经常需要“与您的文档对话”,请在您的环境中设置 RAG_SYSTEM_CONTEXT=True,体验大幅提速的追问响应!

YouTube RAG 管道

专用于通过视频 URL 总结 YouTube 视频的 RAG 管道,可实现直接与视频转录文本的顺畅交互。这一创新功能允许您将视频内容融入您的聊天中,从而进一步丰富您的对话体验。

文档解析

有多种解析器可以提取本地和远程文档的内容。欲了解更多信息,请参见 get_loader 函数。

临时聊天限制

当使用 Temporary Chat(临时聊天)时,文档处理被限制为仅在前端进行,以确保您的数据保持私密且不被存储在服务器上。因此,高级后端解析(用于处理复杂 DOCX 文件等格式)将被禁用,这可能会导致看到原始数据而不是解析后的文本。如需获得完整的文档支持,请使用标准的聊天会话。

Google Drive 集成

当配合启用了 Google Picker API 和 Google Drive API 的 Google Cloud项目时,此功能允许用户直接从聊天界面访问其云端硬盘文件,并将文档、幻灯片、表格等内容上传为您的聊天上下文。该功能可在 Admin Panel > Settings > Documents 菜单中启用。使用前必须设置 GOOGLE_DRIVE_API_KEY and GOOGLE_DRIVE_CLIENT_ID 环境变量。

详细步骤

  1. 创建一个 OAuth 2.0 客户端,并配置 Authorized JavaScript origins(已授权的 JavaScript 来源)以及 Authorized redirect URI(已授权的重定向 URI),将其设为您访问 Open WebUI 实例所使用的 URL(若有端口请包含端口)。
  2. 记录与该 OAuth 客户端关联的 Client ID(客户端 ID)。
  3. 确保为您项目启用了 Google Drive API 和 Google Picker API。
  4. 另外,将您的应用(项目)设置为 Testing(测试)状态,并将您的 Google Drive 电子邮件地址添加到 User List(用户列表)中。
  5. 设置权限范围以包含这些 API 所能提供的所有范围。并且由于应用将处于测试模式,Google 不需要进行任何验证即可允许该应用访问受限测试用户的数据。
  6. 前往 Google Picker API 页面,点击 create credentials(创建凭证)按钮。
  7. 创建一个 API key,并在 Application restrictions(应用限制)下选择 Websites(网站)。然后添加您的 Open WebUI 实例的 URL,这与步骤 1 中的已授权 JavaScript 来源和已授权重定向 URI 设置相同。
  8. 对 API Key 设置 API 限制,使其仅能访问 Google Drive API & Google Picker API。
  9. 将环境变量 GOOGLE_DRIVE_CLIENT_ID 设置为步骤 2 中 OAuth 客户端的 Client ID。
  10. 将环境变量 GOOGLE_DRIVE_API_KEY 设置为步骤 7 中设置的 API Key 值(而不是步骤 2 中的 OAuth 客户端密钥/client secret)。
  11. 将环境变量 GOOGLE_REDIRECT_URI 设置为您的 Open WebUI 实例的 URL(若有端口,包含端口)。
  12. 接着,使用这三个环境变量重新启动您的 Open WebUI 实例。
  13. 之后,确保已在 Admin Panel > Settings > Documents > Google Drive 下启用了 Google Drive。
This content is for informational purposes only and does not constitute a warranty, guarantee, or contractual commitment. Open WebUI is provided "as is." See your license for applicable terms.