全文检索与向量混合搜索最佳实践

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;

联系我们
预约咨询
微信咨询
电话咨询