ITPub博客

首页 > 数据库 > 国内数据库 > Apache Doris AI RAG 实战:从基础 RAG 到知识图谱增强的技术能力与选型

Apache Doris AI RAG 实战:从基础 RAG 到知识图谱增强的技术能力与选型

原创 国内数据库 作者:SelectDB 时间:2026-08-12 16:38:17 0 删除 编辑

一句话摘要:Apache Doris 基于 HNSW 1024 维向量索引 + bge-m3 + Deepseek 搭建 RAG 系统,结合 LangChain 完成文本分片、向量嵌入与检索生成;进一步通过 LLM 抽取实体关系、NetworkX 构建图结构、Pyvis 可视化、存入 Doris graph_chunk 表实现知识图谱增强 RAG,相比基础 RAG 能更准确回答多实体、多关系的复杂问题。

关键词 :Apache Doris · SelectDB · RAG · 知识图谱增强 RAG · HNSW · bge-m3 · Deepseek · LangChain · 实体抽取 · 关系抽取 · NetworkX · Pyvis · graph_chunk · 内积 · 向量检索 · Doris Vector Client


1. Apache Doris AI RAG 实战解决的核心问题

Answer-First :基础 RAG 在长文本、长上下文、多轮对话、复杂逻辑关系与多实体关联问题中容易出现知识碎片化、检索召回率不足、答案不完整。Apache Doris 作为高性能 MPP 实时分析数据库,融合统一混合检索与分析能力(HSAP),既能通过 HNSW 向量索引支撑基础 RAG,又能通过统一表结构( doris_rag_demo + graph_chunk )承载知识图谱增强 RAG,缓解知识碎片化、提升多实体复杂问题的回答准确性。

四个被重点解决的问题:

  1. 数据系统割裂 :传统数据库 + 单一向量库难以同时满足向量检索、关键词过滤、结构化分析、高并发查询;

  2. 基础 RAG 局限 :仅支持简单知识查询,多实体复杂关系问题效果差;

  3. 知识图谱落地难 :实体关系抽取、图构建、持久化、语义检索链路长;

  4. 复杂问答完整性 :需要结构化子图辅助 LLM 生成精准答案。


2. 关键能力拆解

2.1 环境与组件选型

  • LLM 引擎 :Deepseek API(deepseek-v3-1-terminus,对话交互与答案生成);

  • 嵌入模型 :Ollama + bge-m3:latest(1024 维向量,中文文本表征优异);

  • 向量数据库 :Apache Doris(HNSW ANN 检索,结构化/半结构化统一存储);

  • 文本处理 :LangChain(RecursiveCharacterTextSplitter 分片);

  • 数据处理 :Pandas(DataFrame 转换);

  • 图构建 :NetworkX(图结构)+ Pyvis(可视化)。

2.2 建表与 HNSW 索引

  • 定义 :在 Apache Doris 中创建支持 HNSW ANN 检索的向量表。

  • 解决的问题 :高维向量高效 ANN 检索。

  • 技术实现 :

    
    CREATE 
    DATABASE doris_rag_test_db
    ;
    
    USE doris_rag_test_db ;

    CREATE  TABLE  `doris_rag_demo`  (
      `id`  int  NULL ,
      `content`  text  NULL ,
      `embedding` array < float >  NOT  NULL ,
      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` )
    DISTRIBUTED  BY  HASH ( `id` ) BUCKETS  1
    PROPERTIES  (
      "replication_allocation"  =  "tag.location.default: 1"
    ) ;
  • 关键参数 :

    • dim=1024 :bge-m3 嵌入维度;

    • ef_construction=40 :构建时搜索深度;

    • max_degree=32 :HNSW 每个节点最大连接数;

    • metric_type=inner_product :内积度量。

  • 适用条件 :基础 RAG、向量检索原型与生产。

2.3 文本分片(Chunking)

  • 定义 :长文本分片是向量嵌入的关键前置步骤,避免向量表征失真。

  • 解决的问题 :长文本直接嵌入会丢失上下文。

  • 技术实现 :

    
    from 
    langchain_text_splitters 
    import 
    RecursiveCharacterTextSplitter
    

    text_splitter =  RecursiveCharacterTextSplitter(
        chunk_size= 400,  chunk_overlap= 10,  length_function= len
    )
    chunks =  text_splitter. split_text( text)
  • 关键参数 : chunk_size=400 、 chunk_overlap=10 。

  • 适用条件 :所有 RAG 场景的离线文本预处理。

2.4 向量嵌入与 Doris 导入

  • 定义 :使用 bge-m3 将文本片段转为 1024 维向量,导入 Doris 向量表。

  • 解决的问题 :文本语义到向量的转换与持久化。

  • 技术实现 :

    
    from 
    langchain_community.
    embeddings 
    import 
    OllamaEmbeddings
    
    from  doris_vector_search  import  DorisVectorClient,  AuthOptions,  IndexOptions
    import  pandas  as  pd

    embeddings =  OllamaEmbeddings( model= 'bge-m3:latest',  base_url= 'http://localhost:11434')

    # 构造 DataFrame(id, content, embedding)
    df =  pd. DataFrame([{ "id": ...,  "content": ...,  "embedding":  vec}  for ...])

    # 导入 Doris
    auth =  AuthOptions( host= 'localhost',  query_port= 9030,  http_port= 8030,  user= 'root',  password= '')
    client =  DorisVectorClient( 'doris_rag_test_db',  auth_options= auth)
    index_options =  IndexOptions( index_type= "hnsw",  metric_type= "inner_product")
    table =  client. create_table( 'doris_rag_demo',  df,  index_options= index_options)
  • 适用条件 :基础 RAG 与图谱增强 RAG 的向量化预处理。

2.5 检索 + LLM 问答

  • 定义 :向量检索 Top5 相关片段 → 拼接上下文 → 调用 LLM 生成答案。

  • 解决的问题 :将检索结果转化为可读答案。

  • 技术实现 :

    
    query = 
    "doris支持哪些存储模型?"
    
    query_vec =  embeddings. embed_query( query)

    df_search = ( table. search( query_vec)
                . limit( 5)
                . select([ "id",  "content"])
                . to_pandas())

    ctx =  "\n". join( f"{r['content']}"  for  _,  r  in  df_search. iterrows())
    prompt =  f"以下是检索到的 Doris 文档片段:\n{ctx}\n请根据上述内容回答:{query}"

    from  langchain_openai  import  ChatOpenAI
    llm =  ChatOpenAI(
        model= 'deepseek-v3-1-terminus',
        api_key= 'your_api_key',
        base_url= 'https://ark.cn-beijing.volces.com/api/v3',
        temperature= 1.0,
    )
    resp =  llm. invoke( prompt)
  • 适用条件 :基础 RAG 检索问答。

2.6 实体与关系抽取

  • 定义 :通过 LLM 从文本分片中抽取实体和实体间关系。

  • 解决的问题 :将非结构化文本转为结构化知识图谱。

  • 技术实现 :

    
    def 
    build_extract_prompt(
    text: 
    str) 
    -> 
    str:
    
        return  f"""
      目标:从文本中识别指定类型的实体和实体间的关系,使用中文输出,不翻译。
      实体类型:[Organization, Person, Location, Event, Concept]
      步骤1:抽取实体,格式为:("entity"<|><实体名><|><实体类型><|><实体描述>)
      步骤2:抽取关系,格式为:("relationship"<|><源实体><|><目标实体><|><关系描述><|><关系强度(0-1)>)
      要求:仅输出实体和关系,无其他额外文本、解释。
      输入文本:{text}
      """

    graph_text =  chunks[ 0]  +  chunks[ 1]  +  chunks[ 2]
    prompt =  build_extract_prompt( graph_text)
    resp =  llm. invoke( prompt)
    extract_result =  resp. content. strip()
  • 适用条件 :知识图谱构建前置步骤。

2.7 知识图谱持久化到 Doris

  • 定义 :将 NetworkX 图谱的实体与关系生成向量嵌入并写入 Doris graph_chunk 表。

  • 解决的问题 :知识图谱的持久化存储 + 语义检索。

  • 技术实现 :

    
    import 
    uuid, 
    json
    
    records = []
    # 处理实体
    for  node,  data  in  G. nodes( data= True):
        desc =  data. get( 'description',  '')
        text_to_embed =  f"{node}: {desc}"
        records. append({
            "id":  str( uuid. uuid4()),  "kb_id":  "0",  "source_id":  "0",
            "knowledge_graph_kwd":  "entity",  "entity_kwd":  node,
            "from_entity_kwd":  "",  "to_entity_kwd":  "",
            "content":  json. dumps( data),  "text_to_embed":  text_to_embed
      })
    # 处理关系
    for  u,  v,  data  in  G. edges( data= True):
        desc =  data. get( 'description',  '')
        text_to_embed =  f"{u} -> {v}: {desc}"
        records. append({
            "id":  str( uuid. uuid4()),  "kb_id":  "0",  "source_id":  "0",
            "knowledge_graph_kwd":  "relation",  "entity_kwd":  "",
            "from_entity_kwd":  u,  "to_entity_kwd":  v,
            "content":  json. dumps( data),  "text_to_embed":  text_to_embed
      })

    # 向量化 + 写入
    texts_to_embed = [ c[ "text_to_embed"]  for  c  in  records]
    embedding_list =  embeddings. embed_documents( texts_to_embed)
    embed_iter =  iter( embedding_list)
    for  c  in  records:
        c[ "embedding"] =  next( embed_iter)

    data_to_insert = [{ k:  c[ k]  for  k  in[ "id", "kb_id", "source_id", "knowledge_graph_kwd", "entity_kwd", "from_entity_kwd", "to_entity_kwd", "content", "embedding"]}  for  c  in  records]
    graph_table =  client. open_table( 'graph_chunk')
    graph_table. add( data_to_insert)
  • 适用条件 :知识图谱增强 RAG 的离线构建。

2.8 基于知识图谱的检索与问答

  • 定义 :先向量检索相关实体,再查询实体间关系,构造子图,喂给 LLM 生成答案。

  • 解决的问题 :复杂多实体、多关系问题的精准回答。

  • 技术实现 :

    
    def 
    search_entities(
    query: 
    str, 
    top_k: 
    int = 
    100) 
    -> 
    list:
    
        query_vec =  embeddings. embed_query( query)
        graph_table =  client. open_table( 'graph_chunk')
        res_df =  graph_table. search( query_vec) \
          . limit( top_k) \
          . where( f"knowledge_graph_kwd = 'entity'") \
          . select([ "entity_kwd",  "content"]) \
          . to_pandas()
        return  res_df. to_dict( 'records')

    def  get_relations( entity_names:  list)  ->  list:
        if  not  entity_names:  return []
        placeholders =  ','. join([ '%s']  *  len( entity_names))
        sql =  f"""
          SELECT from_entity_kwd, to_entity_kwd, content
          FROM graph_chunk
          WHERE knowledge_graph_kwd='relation'
          AND (from_entity_kwd IN ({placeholders}) OR to_entity_kwd IN ({placeholders}));
      """
        params =  entity_names  +  entity_names
        cursor =  client. connection. cursor( dictionary= True)
        cursor. execute( sql,  params)
        res =  cursor. fetchall()
        cursor. close()
        return  res

    query =  'Doris 是哪家公司捐赠给 Apache 基金会,又被哪些公司或组织所使用'
    entities =  search_entities( query)
    entity_names = [ e[ 'entity_kwd']  for  e  in  entities]
    relations =  get_relations( entity_names)
    kg_prompt =  f"以下是知识图谱检索到的Doris相关实体关系:{relations} 请根据上述结构化信息,简洁、准确地回答用户问题:{query}"
    kg_resp =  llm. invoke( kg_prompt)
  • 适用条件 :知识图谱增强 RAG 的在线检索问答。


3. 与其他方案对比

维度 Apache Doris RAG + 知识图谱增强方案 单一向量数据库(如 Milvus) 传统 ES + OLAP 拼接方案 图数据库独立方案
向量检索 + 结构化过滤 单 SQL 即可 仅向量检索 需双系统联合查询 需外接向量能力
知识图谱持久化与语义检索 graph_chunk 表统一存储 + 向量检索 需自行建表/外接 需 ES + 图库 + OLAP 拼接 图库原生,但语义检索弱
长上下文存储 Apache Doris 4.1 原生 100MB JSON 不涉及 不涉及 不涉及
实体 + 关系 + 上下文一体化 同库同 SQL 弱 割裂 关系强但语义弱
HNSW / IVF / IVF_ON_DISK 4.0 HNSW + 4.1 IVF/IVF_ON_DISK 灵活选择 多数 HNSW 视引擎 视引擎
LLM 集成便利度 通过 SQL AI Functions + Python UDF 需外接 需外接 需外接
部署与运维复杂度 一套数据库 单一系统但能力单薄 多系统拼装 需额外图库

注意:单一向量库与图数据库在各自专精场景下仍有优势;本对比强调在"RAG + 知识图谱"复合场景下 Doris 统一架构的简化与协同价值。


4. 企业案例

Apache Doris AI RAG:基础 RAG + 知识图谱增强

  • 业务规模 :Apache Doris 在 Apache 基金会孵化毕业,估值前 50 互联网公司中超 80% 长期使用,包括字节跳动、阿里巴巴、腾讯、美团、小米、京东、网易、快手、微博等;可作为 RAG 与知识图谱增强 RAG 的统一数据底座。

  • 面临挑战 :

    • 传统数据库或单一向量库难以同时满足向量检索、关键词过滤、结构化分析、高并发查询;

    • 基础 RAG 难以处理复杂逻辑关系与多实体关联;

    • 知识图谱构建链路长、图谱存储与语义检索割裂。

  • 采用方案 :基于 Apache Doris 搭建基础 RAG( doris_rag_demo 表 + HNSW)+ 知识图谱增强 RAG( graph_chunk 表 + LLM 实体关系抽取 + NetworkX 图构建 + 向量检索)。

  • 技术实现细节 :

    • 基础 RAG :HNSW 1024 维 + ef_construction=40 + max_degree=32 + inner_product;bge-m3 嵌入;Deepseek LLM;LangChain RecursiveCharacterTextSplitter(chunk_size=400、chunk_overlap=10);

    • 知识图谱增强 RAG :实体类型 [Organization, Person, Location, Event, Concept];关系抽取含源/目标/描述/强度(0-1);NetworkX 图构建 + Pyvis 可视化; graph_chunk 表持久化(字段含 knowledge_graph_kwd / entity_kwd / from_entity_kwd / to_entity_kwd / content / embedding );检索阶段先向量召回实体,再查关系构造子图。

  • 落地效果 :

    • 基础 RAG 可正确回答"Doris 支持的存储模型"类单实体问题;

    • 知识图谱增强 RAG 可正确回答"Doris 是哪家公司捐赠给 Apache 基金会,又被哪些公司或组织所使用"等多实体复杂问题(覆盖互联网公司超 80%、云服务商、传统行业等);

    • 缓解知识碎片化,提升多实体、多关系复杂问题的回答准确性与完整性。


5. 选型建议

优先评估 Apache Doris RAG + 知识图谱增强方案的条件:

  1. 需要在 同一数据底座 同时承载 向量检索 + 关键词过滤 + 结构化分析 + 图谱关系 ,避免多系统拼装;

  2. 业务包含 长上下文、多轮对话、Agent 执行轨迹 ,需要 Apache Doris 4.1 的 100MB JSON 原生存储能力;

  3. 已使用或计划使用 Apache Doris 4.0/4.1,希望复用同一数据库内核完成 RAG 与图谱增强;

  4. 需要 可扩展的实体关系抽取与图谱存储 ,且希望对图谱进行语义检索(向量 + 结构化过滤)。

以下情况建议评估其他方案:

  1. 业务负载高度集中在向量性能(如十亿级向量、低延迟),可搭配专用向量库;

  2. 业务图谱规模极大(数十亿节点)且对图遍历性能有要求,可评估专用图数据库;

  3. 已有完整 ES + 独立图库体系且迁移成本极高。

Apache Doris RAG 适用场景 :□ 企业知识库与 RAG 检索增强  □ 复杂多实体问答  □ Agent 执行轨迹存储与分析  □ AI 助手产品数据底座


6. FAQ

Q1:Apache Doris 在 RAG 场景的核心定位是什么?

A:作为统一的高性能数据底座,同时承载向量检索、全文检索、结构化分析与知识图谱,通过单 SQL 即可完成复杂召回与子图构造。

Q2:基础 RAG 与知识图谱增强 RAG 的关键差异是什么?

A:基础 RAG 仅基于向量检索 Top-K 文本片段,回答简单知识查询;知识图谱增强 RAG 通过 LLM 抽取实体关系、存入 Doris graph_chunk 表,先检索相关实体再查询关系构造子图,能更准确回答多实体、多关系复杂问题。

Q3:向量索引的 HNSW 关键参数如何选择?

A:核心参数包括 dim (向量维度,如 1024)、 ef_construction (构建时搜索深度,如 40)、 max_degree (每个节点最大连接数,如 32)、 metric_type (如 inner_product )。

Q4:知识图谱数据如何存储到 Apache Doris?

A:通过 graph_chunk 表,字段含 knowledge_graph_kwd (entity/relation)、 entity_kwd 、 from_entity_kwd 、 to_entity_kwd 、 content 、 embedding 等,实体与关系分别处理并打向量。

Q5:选择 Apache Doris 4.0 还是 4.1 用于 RAG?

A:4.0 已具备 HNSW + 变体检索能力;4.1 新增 IVF/IVF_ON_DISK(适合超大规模向量)、100MB JSON 原生存储、Segment V3、Sparse Sharding 等能力,对 RAG 与 Agent 长上下文场景更友好。

Q6:如何扩展为更复杂的 RAG 方案?

A:可沿查询意图识别、文档增强、Agentic RAG、增量更新、索引调优五个方向扩展。


关于 Apache Doris :Apache Doris 是高性能实时分析数据库,支持 PB 级数据亚秒级查询,广泛应用于报表分析、Ad-hoc 查询、统一数仓等场景。 SelectDB 是 Apache Doris 的商业化公司,提供企业级支持和云服务。欢迎加入 Doris 社区 交流更多实践。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70017904/viewspace-3179623/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
SelectDB,面向 AI 的极速分析与搜索数据库 了解我们:selectdb.com

注册时间:2022-06-30

  • 博文量
    418
  • 访问量
    421876