基于Apache Doris构建知识图谱增强RAG系统:从向量检索到复杂关系推理

📅 2026/7/28 13:30:35
基于Apache Doris构建知识图谱增强RAG系统:从向量检索到复杂关系推理
在实际 AI 应用开发中,检索增强生成(RAG)技术已成为连接大语言模型与私有知识库的关键桥梁。然而,一个常见的困境是:基础 RAG 系统在处理简单事实性问答时表现尚可,一旦面对涉及多实体、复杂逻辑关系的查询,其基于向量相似度的检索方式就容易导致知识碎片化,难以提供连贯、准确的答案。例如,当用户询问“Doris 是哪家公司捐赠给 Apache 基金会,又被哪些公司或组织所使用”时,基础 RAG 可能只会返回包含“百度捐赠”和“字节跳动使用”的孤立片段,而无法系统性地梳理出“捐赠”和“使用”这两类关系,并组织成结构化的回答。要解决这个问题,一种思路是将结构化的知识图谱与 RAG 结合。知识图谱能够以“实体-关系-实体”三元组的形式,清晰地刻画知识间的关联,为 LLM 提供更富逻辑性的上下文。但随之而来的挑战是技术栈的复杂化:传统方案往往需要引入独立的图数据库来存储知识图谱,再配合向量数据库进行语义检索,这带来了额外的运维成本、数据同步难题和查询延迟。Apache Doris 作为一款高性能的实时分析型数据库,其 HSAP(Hybrid Serving/Analytical Processing)架构提供了向量检索、全文搜索与结构化分析相融合的统一能力。这意味着,我们可以在同一个数据库内,既存储文档分片和向量,也存储知识图谱的实体与关系,并通过统一的查询接口进行混合检索,从而简化架构、提升性能。本文将详细演示如何基于 Apache Doris,从零开始构建一个从基础 RAG 到知识图谱增强 RAG 的完整系统,涵盖环境部署、数据处理、向量入库、图谱构建、混合检索与答案生成的完整闭环。1. 理解 RAG 与知识图谱增强的核心架构在深入代码之前,我们需要厘清两种方案的核心差异与互补关系。基础 RAG 的核心流程是“文档分片 - 向量化 - 向量检索 - 生成答案”。它擅长处理语义匹配,但上下文是线性的文本片段,缺乏对实体间显式关系的理解。知识图谱增强 RAG 则在基础流程前增加了一个“知识结构化”的环节。其核心流程变为“文档分片 - 实体关系抽取 - 图谱构建与向量化 - 图谱检索(实体+关系)- 生成答案”。这个方案的优势在于,当用户查询涉及多个实体及其关系时,系统可以先通过向量检索找到相关实体,再通过图查询找到这些实体之间的所有关联路径,最终将一张结构化的“知识子图”作为上下文提供给 LLM。这使得 LLM 能够基于完整的关联网络进行推理,生成更准确、更全面的答案。Apache Doris 在其中扮演了“统一数据底座”的角色。它通过以下特性支撑整个系统:向量检索:支持 HNSW 等近似最近邻(ANN)索引,高效检索高维向量。结构化查询:支持标准的 SQL,可以高效地查询和关联图谱中的实体与关系。混合负载:能够同时处理用于检索的 OLTP 类点查和用于分析的 OLAP 类复杂查询。数据统一:无需在向量库、图数据库和关系型数据库之间进行数据同步,简化了架构。接下来的实践将分为两大模块:首先构建一个基础 RAG 系统,验证从文档处理到问答的完整链路;然后在此基础上,引入知识图谱增强模块,实现更复杂的知识查询。2. 环境准备与 Doris 部署配置2.1 核心组件与版本选择一个可运行的 RAG 系统需要以下组件协同工作:向量数据库/分析数据库:Apache Doris 2.1.0 及以上版本(本文以 2.1.2 为例),用于存储和检索向量及结构化数据。嵌入模型:用于将文本转换为向量。我们选用BGE-M3模型,它支持多语言、跨向量检索,且效果优异。通过Ollama在本地部署。大语言模型:用于答案生成和实体关系抽取。我们使用DeepSeek的 API 服务。应用框架:使用LangChain来组织文本分片、嵌入生成和 LLM 调用流程。数据处理:使用Pandas进行数据格式转换。图谱构建与可视化:使用NetworkX构建图结构,PyVis进行可视化。2.2 Apache Doris 单机快速部署对于开发和测试环境,可以使用 Docker 快速启动一个 Doris 集群。首先确保已安装 Docker 和 Docker Compose。下载并编排 Docker Compose 文件: 创建一个docker-compose.yml文件,内容如下:version: '3' services: doris-fe: image: apache/doris:2.1.2-fe-x86_64 container_name: doris-fe hostname: doris-fe environment: FE_SERVERS: "doris-fe:9010" FE_ID: 1 ports: - "8030:8030" # web UI - "9030:9030" # MySQL 协议端口 volumes: - ./fe/doris-meta:/opt/apache-doris/fe/doris-meta - ./fe/log:/opt/apache-doris/fe/log networks: - doris-net doris-be: image: apache/doris:2.1.2-be-x86_64 container_name: doris-be hostname: doris-be environment: FE_SERVERS: "doris-fe:9010" BE_ADDR: "doris-be:9050" depends_on: - doris-fe volumes: - ./be/storage:/opt/apache-doris/be/storage - ./be/log:/opt/apache-doris/be/log networks: - doris-net networks: doris-net: driver: bridge启动 Doris 集群: 在包含docker-compose.yml的目录下执行:docker-compose up -d等待片刻后,使用docker-compose logs -f doris-fe查看日志,当看到fe thrift server started等关键日志时,表示 FE 启动成功。连接并初始化: 使用 MySQL 客户端或任何支持 MySQL 协议的工具连接 Doris。这里使用mysql命令行工具:mysql -h 127.0.0.1 -P 9030 -uroot首次连接可能无需密码。连接成功后,可以执行SHOW FRONTENDS;和SHOW BACKENDS;来确认 FE 和 BE 状态均为Alive。2.3 创建数据库与向量表在 Doris 中,我们需要创建两张核心表:一张用于存储基础 RAG 的文档分片和向量,另一张用于存储知识图谱的实体和关系。创建数据库:CREATE DATABASE IF NOT EXISTS doris_rag_demo; USE doris_rag_demo;创建基础 RAG 向量表: 这张表将存储文档分片内容及其对应的向量。我们使用ARRAYFLOAT类型存储向量,并为其创建 HNSW 索引以加速近似最近邻搜索。CREATE TABLE IF NOT EXISTS document_chunks ( `id` BIGINT NOT NULL, `doc_id` VARCHAR(255) NULL COMMENT '原始文档ID', `chunk_index` INT NULL COMMENT '分片序号', `content` TEXT NULL COMMENT '文本分片内容', `embedding` ARRAYFLOAT NOT NULL COMMENT '文本向量,1024维', `metadata` JSON NULL COMMENT '额外元数据,如来源、创建时间等', INDEX idx_embedding (`embedding`) USING ANN PROPERTIES( "dim" = "1024", "ef_construction" = "40", "index_type" = "hnsw", "max_degree" = "32", "metric_type" = "inner_product" ) ) ENGINE=OLAP DUPLICATE KEY(`id`) D