RRF 算法原理
什么是 RRF?
Reciprocal Rank Fusion(倒数排名融合) 是一种多检索结果融合算法,通过倒数排名加权合并多个检索系统的结果。
核心公式:
RRF Score = Σ (1 / (k + rank_i))
rank_i: 文档在第 i 个检索系统中的排名
k: 平滑常数(通常设为 60,避免分母为 0)
为什么需要 RRF?
| | | |
|---|
| 检索方式 | 优势 | **劣势 ** | 典型场景 |
| 全文检索 | 精确关键词匹配、可解释性强 | 无法理解语义、同义词召回差 | 精确查询、专有名词 |
| 向量检索 | 语义理解、同义词召回好 | 精确匹配差、可能偏离关键词 | 语义查询、模糊搜索 |
| RRF 混合 | ✅ 结合两者优势,召回率 90%+ | 需要合理配置权重 | 综合检索需求 |
产品核心能力
-
AI Function:在 云器 Lakehouse 中可以用标准 SQL 的方式调用 Function,通过调用AI Gateway大模型,完成 AI 服务建设场景。
- 数据加工:提供 AI_EMBEDDING 算子,可以对非结构化数据加工成结构化数据存储,无需使用外部算法就能自动 embed。
- 数据检索和分析:提供AI_COMPLETE等算子,使用 SQL 就能对数据进行推理、问题总结、翻译等能力。
-
Dynamic Table:支持增量刷新模式对非结构化数据自动加工,每次只计算增量数据,有效减少重复计算,降低资源利用率。
-
向量检索:支持标准 SQL 的向量检索,用于非结构化数据的相似度搜索、场景识别等,在同一个查询中可以自由实现向量+标量的检索。
-
全文检索:通过倒排索引、分词等机制实现对非结构化数据的高效检索,支持关键词匹配、短语检索等丰富的检索方式。
实施步骤
步骤 1:创建基础数据表
CREATE TABLE documents (
doc_id BIGINT PRIMARY KEY,
title STRING,
content STRING,
author STRING,
category STRING,
publish_time STRING,
update_time STRING,
word_count INT,
doc_type STRING -- article/video/audio/product
)COMMENT '文档元数据表';
步骤 2:创建全文检索索引
-- 为内容创建倒排索引(全文检索)
CREATE INVERTED INDEX idx_content_fulltext ON TABLE documents(content)
COMMENT '内容全文检索索引'
PROPERTIES( 'analyzer'='chinese','mode'='smart');
--为标题创建倒排索引
CREATE INVERTED INDEX idx_title_fulltext ON TABLE documents(title)
COMMENT '标题全文检索索引'
PROPERTIES('analyzer'='chinese','mode'='smart');
-- 验证索引
SHOW INDEX FROM documents;
步骤 3:创建向量嵌入动态表(自动处理)
-- 创建动态表:自动为新文档生成向量嵌入
CREATE OR REPLACE DYNAMIC TABLE document_embeddings(
doc_id BIGINT,
title_embedding VECTOR(FLOAT, 1024),
content_embedding VECTOR(FLOAT, 1024),
embedding_model STRING,
embedding_version STRING,
created_time TIMESTAMP,
-- 高精度场景配置(适用于对准确性要求高的 AI 应用)
INDEX high_precision_idx(title_embedding) USING VECTOR
PROPERTIES(
'scalar.type' = 'f32',
'distance.function' = 'cosine_distance',
'm' = '32', -- 增加邻居数提升精度
'ef.construction' = '256', -- 增加候选集提升质量
'compress.codec' = 'zstd' -- 启用压缩节省空间
),
-- 高性能场景配置(适用于对速度要求高的实时应用)
INDEX high_speed_idx(content_embedding) USING VECTOR
PROPERTIES(
'scalar.type' = 'f16',
'distance.function' = 'l2_distance',
'm' = '32', -- 增加邻居数提升精度
'ef.construction' = '256', -- 增加候选集提升质量
'compress.codec' = 'zstd' -- 启用压缩节省空间
)
)COMMENT '自动向量嵌入生成表'
PROPERTIES('data_lifecycle'='30') REFRESH INTERVAL 5 MINUTE VCLUSTER default_ap
AS SELECT d.doc_id,
-- 生成标题向量(使用 AI_EMBEDDING 函数)
AI_EMBEDDING(
'endpoint:text-embedding-v4',
d.title,
JSON '{"input": "text","embedding.dimension": "1024"}'
) as title_embedding,
-- 生成内容向量(截取前 8000 字符)
AI_EMBEDDING(
'endpoint:text-embedding-v4',
LEFT(d.content, 8000),
JSON '{ "input": "text", "embedding.dimension": "1024" }'
) as content_embedding,
'text-embedding-v4' as embedding_model,
'v4' as embedding_version,
CURRENT_TIMESTAMP() as created_time
FROM documents d
WHERE d.content IS NOT NULL AND LENGTH(d.content) > 0;
AI_EMBEDDING 函数语法说明:
AI_EMBEDDING( 'endpoint:端点名称', -- 必需:模型端点
input_text, -- 必需:输入文本(可以是字段)
JSON '{ -- 可选:模型超参数
"input": "text",
"embedding.dimension": "1024"
}'
)
动态表语法说明:
-- 动态表标准语法(直接 SELECT,不需要 INSERT INTO)
CREATE DYNAMIC TABLE table_name
COMMENT '描述'
PROPERTIES('data_lifecycle'='天数')
REFRESH INTERVAL 时间间隔 VCLUSTER 集群名称
AS SELECT ...;
步骤 4:实现 RRF 混合检索查询
-- RRF 混合检索查询
WITH
-- 全文检索结果
fulltext_search AS (
SELECT
doc_id,
title,
content,
category,
publish_time,
-- 全文检索分数(基于关键词匹配度)
ROW_NUMBER() OVER (ORDER BY SCORE() DESC) as fulltext_rank
FROM documents
WHERE multi_match(title,content, '数据 数据资产 数据质量 数据血缘', str_to_map('analyzer:chinese,minimum_should_match:67%'))
LIMIT 100
)
-- 向量检索结果
,vector_search AS (
SELECT
d.doc_id,
d.title,
d.content,
d.category,
d.publish_time,
-- 向量相似度分数
COSINE_DISTANCE(
e.content_embedding,
AI_EMBEDDING(
'endpoint:text-embedding-v4',
'现代大数据平台的架构设计原则,包括数据采集、存储、计算和服务层',
JSON '{
"input": "query",
"embedding.dimension": "1024"
}')) as vector_score,
ROW_NUMBER() OVER (ORDER BY COSINE_DISTANCE(
e.content_embedding,
AI_EMBEDDING(
'endpoint:text-embedding-v4',
'现代大数据平台的架构设计原则,包括数据采集、存储、计算和服务层',
JSON '{
"input": "query",
"embedding.dimension": "1024"
}')) ASC
) as vecto_rank
FROM documents d
JOIN document_embeddings e ON d.doc_id = e.doc_id
WHERE d.content IS NOT NULL
LIMIT 100
),
-- RRF 分数计算
rrf_calculation AS (
SELECT
COALESCE(f.doc_id, v.doc_id) as doc_id,
COALESCE(f.title, v.title) as title,
COALESCE(f.content, v.content) as content,
COALESCE(f.category, v.category) as category,
COALESCE(f.publish_time, v.publish_time) as publish_time,
v.vector_score,
f.fulltext_rank,
v.vector_rank,
-- RRF Score 计算
(1.0 / (60 + COALESCE(f.fulltext_rank, 1000))) +
(1.0 / (60 + COALESCE(v.vector_rank, 1000))) as rrf_score
FROM fulltext_search f
FULL OUTER JOIN vector_search v ON f.doc_id = v.doc_id
)
-- 最终结果
SELECT
doc_id,
title,
content,
category,
publish_time,
vector_score,
fulltext_rank,
vector_rank,
rrf_score,
-- 排名解释
CASE WHEN fulltext_rank IS NOT NULL AND vector_rank IS NOT NULL THEN '混合命中'
WHEN fulltext_rank IS NOT NULL THEN '仅全文命中'
WHEN vector_rank IS NOT NULL THEN '仅向量命中'
ELSE '未知'
END as hit_type
FROM rrf_calculation
ORDER BY rrf_score DESC
LIMIT 20;