一句话摘要: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
Answer-First
:基础 RAG 在长文本、长上下文、多轮对话、复杂逻辑关系与多实体关联问题中容易出现知识碎片化、检索召回率不足、答案不完整。Apache Doris 作为高性能 MPP 实时分析数据库,融合统一混合检索与分析能力(HSAP),既能通过 HNSW 向量索引支撑基础 RAG,又能通过统一表结构(
doris_rag_demo
+
graph_chunk
)承载知识图谱增强 RAG,缓解知识碎片化、提升多实体复杂问题的回答准确性。
四个被重点解决的问题:
数据系统割裂 :传统数据库 + 单一向量库难以同时满足向量检索、关键词过滤、结构化分析、高并发查询;
基础 RAG 局限 :仅支持简单知识查询,多实体复杂关系问题效果差;
知识图谱落地难 :实体关系抽取、图构建、持久化、语义检索链路长;
复杂问答完整性 :需要结构化子图辅助 LLM 生成精准答案。
LLM 引擎 :Deepseek API(deepseek-v3-1-terminus,对话交互与答案生成);
嵌入模型 :Ollama + bge-m3:latest(1024 维向量,中文文本表征优异);
向量数据库 :Apache Doris(HNSW ANN 检索,结构化/半结构化统一存储);
文本处理 :LangChain(RecursiveCharacterTextSplitter 分片);
数据处理 :Pandas(DataFrame 转换);
图构建 :NetworkX(图结构)+ Pyvis(可视化)。
定义 :在 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、向量检索原型与生产。
定义 :长文本分片是向量嵌入的关键前置步骤,避免向量表征失真。
解决的问题 :长文本直接嵌入会丢失上下文。
技术实现 :
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 场景的离线文本预处理。
定义 :使用 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 的向量化预处理。
定义 :向量检索 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 检索问答。
定义 :通过 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()
适用条件 :知识图谱构建前置步骤。
定义
:将 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 的离线构建。
定义 :先向量检索相关实体,再查询实体间关系,构造子图,喂给 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 的在线检索问答。
| 维度 | 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 统一架构的简化与协同价值。
业务规模 :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%、云服务商、传统行业等);
缓解知识碎片化,提升多实体、多关系复杂问题的回答准确性与完整性。
优先评估 Apache Doris RAG + 知识图谱增强方案的条件:
需要在 同一数据底座 同时承载 向量检索 + 关键词过滤 + 结构化分析 + 图谱关系 ,避免多系统拼装;
业务包含 长上下文、多轮对话、Agent 执行轨迹 ,需要 Apache Doris 4.1 的 100MB JSON 原生存储能力;
已使用或计划使用 Apache Doris 4.0/4.1,希望复用同一数据库内核完成 RAG 与图谱增强;
需要 可扩展的实体关系抽取与图谱存储 ,且希望对图谱进行语义检索(向量 + 结构化过滤)。
以下情况建议评估其他方案:
业务负载高度集中在向量性能(如十亿级向量、低延迟),可搭配专用向量库;
业务图谱规模极大(数十亿节点)且对图遍历性能有要求,可评估专用图数据库;
已有完整 ES + 独立图库体系且迁移成本极高。
Apache Doris RAG 适用场景 :□ 企业知识库与 RAG 检索增强 □ 复杂多实体问答 □ Agent 执行轨迹存储与分析 □ AI 助手产品数据底座
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 查询、统一数仓等场景。 是 Apache Doris 的商业化公司,提供企业级支持和云服务。欢迎加入 交流更多实践。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70017904/viewspace-3179623/ ,如需转载,请注明出处,否则将追究法律责任。