混合检索增强生成系统

一个支持多文档格式的混合检索增强生成系统,结合语义搜索和关键词搜索,适用于文档查询和知识管理场景。

  • by gwyer
  • Python
  • 本地部署
  • 4 星标
  • 更新于
在 GitHub 查看 gwyer/hybrid-rag-project

使用说明

混合RAG项目

一个具有混合搜索功能的通用检索增强生成(RAG)系统,适用于您提供的任何文档。将语义(密集向量)搜索和关键字(稀疏BM25)搜索相结合,以实现最佳文档检索,并使用MCP服务器API进行轻松集成。

🎯 主要特点:多格式支持•本地LLM•Claude Desktop集成•结构化数据查询•文档类型感知检索

🚀 快速入门(无需MCP!)

您不需要Claude Desktop或MCP来使用此项目! 只需运行:

# 1. Make sure Ollama is running
ollama serve

# 2. Activate virtual environment
source .venv/bin/activate

# 3. Start conversational demo (recommended)
python scripts/demos/conversational.py

# Or use the shortcut
./scripts/bin/ask.sh

就是这样! 询问有关样本数据集中43835个文档块的问题。

📖 看 快速入门指南 了解完整的使用说明。 📚 浏览所有文档 在 docs/ 文件夹或开头 docs/README.md.


概述

该项目实施了一个混合RAG系统,该系统结合了:

  • 语义搜索:用于理解意义和上下文的密集向量嵌入
  • 关键字搜索:BM25稀疏检索用于精确的关键字匹配
  • 混合融合:交互秩融合(RRF),将两种方法的结果结合起来
  • MCP服务器:用于Claude集成的REST API和模型上下文协议服务器
  • 多格式支持:自动从各种文件格式加载文档

混合方法通过利用两种搜索方法的优势来确保更好的检索准确性。

特性

  • 基于Chroma和Ollama嵌入的矢量语义搜索
  • BM25关键字搜索以进行精确的术语匹配
  • 具有互易秩融合(RRF)的集合检索器
  • 与当地Ollama LLM集成以生成答案
  • 支持多种文档格式(TXT、PDF、MD、DOCX、CSV)
  • 从数据目录自动加载文档
  • 带有的RESTful API服务器 /ingest 和 /query 端点
  • 用于Claude Desktop/API集成的模型上下文协议(MCP)服务器
  • 配置驱动架构(无硬编码值)
  • 持久向量存储,用于更快的后续查询

建筑

User Documents → data/ directory
                      ↓
            Document Loader
                      ↓
Query → Hybrid Retriever → [Vector Retriever + BM25 Retriever]
                         → RRF Fusion
                         → Retrieved Context
                         → LLM (Ollama)
                         → Final Answer

先决条件

  1. Python 3.9+
  2. 奥拉玛 在本地安装并运行
  3. 所需Olama型号:
    • llama3.1:latest (或其他LLM模型)
    • nomic-embed-text (或另一种嵌入模型)

安装Ollama

访问 奥拉玛 为您的平台下载并安装Ollama。

安装后,拉出所需的型号:

ollama pull llama3.1:latest
ollama pull nomic-embed-text

确认Ollama正在运行:

curl http://localhost:11434/api/tags

安装

  1. 克隆存储库:
git clone <your-repo-url>
cd hybrid-rag-project
  1. 创建虚拟环境:
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
  1. 安装依赖项:
pip install -r requirements.txt

项目结构

hybrid-rag-project/
├── src/
│   └── hybrid_rag/            # Core application package
│       ├── __init__.py        # Package initialization
│       ├── document_loader.py # Document loading utility
│       ├── structured_query.py# CSV query engine
│       └── utils.py           # Logging and utility functions
├── scripts/
│   ├── run_demo.py            # Main demonstration script
│   ├── mcp_server.py          # REST API server
│   └── mcp_server_claude.py   # MCP server for Claude integration
├── config/
│   ├── config.yaml            # Configuration file
│   └── claude_desktop_config.json # Sample Claude Desktop MCP config
├── docs/
│   ├── INSTALLATION.md        # Detailed installation guide
│   ├── STRUCTURED_QUERIES.md  # CSV query documentation
│   ├── ASYNC_INGESTION.md     # Async ingestion guide
│   └── SHUTDOWN.md            # Shutdown handling guide
├── data/                      # Sample data files (13 files included)
│   ├── *.csv                  # 7 CSV files (structured data)
│   ├── *.md                   # 5 Markdown files (unstructured)
│   └── *.txt                  # 1 Text file (technical specs)
├── chroma_db/                 # Vector store (auto-created)
├── tests/                     # Unit tests
│   └── extract_fields_tests.py
├── setup.py                   # Package setup file
├── requirements.txt           # Python dependencies
├── TESTING_RESULTS.md         # Comprehensive test results
├── CONTRIBUTING.md            # Contribution guidelines
├── CHANGELOG.md               # Version history
├── LICENSE                    # MIT License
└── README.md                  # This file

示例数据(UCSC扩展项目)

此存储库包括 13个样本数据文件 用于演示和测试目的。这些文件代表了TechVision Electronics的现实业务场景,旨在展示该系统在多种文档类型中的功能。

📊 包含的示例文件

结构化数据(CSV)-7个文件:

  • product_catalog.csv -带规格的产品库存(5000行)
  • inventory_levels.csv -库存水平和仓库数据(10000行)
  • sales_orders_november.csv -月度销售交易记录(8000行)
  • warranty_claims_q4.csv -客户保修索赔(3000行)
  • production_schedule_dec2024.csv -制造进度表(4000行)
  • supplier_pricing.csv -供应商定价信息(6000行)
  • shipping_manifests.csv -运输和物流数据(5000行)

非结构化数据(Markdown)-5个文件:

  • customer_feedback_q4_2024.md -客户评论和反馈(600块)
  • market_analysis_2024.md -市场研究和趋势(400块)
  • quality_control_report_nov2024.md -质量控制发现和问题(501块)
  • return_policy_procedures.md -政策文件(300块)
  • support_tickets_summary.md -技术支持摘要(700块)

文本数据-1个文件:

  • product_specifications.txt -技术规格(334块)

总数据集:

  • 41000行CSV (分块为41000个文档,每个块10行)
  • 2835个文本/标记块 (分块为1000个字符,重叠200个字符)
  • 总共43835个可搜索文档块

🎯 目的

这些示例文件包含在:

  1. 演示 该系统的混合搜索能力
  2. 测试 语义(向量)和词汇(关键字)检索
  3. 验证 文档类型感知检索架构
  4. 提供 无需额外设置的即时工作示例
  5. 展示 跨文档查询综合

📖 测试结果

综合测试结果记录在 TESTING_RESULTS.md,显示:

  • ✅ 检索成功率100% 跨所有文档类型
  • ✅ 17个测试查询 详细结果
  • ✅ 性能指标 比较分析
  • ✅ 语义vs词汇vs混合 搜索比较

💡 使用样本数据

快速入门:

# 1. Run setup
./setup.sh

# 2. The sample data is already in data/ - ready to use!

# 3. Run the demo
python scripts/run_demo.py

# 4. Or use Claude Desktop
# Configure MCP server and query: "What are the prices in the product catalog?"

用于生产用途: 要使用自己的数据,请执行以下操作:

  1. 从中删除或备份示例文件 data/
  2. 添加您自己的文档(TXT、PDF、MD、DOCX、CSV)
  3. 重新运行摄入
  4. (可选)取消注释中的数据排除 .gitignore

## Configuration

All settings are managed in `config/config.yaml`:

```yaml
# Ollama Configuration
ollama:
  base_url: "http://localhost:11434"
  embedding_model: "nomic-embed-text"
  llm_model: "llama3.1:latest"

# Data Configuration
data:
  directory: "./data"
  supported_formats:
    - "txt"
    - "pdf"
    - "md"
    - "docx"
    - "csv"

# Retrieval Configuration
retrieval:
  vector_search_k: 2
  keyword_search_k: 2

# MCP Server Configuration
mcp_server:
  host: "0.0.0.0"
  port: 8000

# Vector Store Configuration
vector_store:
  persist_directory: "./chroma_db"

将此文件修改为:

  • 使用不同的Olama型号
  • 更改数据目录位置
  • 调整检索参数(k值)
  • 配置服务器主机/端口
  • 更改矢量存储持久位置

用法

选项1:命令行脚本

  1. 添加您的文档 到 data/ 目录:
cp /path/to/your/documents/*.pdf data/
cp /path/to/your/documents/*.txt data/
  1. 运行脚本:
python scripts/run_demo.py

脚本将:

  • 从加载所有支持的文档 data/ 目录
  • 初始化Ollama嵌入和LLM
  • 创建矢量和BM25检索器
  • 构建混合RAG链
  • 执行示例查询并显示结果

选项2:REST API服务器

  1. 启动REST API服务器:
python scripts/mcp_server.py

服务器将于启动 http://localhost:8000

要停止服务器,请执行以下操作: 按 Ctrl+C 用于优雅关机

  1. 摄入文件 (先这样做):
curl -X POST http://localhost:8000/ingest

答复:

{
  "status": "success",
  "message": "Documents ingested successfully",
  "documents_loaded": 15
}
  1. 查询文档:
curl -X POST http://localhost:8000/query \
  -H "Content-Type: application/json" \
  -d '{"query": "What is the main topic of these documents?"}'

答复:

{
  "answer": "Based on the documents...",
  "context": [
    {
      "content": "Document text...",
      "source": "example.pdf",
      "type": ".pdf"
    }
  ]
}
  1. 检查服务器状态:
curl http://localhost:8000/status

API终点

端点 方法 描述
/ GET 健康检查
/ingest POST 从数据/目录加载文档
/query POST 使用混合搜索查询文档
/status GET 获取系统状态和配置

选项3:通过MCP的Claude Desktop/API

MCP(模型上下文协议)服务器允许Claude直接查询您的本地RAG系统。

Claude桌面设置

  1. 首先,将文档添加到数据目录中:
cp /path/to/your/documents/*.pdf data/
  1. 编辑 config/claude_desktop_config.json 文件 要使用正确的绝对路径:
{
  "mcpServers": {
    "hybrid-rag": {
      "command": "python",
      "args": [
        "/absolute/path/to/hybrid-rag-project/scripts/mcp_server_claude.py"
      ],
      "env": {
        "PYTHONPATH": "/absolute/path/to/hybrid-rag-project"
      }
    }
  }
}
  1. 将此配置添加到Claude Desktop:

    在macOS上:

    # Copy the configuration
    mkdir -p ~/Library/Application\ Support/Claude
    # Edit the file and add your MCP server configuration
    nano ~/Library/Application\ Support/Claude/claude_desktop_config.json
    

    在Windows上:

    %APPDATA%\Claude\claude_desktop_config.json
    

    在Linux上:

    ~/.config/Claude/claude_desktop_config.json
    
  2. 重新启动克劳德桌面

  3. 在Claude Desktop中,您现在可以看到可用的MCP工具你可以问克劳德:

    • “使用ingest_documents工具加载我的文档”
    • “查询有关[您的问题]的文档”
    • “检查RAG系统的状态”

可用的MCP工具

Claude将可以使用这些工具:

文件摄取和搜索:

  • ingest_documents:开始从数据/目录异步加载和索引文档
  • get_ingestion_status:监控文档摄取的进度(百分比、当前文件、阶段)
  • query_documents:使用混合搜索(语义+关键字)查询文档
  • get_status:检查RAG系统状态

结构化数据查询(CSV文件):

  • list_datasets:列出所有可用的CSV数据集,包括列数和行数
  • count_by_field:统计字段与值匹配的行数(例如,“统计名为Michael的人”)
  • filter_dataset:获取符合字段条件的所有行(例如,“X公司的所有人员”)
  • get_dataset_stats:获取数据集的统计信息(行、列、内存使用情况)

异步摄入与进度跟踪

摄取过程现在与实时进度更新异步运行:

  • 非阻塞:摄入在后台运行
  • 进度跟踪:查看完成百分比(0-100%)
  • 文件级更新:知道当前正在处理哪个文件
  • 舞台信息:正在加载文件(0-80%)→构建索引(80-100%)→已完成
  • 状态监测:随时检查进度 get_ingestion_status

Claude使用示例

You: "Please start ingesting my documents"
Claude: [Uses ingest_documents tool]
        "Ingestion started. Use get_ingestion_status to monitor progress."

You: "Check the ingestion status"
Claude: [Uses get_ingestion_status tool]
        "Ingestion Status: In Progress
         Progress: 45%
         Stage: loading_files
         Files Processed: 9/20
         Current File: document.pdf
         Documents Loaded: 15"

You: "Check status again"
Claude: [Uses get_ingestion_status tool]
        "Ingestion Status: Completed ✅
         Progress: 100%
         Total Files Processed: 20
         Total Documents Loaded: 35

         You can now use query_documents to search the documents."

You: "What are the main topics in my documents?"
Claude: [Uses query_documents tool with your question]
        "Based on the documents, the main topics are..."

结构化数据查询

对于CSV文件,使用结构化查询工具进行精确计数和过滤:

You: "List available datasets"
Claude: [Uses list_datasets tool]
        "Available Datasets:
         📊 contacts
            Rows: 24,697
            Columns (7): First Name, Last Name, URL, Email Address, Company, Position, Connected On"

You: "Count how many people are named Michael in the contacts dataset"
Claude: [Uses count_by_field tool with dataset="contacts", field="First Name", value="Michael"]
        "Count Result:
         Dataset: contacts
         Field: First Name
         Value: Michael
         Count: 226 out of 24,697 total rows (0.92%)"

You: "Show me all the Michaels"
Claude: [Uses filter_dataset tool]
        "Filter Results:
         Found: 226 rows
         Showing: 100 rows (truncated to 100)

         [1] First Name: Michael | Last Name: Randel | Company: Randel Consulting Associates ..."

何时使用每种方法:

  • 结构化查询 (count_by_field, filter_dataset):用于精确计数、过滤和结构化数据
  • 语义搜索 (query_documents):用于概念问题、理解内容、总结

支持的文件格式

系统会自动加载和处理这些格式:

  • .txt -纯文本文件
  • .pdf -PDF文档
  • .md -Markdown文件
  • .docx -Microsoft Word文档
  • .csv -CSV文件

只需将任何支持的文件放入 data/ 目录!

运作原理

文档加载

这 DocumentLoaderUtility 类别:

  1. 扫描 data/ 递归目录
  2. 识别支持的文件格式
  3. 为每种格式使用适当的加载器
  4. 向每个文档添加元数据(源文件、文件类型)
  5. 返回以下列表 Document 已准备好进行索引的对象

混合检索

这 EnsembleRetriever 使用互易秩融合(RRF)来:

  1. 从向量搜索中检索前k个结果(语义)
  2. 从BM25搜索中检索前k个结果(关键字)
  3. 为每个结果分配相互的排名分数
  4. 合并分数以产生统一的排名
  5. 返回总体上最相关的文档

这种方法处理:

  • 语义查询(“我如何申请休假?”)
  • 关键字查询(“PTO表格HR-42”)
  • 受益于这两种方法的复杂查询

定制

使用不同的模型

编辑 config/config.yaml 更改模型:

ollama:
  embedding_model: "your-embedding-model"
  llm_model: "your-llm-model"

调整检索参数

修改 k 值在 config/config.yaml:

retrieval:
  vector_search_k: 5   # Return top 5 from semantic search
  keyword_search_k: 5  # Return top 5 from keyword search

添加更多文件格式支持

编辑 src/hybrid_rag/document_loader.py 要添加更多加载器:

self.supported_loaders = {
    '.txt': TextLoader,
    '.pdf': PyPDFLoader,
    '.json': JSONLoader,  # Add this
    # ... more formats
}

自定义提示

在中编辑提示模板 scripts/run_demo.py 或 scripts/mcp_server.py:

prompt = ChatPromptTemplate.from_template("""
Your custom prompt here...

<context>
{context}
</context>

Question: {input}
""")

开发流程

  1. 添加文档 到 data/ 目录
  2. 修改配置 在 config/config.yaml 根据需要
  3. 使用命令行进行测试: python scripts/run_demo.py
  4. 部署MCP服务器: python scripts/mcp_server.py
  5. 通过API集成 在您的应用程序中

故障排除

“连接到Ollama时出错”

  • 确保Ollama已安装并正在运行
  • 检查Ollama服务是否可以通过配置的URL访问
  • 验证模型是否已下载: ollama list

“在数据目录中找不到文档”

  • 将文件添加到 data/ 目录
  • 确保文件具有支持的扩展名(.txt、.pdf、.md、.docx、.csv)
  • 检查 config/config.yaml 数据目录路径正确

“模块无基础错误”

  • 确保虚拟环境已激活: source .venv/bin/activate
  • 重新安装依赖关系: pip install -r requirements.txt

检索结果不佳

  • 将更多相关文件添加到 data/ 目录
  • 调整 k 值在 config/config.yaml
  • 尝试不同的嵌入模型
  • 确保查询术语与文档内容匹配

API错误

  • 确保你打电话 /ingest 之前 /query
  • 检查服务器日志以获取详细的错误消息
  • 确认Ollama正在运行且可访问
  • 检查文档是否已成功加载

示例:完整工作流

# 1. Activate environment
source .venv/bin/activate

# 2. Add your documents
cp ~/my-docs/*.pdf data/

# 3. Start MCP server
python scripts/mcp_server.py &

# 4. Ingest documents
curl -X POST http://localhost:8000/ingest

# 5. Query your documents
curl -X POST http://localhost:8000/query \
  -H "Content-Type: application/json" \
  -d '{"query": "Summarize the key points"}'

# 6. Check status
curl http://localhost:8000/status

依赖项

核心库:

  • langchain:法学硕士申请框架
  • langchain-community:社区集成
  • langchain-ollama:Olama集成
  • chromadb:用于嵌入的矢量数据库
  • rank-bm25:BM25实现关键字搜索
  • fastapi:API的Web框架
  • uvicorn:ASGI服务器
  • pyyaml:YAML配置解析

文档加载器:

  • pypdf:PDF处理
  • python-docx:Word文档处理
  • unstructured:Markdown和其他格式

性能提示

  1. 矢量存储持久性:矢量存储持久化到磁盘(chroma_db/)摄取后,使后续查询更快。

  2. 批处理:添加许多文档时,请使用 /ingest 端点一次而不是多次。

  3. 检索参数:较低 k 值(例如2-3)更快并且通常足以用于小文档集。

  4. 模型选择:较小的嵌入模型速度更快,但可能会牺牲一些准确性。

许可证

本项目按原样提供,用于教育和示范目的。

贡献

您可以随时提交问题、分叉存储库,并为任何改进创建pull请求。

资源

更新日志

版本2.0.0

  • 适用于任何文档的通用系统
  • 添加 data/ 文档摄取目录
  • 创建 DocumentLoaderUtility 支持多种格式
  • 按照Python最佳实践重构项目(src布局)
  • 已将所有配置移动到 config/ 目录
  • 已将所有文档移至 docs/ 目录
  • 使用创建了正确的Python包结构 setup.py
  • 将脚本组织成 scripts/ 目录
  • 更新了所有导入路径和文档

版本1.0.0

  • 初步实施人力资源文件样本
  • 使用矢量和BM25检索器的基本混合搜索