Meilisearch v1.14 发布啦 ✨ 在我们的博客上阅读更多

转到主页Meilisearch 的标志
返回文章
2025 年 1 月 29 日

使用 Meilisearch 构建 RAG 系统:综合指南

探索构建 RAG 系统的最佳实践,包括优化文档、集成 AI 的技巧,以及为何有效的检索是成功的关键。

Carolina Ferreira
Carolina Ferreira开发者布道师 @ Meilisearch@CarolainFG
Building a RAG system with Meilisearch: a comprehensive guide

检索增强生成 (RAG) 已成为现代 AI 应用的重要组成部分,使大型语言模型 (LLM) 能够产生更准确和可控的响应。虽然向量数据库是 RAG 的标准配置,但 Meilisearch 以其快速、开源的特性和 AI 驱动的搜索、卓越的相关性和非凡的速度而脱颖而出,成为一种替代方案。

本指南将引导您完成使用 Meilisearch 构建和优化 RAG 系统的过程。

理解 RAG

RAG 是一种通过将大型语言模型 (LLM) 的输出基于外部可检索数据来增强其性能的过程。RAG 系统不是仅仅依赖模型训练的知识,而是首先从精选的知识库中检索相关信息,然后使用此上下文来生成响应。

典型的 RAG 工作流程包含三个主要步骤

  1. 检索:查询知识库以查找相关文档或段落
  2. 增强:将检索到的信息与用户查询结合
  3. 生成:使用 LLM 基于查询和检索到的上下文生成回应

RAG 的关键组件

一个 RAG 系统包含三个基本组件

  • 外部数据源 外部数据源是 RAG 系统的基础。这些来源(例如知识库或技术文档)提供了 LLM 用来生成响应的信息。此数据的质量直接影响性能;它必须组织良好,并定期更新以确保准确性和相关性。

  • 向量存储 向量存储充当原始数据和 LLM 之间的桥梁。它将文本转换为向量嵌入——含义的数值表示。这些向量允许高效的相似性搜索,从而可以快速检索相关信息。像 Meilisearch 这样的现代工具将关键词搜索与语义相似性相结合,以提供快速且可扩展的结果。

  • 大型语言模型 LLM 是系统的智能核心,负责理解用户查询并生成连贯、相关的响应。它将用户查询与从向量存储中检索到的上下文相结合,以生成准确的回复。像 GPT-4、Claude 或 Llama 2 这样的模型擅长在提供的上下文约束内创建类似人类的回应。

为什么 LLM 需要 RAG:克服关键限制

大型语言模型在通用知识方面表现出色,但也面临两个重大限制

  • 它们在处理特定领域的专业信息时遇到困难
  • 它们受限于上次训练会话,依赖过时的知识,并且常常落后于当前进展数月甚至数年。

RAG 让您能够同时应对这两个挑战。例如,一家律师事务所可以通过整合其历史案例档案以及最新的法院判决和监管变更来增强其 LLM 的能力。医疗保健提供商可能会整合已建立的医学文献和最新的临床试验或更新的治疗方案。

持续更新知识库的能力确保了您的 LLM 驱动的应用程序能够提供准确、最新的回应,这些回应将深入的领域专业知识与您所在领域的最新信息相结合。

如何优化 RAG 系统中的文档检索

高效的信息检索对于 RAG 至关重要。如果没有精确且相关的文档检索,即使是最先进的 LLM 也可能产生不准确或不完整的响应。目标是确保仅检索到最相关、上下文丰富的文档以响应查询。

选择正确的文档检索系统是至关重要的一步。Meilisearch 提供了一个快速、开源的搜索引擎,它支持关键词搜索和更高级的 AI 驱动的搜索方法,这些方法将精确的单词匹配与语义搜索相结合。这种双重能力使其成为 RAG 系统的理想工具,其目标不仅是检索与关键词匹配的文档,还要检索那些语义相关的文档

Meilisearch 提供了一系列专门为 RAG 系统设计的功能

  • 轻松的嵌入器集成:Meilisearch 自动生成向量嵌入,实现高质量的语义检索,只需最少的设置,并可以灵活选择最新的嵌入器模型。
  • 混合搜索能力:结合关键词搜索和语义(基于向量)搜索,以提供更广泛、更准确的文档检索。
  • 速度和性能:Meilisearch 提供超快的响应时间,确保检索永远不会成为您 LLM 工作流程的瓶颈。
  • 可定制的相关性:调整排名规则,并根据新鲜度或重要性等属性对文档进行排序,以优先显示最有价值的结果。设置相关性阈值以排除不太相关的结果。

一旦您建立了检索系统,下一步就是优化数据的存储、索引和检索方式。以下策略——文档分块、元数据丰富和相关性调整——将确保每个搜索查询都返回最有用且上下文最相关的信息。

如何分块文档以最大化相关性

将文档分解为最佳大小的块对于有效的检索至关重要。块应足够大以保持上下文,但又足够小以具有针对性和相关性。考虑语义边界,如段落或章节,而不是任意字符计数。

丰富元数据以提高搜索精度

使用丰富的元数据增强您的文档以提高检索准确性。包括类别、标签、时间戳、作者和其他相关属性。例如,用特定产品版本标记技术文档可以显着提高检索质量。

调整相关性以获得准确的结果

根据您的具体用例微调搜索参数。调整 混合搜索语义比率,以根据您所在领域的需要平衡概念理解和精确匹配。使用 排名分数阈值 来过滤掉低质量的匹配项,但要注意不要设置得太高而错过有价值的上下文信息。

为 RAG 设置 Meilisearch

检索系统的质量直接影响生成响应的准确性和可靠性。Meilisearch 以其 AI 驱动的搜索能力、可定制的文档处理和高级排名控制,成为 RAG 实现的理想搜索引擎。

设置 Meilisearch

与传统上仅依赖语义搜索的向量存储不同,Meilisearch 将向量相似性与全文搜索相结合,为您提供两全其美的方案。

首先,您需要创建一个 Meilisearch 项目并激活 AI 驱动的搜索功能

然后,您需要配置您选择的嵌入器。我们将使用 OpenAI 嵌入器,但 Meilisearch 也支持来自 HuggingFace、Ollama 以及任何可通过 RESTful API 访问的嵌入器。

import os
import meilisearch

client = meilisearch.Client(os.getenv('MEILI_HOST'), os.getenv('MEILI_API_KEY'))

# An index is where the documents are stored.
index = client.index('domain-data')

index.update_embedders({
    "openai": {
        "source": "openAi",
        "apiKey": "OPEN_AI_API_KEY",
        "model": "text-embedding-3-small",
        "documentTemplate": "A document titled '{{doc.hierarchy_lvl1}}'. Under the section '{{doc.hierarchy_lvl2}}'. This is further divided into '{{doc.hierarchy_lvl3}}'. It discusses {{doc.content}}."
    }
})

注意:您需要将 OPEN_AI_API_KEY 替换为您的 OpenAI API 密钥。

使用 Meilisearch 文档模板进行智能文档处理

Meilisearch 的 文档模板 允许您自定义每个文档的嵌入,确保仅包含最相关的字段。

自定义文档处理可以帮助您

  • 通过精确的嵌入提高检索相关性
  • 通过减少不必要的 token 降低成本
  • 确保不同文档类型之间的一致性
  • 支持独特数据格式的领域特定需求
  • 随着系统的发展,迭代和改进嵌入策略

这是一个来自 Meilisearch 文档的示例文档

{
    "hierarchy_lvl1":"Filter expression reference"
    "hierarchy_lvl2":"Filter expressions"
    "hierarchy_lvl3":"Creating filter expressions with arrays"
    "content":"Inner array elements are connected by an OR operator. The following expression returns either horror or comedy films"
    "hierarchy_lvl0":"Filtering and sorting"
    "anchor":"creating-filter-expressions-with-arrays"
    "url":"https://meilisearch.org.cn/docs/learn/filtering_and_sorting/filter_expression_reference#creating-filter-expressions-with-arrays"
    "objectID":"bbcce6ab00badb2a377b455ba16180d"
    "publication_date":"1733986800"
}

为了优化此文档的嵌入,我们决定专注于最有意义的字段

  • 标题:hierarchy_lvl0 到 hierarchy_lvl3 的值将包含在嵌入中,以保留文档结构和上下文
  • 内容:content 的值将被嵌入,因为它提供了语义搜索所需的必要文本

其他字段,如 publication_date,将从嵌入中排除,但仍可用于排序。这允许 Meilisearch 按日期排序,同时保持嵌入的精简并专注于相关性

Meilisearch 可定制的排名规则

Meilisearch 提供对结果排名的细粒度控制,使您能够自定义搜索结果的排序和优先级。这种控制确保用户首先看到最相关的内容,这些内容根据您的特定业务或领域需求量身定制。

与固定的排名系统不同,Meilisearch 允许您定义 您自己的排名规则。这种灵活性有助于您优先考虑某些类型的内容,提升更新或更相关的结果,并创建符合用户期望的搜索体验。

例如,我们在默认排名规则中添加了一条自定义规则,以优先显示较新的文档。

# Configure settings

import os
import meilisearch

# Initialize the Meilisearch client
client = meilisearch.Client(os.getenv('MEILI_HOST'), os.getenv('MEILI_API_KEY'))

# An index is where the documents are stored.
index = client.index('domain-data')

index.update_settings({
    'rankingRules': [
        "words",
        "typo",
        "proximity",
        "attribute",
        "sort",
        "exactness",
        "publication_date:desc",
    ],
    'searchableAttributes': [
        'hierarchy_lvl1',
        'hierarchy_lvl2',
        'hierarchy_lvl3',
        'content'
    ]
})

索引您的文档

在设置 Meilisearch 并使用文档分块和元数据丰富等最佳实践准备数据后,您现在可以将数据推送到 Meilisearch。

Meilisearch 接受 .json.ndjson.csv 格式的数据。有几种方法可以上传您的文档

  • 将文件拖放到 Cloud UI 中。
  • 通过 /indexes/{index_uid}/documents 路由使用 API。
  • 从您首选的 SDK 调用方法

💡 注意:您的文档必须具有唯一的标识符 (id)。这对于 Meilisearch 正确识别和更新记录至关重要。

这是如何使用 Python SDK 上传文档的方法

import os
import meilisearch
import json

# Initialize Meilisearch client
client = meilisearch.Client(os.getenv('MEILI_HOST'), os.getenv('MEILI_API_KEY')))

# Select or create the index
index = client.index('domain-data')

# Load the JSON file
with open('path/to/your/file.json', 'r') as file:
    documents = json.load(file)  # Load the array of JSON objects as a Python list

# Add documents to Meilisearch
index.add_documents(documents)

执行 AI 驱动的搜索

使用 qhybrid 执行 AI 驱动的搜索,以使用您之前配置的嵌入器检索搜索结果。

Meilisearch 将返回语义匹配和全文匹配的组合,优先考虑与查询的含义和上下文相匹配的结果。您可以使用 semanticRatio 参数微调这种平衡

index.search(
    userQuery,  
    {
        "hybrid": {
            "embedder": "openai",
            "semanticRatio": 0.7  # 70% semantic, 30% full-text
        }
    }
)

这种灵活的控制使您能够

  • 优化平衡以适应您的特定用例。
  • 根据查询模式实时调整。
  • 结合两种方法的优势,确保您不会错过关键结果。

这种双重方法确保您不会错过可能从纯语义搜索的漏洞中溜走的相关结果,同时保持语义理解的优势。

使用排名分数阈值进行质量控制

rankingScoreThreshold 参数 确保只有高质量的结果包含在搜索响应中。它与 排名分数 协同工作,排名分数是一个介于 0.0(差匹配)到 1.0(完美匹配)之间的数值。任何排名分数低于指定 rankingScoreThreshold 的结果都将被排除。

通过设置排名分数阈值,您可以

  • 过滤掉低相关性结果,以提高整体结果质量
  • 为 RAG 系统提供更好的上下文,确保 LLM 使用更高质量的数据
  • 减少搜索结果中的噪音,最大限度地减少不相关的信息
  • 自定义相关性以符合您的特定用例需求

以下查询仅返回排名分数大于 0.3 的结果

index.search(
    userQuery,  
    {
        "hybrid": {
            "embedder": "openai",
            "semanticRatio": 0.7  # 70% semantic, 30% full-text
        },
        "rankingScoreThreshold": 0.4

    }
)

准备好构建您的 RAG 系统了吗?现在我们已经设置了 Meilisearch。我们将引导您完成使用 Meilisearch 创建 RAG 系统的步骤。

使用 Meilisearch 实现 RAG

我们将使用 Meilisearch 文档作为示例知识库构建一个 RAG 系统,演示如何检索、处理和生成准确、上下文感知的回应。

使用的关键技术

我们的实现利用了以下几项关键技术

  • FastAPI:为处理用户查询的 API 提供动力
  • Meilisearch:检索相关内容
  • OpenAI 的 GPT-4:生成类似人类的、上下文相关的回应
  • LangChain:通过链接搜索和 LLM 响应生成来协调 AI 工作流程。

系统如何工作

当用户提交问题时,系统将执行以下步骤

  • 用户输入:用户向 API 提交查询
  • 内容检索:Meilisearch 使用关键词搜索和语义搜索的组合来搜索最相关的内容
  • 上下文构建:系统从搜索结果构建分层上下文
  • LLM 生成:上下文和用户查询被发送到 GPT-4 以生成准确、实用的回应
  • 响应交付:系统返回 LLM 生成的答案以及用于生成答案的来源

设置环境

API 密钥和凭据存储在 .env 文件中的环境变量中。我们使用 dotenv 来加载它们。

以下是关键服务的初始化方式

  • Meilisearch 客户端:使用主机和 API 密钥连接到 Meilisearch 实例。
  • OpenAI 客户端:通过 API 密钥验证 GPT-4 LLM
  • FastAPI 应用程序:设置 Web API 以供用户与系统交互
import os
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from meilisearch import Client
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Initialize FastAPI application
app = FastAPI()

# Initialize Meilisearch client
client = meilisearch.Client(os.getenv('MEILI_HOST'), os.getenv('MEILI_API_KEY')))

# Initialize OpenAI
llm = ChatOpenAI(temperature=0, model="gpt-4o", api_key=os.getenv('OPENAI_API_KEY'))

配置 CORS 中间件

为了确保系统可以处理来自不同来源(如前端客户端)的请求,我们为 FastAPI 应用程序配置了跨域资源共享 (CORS)。这允许来自任何域的跨域请求。

# Configure CORS middleware to allow cross-origin requests
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Allows all origins
    allow_credentials=True,  # Allows credentials (cookies, authorization headers, etc.)
    allow_methods=["*"],  # Allows all HTTP methods
    allow_headers=["*"],  # Allows all headers
)

定义查询数据模型

Query 类定义了传入 POST 请求的数据结构。这确保只接受包含有效问题的查询。

class Query(BaseModel):
    question: str

工作原理

  • 输入验证:FastAPI 将自动验证传入的 POST 请求是否包含类型为字符串的有效 question 字段
  • 数据解析:传入的查询被解析为 Query 对象,该对象可以在端点内使用

定义 API 端点

API 公开一个 POST 端点 (/query),用户可以在其中发送查询。此端点检索相关内容,构建上下文,并从 GPT-4 返回答案。

@app.post("/query")
async def query_documents(query: Query):
    """Query documents and generate response using RAG."""

查询 Meilisearch 以获取相关文档

系统使用混合搜索方法查询 Meilisearch,该方法将语义搜索 (70%) 与关键词搜索 (30%) 相结合。它还强制执行 0.4rankingScoreThreshold,确保仅包含高质量的结果。

    try:
        # Prepare search parameters
        search_params =     {
        "hybrid": {
            "embedder": "openai",
            "semanticRatio": 0.7  # 70% semantic, 30% full-text
        },
        "limit": 5, # restricts results to 5 documents
        "rankingScoreThreshold": 0.4
    }
        
        # Search Meilisearch
        search_results = meili.index('domain-data').search(
            query.question,  
            search_params
        )

为 GPT-4 构建上下文

一旦 Meilisearch 返回搜索结果,系统将处理它们以创建结构化上下文。上下文保留文档的层次结构,确保标题和副标题被保留。

上下文构建过程

  • 提取分层数据:系统从搜索结果中提取分层级别(hierarchy_lvl0、hierarchy_lvl1 等)。
  • 连接上下文:标题和主要内容结合在一起,以创建清晰、可读的上下文。
  • 分隔章节:每个文档的上下文都使用 “---” 分隔,以提高 GPT-4 的清晰度。
        # Prepare context from search results
        contexts = []
        for hit in search_results['hits']:
            context_parts = []
            
            # Add hierarchical path
            for i in range(4):  # levels 0-3
                hierarchy_key = f'hierarchy_lvl{i}'
                if hit.get(hierarchy_key):
                    context_parts.append(f"{'  ' * i}> {hit[hierarchy_key]}")
            
            # Add content
            if hit.get('content'):
                context_parts.append(f"\nContent: {hit['content']}")
                
            contexts.append("\n".join(context_parts))
        
        context = "\n\n---\n\n".join(contexts)

使用 GPT-4 生成回应

组装好的上下文与用户的问题一起传递给 GPT-4。精确的提示确保回应是

  • 实用且以实施为重点
  • 基于实际文档
  • 在信息不可用时明确说明局限性
        # Create prompt template
        prompt_template = """You are a helpful Meilisearch documentation assistant. Use the following Meilisearch documentation to answer the question. 
If you cannot find the answer in the context, say so politely and suggest checking Meilisearch's documentation directly.
Provide practical, implementation-focused answers when possible.

Context:
{context}

Question: {question}

Answer (be concise and focus on practical information):"""

使用 LangChain 运行 LLMChain

  • 创建 LLMChain:这会将 GPT-4 链接到格式化的提示。
  • 发送输入:用户查询和上下文被发送到 LLM 进行处理。
  • 返回响应:LLM 的响应返回给用户。
        prompt = PromptTemplate(
            template=prompt_template,
            input_variables=["context", "question"]
        )
        
        # Create and run chain
        chain = LLMChain(llm=llm, prompt=prompt)
        response = chain.run(context=context, question=query.question)

组装最终 API 响应

最终 API 响应包括

  • LLM 生成的答案
  • 来源(使用的文档的 URL 和层次结构)
        return {
            "answer": response,
            "sources": [{
                'url': doc.get('url', ''),
                'hierarchy': [
                    doc.get(f'hierarchy_lvl{i}', '') 
                    for i in range(4) 
                    if doc.get(f'hierarchy_lvl{i}')
                ]
            } for doc in search_results['hits']]
        }

处理错误和异常

为了避免系统崩溃,所有异常都会被捕获并作为错误响应返回。

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

运行应用程序

最后,您可以使用 Uvicorn 在本地运行 API。此命令在 localhost:8000 上启动 FastAPI 应用程序。

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

此时,您的 RAG 系统已上线,能够使用 Meilisearch 和 GPT-4 检索相关上下文并生成精确的答案。

如何评估 RAG 系统的性能

确保 RAG 系统中的高质量内容

对您的文档库保持高标准。定期审核和更新您的内容,以确保准确性和相关性。删除重复或过时的信息,这些信息可能会稀释搜索结果。建立验证和更新信息的过程,以维护知识库的完整性。

监控性能以识别瓶颈

实施监控以跟踪检索效果。注意失败查询或持续低排名结果的模式。使用此数据来改进您的文档处理和搜索参数。监控技术指标(如响应时间)和质量指标(如相关性分数)以确保最佳性能。这可以通过 Meilisearch Cloud 监控指标和分析仪表板轻松完成。

收集用户反馈

用户反馈是改进 RAG 系统性能的最有价值的来源之一。虽然诸如查询延迟或相关性分数之类的指标提供了技术见解,但用户反馈揭示了现实世界中的问题。

通过收集和分析反馈,您可以识别仅使用系统指标更难检测到的问题,例如

  • 误报:当查询返回不相关结果时
  • 遗漏上下文:当系统未能检索到用户期望看到的文档时
  • 响应缓慢:当用户遇到加载时间缓慢或响应不完整时

用户反馈可以指导您微调 Meilisearch 配置。它可能会突出显示需要调整排序以优先显示更新的文档,提高 rankingScoreThreshold 以过滤掉低相关性结果,优化 documentTemplate 以嵌入更相关的上下文,或将大型文档分块为更小、更有针对性的部分,以提高检索准确性。

主要要点:使用 Meilisearch 最大化 RAG 性能

使用 Meilisearch 实现 RAG 提供了几个关键优势

  • 灵活性:易于与各种数据源和 LLM 集成。
  • 性能:提供快速的检索时间和高效的资源使用。
  • 准确性:结合关键词搜索和语义搜索,以获得更精确的结果。
  • 可扩展性:轻松处理大型、不断增长的知识库。

Meilisearch 的强大功能和高性能使其成为生产就绪 RAG 实现的坚实基础。为了充分利用您的系统,请关注

  • 数据准备和索引:确保您的知识库干净、有组织且结构良好
  • 领域特定的微调:为您的独特上下文调整排名规则、相关性阈值和嵌入策略
  • 持续评估:使用用户反馈、系统指标和 LLM 响应来优化系统性能
  • 知识库更新:定期审查和更新内容,以保持响应的准确性和相关性

随着 Meilisearch 和 LLM 技术的不断发展,未来的进步将为 RAG 系统带来更高的效率、准确性和灵活性——使其成为 AI 驱动应用程序越来越有价值的方法。

有兴趣构建您自己的 RAG 应用程序吗?

准备好构建一个具有闪电般快速的搜索和卓越相关性的强大 RAG 系统了吗?立即开始您的免费 Meilisearch 试用,体验关键词搜索和语义搜索功能的完美融合。

The 10 best AI enterprise search tools and platforms [2025]

2025 年 10 大最佳 AI 企业搜索工具和平台

探索当今市场上十大最佳 AI 企业搜索工具。了解它们在功能、能力、用例、定价等方面的比较情况。

Ilia Markov
Ilia Markov2025 年 4 月 15 日
Building the future of search with Meilisearch AI

使用 Meilisearch AI 构建搜索的未来

我们正在改变开发者使用 Meilisearch AI 构建搜索的方式。不再需要复杂的基础设施——只需开箱即用的强大、智能的搜索。

Quentin de Quelen
Quentin de Quelen2025 年 3 月 24 日
What are vector embeddings? A complete guide [2025]

什么是向量嵌入?完整指南 [2025]

探索您需要了解的关于向量嵌入的一切。了解它们是什么、不同的类型、如何创建它们、应用等等。

Carolina Ferreira
Carolina Ferreira2025 年 3 月 20 日