本文将尝试使用 Open WebUI 来构建一个小型的 RAG(检索增强生成)系统 [6]。
RAG 结合了 LLM(大型语言模型)的生成能力与从 LLM 未知来源(通常是组织的 私有数据)检索到的知识,旨在提供针对特定领域准确且精确的回答。
因此,目标是利用 私有数据库 来回答用户关于特定主题的问题。
数据可以来自多种来源:数据库、管理系统、文档、文件系统、网站等。当数据被加载到 RAG 系统时,会被向量化并存储在向量数据库中(例如 ChromaDB)。当用户查询 RAG 时,系统会检索所有与问题相关的数据向量,并将它们包含在发送给 LLM 的提示中。模型随后会在这些数据中寻找所需信息,并结合这些特定信息和其内置的通用知识来回答问题。
可以使用诸如 LllamaIndex 或 LangChain 等库来构建 RAG 系统,但也有一些系统已经内置了所有这些功能。
为了演示整个过程,本文将构建一个专注于烹饪的聊天机器人:Chef Gino,基于 OpenWebUI 和 Ollama 实现。
前提条件
需要在系统(本文以 Windows 电脑为例)上预先安装并配置好 Ollama [8] 和 OpenWebUI [5],并下载 此 压缩包,内含格式化好的若干食谱 [7]。
项目描述
假设我们想构建一个模拟资深厨师知识的聊天机器人,这位厨师熟知众多食谱及制作美味佳肴的秘诀。我们希望这位名叫 Gino 的厨师朋友,能随时根据现有食材推荐美味菜肴。
这个项目并不复杂,但我选择它是因为有趣且网络上有大量免费食谱可用作数据库基础。不过这次我使用了结构化格式的食谱,并通过 ChatGPT 生成以节省时间。
显然,这只是一个原型,构建商业系统需要更严谨和复杂的工作。最后一节列出了主要遇到的问题及需要深入研究的方面,以提升系统质量。
配置及作为 RAG 使用
官方文档中有详细的 RAG 配置教程[6]。步骤如下:
- 下载 食谱压缩包,或自行制作 [7]。
- 在 Ollama 上创建自定义模型,扩展上下文长度,以便向模型发送从食谱中提取的信息。这里以 Mistral:7b 模型为基础,将上下文长度从默认的 2048 token 增加到 8192 token:
- 创建一个 Modelfile 文件。
- 文件内容为:
FROM mistral:7b PARAMETER num_ctx 8192
- 执行命令创建并运行模型 mistral-8k:
ollama create mistral-8k -f Modelfile ollama run mistral-8k
- 创建知识库:
- 在 工作区->知识 中点击 创建知识库。
- 填写 名称(例如 Gino 的知识)和 描述。
- 保持 可见性 为 私有。
- 点击 创建知识。
- 点击 + 导入文件或目录(本文导入了目录 RicetteFormattate),选择步骤2中创建的自定义模型:mistral-8k:latest。
- 创建自定义模型:
- 在 工作区->模型 中点击 +。
- 填写 名称(例如 ChefGino)和 描述。
- 保持 可见性 为 私有。
- 选择步骤2中创建的自定义模型作为 基础模型:mistral-8k:latest。
- 在 系统提示 中输入文本:
充当一位意大利厨师,精通传统烹饪。用意大利语回答,风格热情、直接且专业,仿佛在家中厨房交谈。 不要编造任何食谱。 回答关于菜肴或食谱的问题时,仅使用知识库中提供的文档信息(PDF或文本格式的食谱)。 不要凭空想象或猜测答案;若文档中无相关信息,请礼貌说明无法提供详情。 文档中的食谱通常按以下结构组织: 食谱名称、原料、制作步骤、建议。 当被问及如何制作某道菜时,若知识库中有该食谱,请按以下有序结构回答: 标题、原料(含用量列表)、制作步骤(编号清晰)、建议(实用技巧、烹饪注意事项、地区变体等)。 回答要精准、简洁,专注于食谱内容。 保持亲切真实的语气,像一位充满爱心分享家常烹饪秘诀的厨师。 如有必要,简明易懂地解释复杂步骤,适合初学者。 若问题非针对具体食谱,而是关于原料、步骤或菜肴比较,仍只引用文档中相关信息,且仅提及相关食谱。 回答时开头和结尾均向提问者致意。
- 在 知识 字段选择第3步创建的知识库(Gino 的知识)。
- 在 功能 中仅保留选择:文件上传、使用情况 和 引用。
- 点击 保存并创建。
- 修改文档检索属性:
- 进入页面 管理面板->设置->文档->记忆检索 的 RAG 模型 部分。
- 将以下两条指令替换为:
- 如果上下文不可读或质量差,告知用户并尽力给出最佳答案。 - 如果答案不在上下文中但你拥有知识,向用户解释并用自己的理解给出答案。
- 替换为以下三条指令:
- 如果上下文不可读或质量差,告知用户并说类似“抱歉,我不了解这道食谱”。 - 如果答案不在上下文中,向用户解释,但不要凭自己的理解编造答案。 - 绝不使用模型预训练知识回答与食谱相关的问题——严格使用下面 <context> 部分提供的上下文回答。
- 创建 API Key:
- 按照 [5]指示,在 设置->账户->API 密钥 中点击 创建新密钥,生成 API Key(<YOUR_API_KEY>)。
通过图形界面查询 RAG
此时,我们可以进行测试查询,确保选择了模型:ModelloGino。
图片库展示了以下三个问题的回答:
- 你好 Gino,如何制作海绵蛋糕?
- 如何准备威灵顿牛排?
- 我买了些苹果,怎么做菜?
- 我要邀请朋友吃饭,你能推荐一个三道菜菜单吗?包括前菜、主菜和甜点,使用你最好的食谱。
这些问题分别用基础模型 mistral:7b(M1-M4)和 RAG 及 ModelloGino(G1-G4)回答。
从截图可见,基础模型的回答(M1-M4)较为通用,基于 LLM 训练时获得的知识;而 RAG 系统的回答(G1-G4)则基于我们提供的文档。每个回答底部均标明了信息来源文件。
我们的目标之一是确保系统仅使用知识库中的食谱回答,以避免幻觉并提供准确答案。
为此,我们调整了 系统提示 和 RAG 模板,但系统并不总是遵守规则。例如在回答 G2* 时,ChefGino 经常依赖其“先验知识”来回答知识库中不存在的食谱问题。
值得一提的是,在本地使用一台简单的 联想 Ideapad 3(搭载 Intel Core i7,无 GPU)时,响应时间非常长,几乎令人抓狂,但这是预料之中的。
通过 HTTP API 查询 RAG
要通过 HTTP API 查询 ChefGino 模型,只需执行如下调用:
curl -X POST "http://localhost:3000/api/chat/completions" -H "Content-Type: application/json" -H "Authorization: Bearer <YOUR_API_KEY>" -d '{"model": "ChefGino", "messages": [{"role": "user", "content": "制作卡博纳拉的原料有哪些?"}],"stream": false}'
总结
OpenWeb UI 使构建 RAG 系统变得非常简单。
但要构建可用系统,必须选择合适模型并通过多次试验调整系统参数。
将食谱文件从 PDF 替换为结构化格式后,测试结果显著提升。
需要进一步解决以提升系统性能和可靠性的问题包括:
- 合理配置硬件,并考虑使用 GPU。
- 妥善管理会话。
- 在查询中纳入用户个人资料数据。
- 合理设置传递给 Ollama 的上下文大小。
- 正确设计 系统提示 和 RAG 模板。
- 调优所有向量化系统参数(如分块大小、重叠等)及 LLM 参数(如温度等)。
- 对构成知识库的文档进行格式化。
图片库
*** 注意:本文是通过 n8n 和 OpenAI 自动流程翻译生成的。
















