前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
https://www.captainbed.cn/north
文章目录
混合检索(Hybrid Search)是结合多种检索技术的综合搜索方法,它通过整合不同检索模型的优势来提升信息获取的全面性和准确性。在基于大模型的应用开发中,混合检索已成为解决复杂信息需求的关键技术。
一、混合检索的本质与构成
1.1 混合检索的基本定义
混合检索是指同时使用**稠密检索(Dense Retrieval)和稀疏检索(Sparse Retrieval)**两种范式,并有机融合其结果的检索方法:
- 稠密检索:基于神经网络的嵌入模型(如BERT、GPT等),将查询和文档映射到高维向量空间,通过向量相似度匹配
- 稀疏检索:基于传统的信息检索方法(如BM25、TF-IDF等),依赖词频统计和精确词汇匹配
1.2 典型混合架构
二、混合检索解决的核心问题
2.1 单一检索模式的局限性
问题类型 | 稠密检索弱点 | 稀疏检索弱点 |
---|---|---|
专业术语 | 可能混淆语义相近术语 | 精确匹配专业术语 |
长尾查询 | 对罕见查询表现好 | 对未见词项失效 |
语义理解 | 擅长同义/转述理解 | 无法理解语义变化 |
精确匹配 | 可能忽略关键字符 | 保持字符级精确 |
训练依赖 | 需要大量训练数据 | 无需训练数据 |
2.2 混合检索的具体解决方案
-
术语精确性与语义泛化的平衡
- 案例:医疗领域同时检索"心肌梗塞"(专业术语)和"心脏病发作"(日常表达)
-
新出现词汇的应对
- 解决方案:稀疏检索处理新词,稠密检索处理相关概念
-
多语言混合场景
- 实现:BM25处理原文匹配,向量模型处理跨语言语义
-
多模态搜索需求
- 架构:文本稀疏检索+跨模态稠密检索
-
领域自适应挑战
- 方法:通用稠密模型+领域定制关键词扩展
三、技术实现方案
3.1 基础混合实现
from rank_bm25 import BM25Okapi
from sentence_transformers import SentenceTransformer
import numpy as np
class HybridRetriever:
def __init__(self, documents):
self.documents = documents
# 初始化稀疏检索
tokenized_docs = [doc.split() for doc in documents]
self.bm25 = BM25Okapi(tokenized_docs)
# 初始化稠密检索
self.encoder = SentenceTransformer('all-MiniLM-L6-v2')
self.doc_embeddings = self.encoder.encode(documents)
def search(self, query, alpha=0.5, top_k=5):
# 稀疏检索
tokenized_query = query.split()
bm25_scores = self.bm25.get_scores(tokenized_query)
# 稠密检索
query_embedding = self.encoder.encode(query)
dense_scores = np.dot(self.doc_embeddings, query_embedding)
# 分数归一化
bm25_scores_norm = (bm25_scores - np.min(bm25_scores)) / (np.max(bm25_scores) - np.min(bm25_scores))
dense_scores_norm = (dense_scores - np.min(dense_scores)) / (np.max(dense_scores) - np.min(dense_scores))
# 混合分数
combined_scores = alpha * dense_scores_norm + (1 - alpha) * bm25_scores_norm
# 获取Top K结果
top_indices = np.argsort(combined_scores)[-top_k:][::-1]
return [(self.documents[i], combined_scores[i]) for i in top_indices]
# 使用示例
documents = [
"RAG技术结合了检索和生成两种方法",
"BM25是基于词频的经典检索算法",
"混合检索整合了稠密和稀疏检索的优势"
]
retriever = HybridRetriever(documents)
results = retriever.search("如何改进RAG中的检索模块?")
for doc, score in results:
print(f"Score: {
score:.3f} | Doc: {
doc[:50]}...")
3.2 动态权重调整策略
def dynamic_hybrid_search(query, documents, query_analyzer):
# 查询特征分析
features = query_analyzer.analyze(query)
# 根据查询特征动态调整权重
if features['is_technical'] and features['term_specificity'] > 0.8:
alpha = 0.3 # 偏向稀疏检索
elif features['semantic_complexity'] > 0.7:
alpha = 0.7 # 偏向稠密检索
else:
alpha = 0.5 # 平衡权重
# 执行混合检索
return HybridRetriever(documents).search(query, alpha=alpha)
class QueryAnalyzer:
def __init__(self, technical_terms):
self.technical_terms = technical_terms
def analyze(self, query):
tokens = query.lower().split()
return {
'is_technical': len(set(tokens) & self.technical_terms) > 0,
'term_specificity': len(set(tokens)) / len(tokens), # 术语密度
'semantic_complexity': min(1.0, len(query) / 30) # 查询长度标准化
}
# 使用示例
technical_terms = {
'rag', 'bm25', '检索', '生成', '算法'}
analyzer = QueryAnalyzer(technical_terms)
results = dynamic_hybrid_search("RAG中BM25算法的参数调优", documents, analyzer)
四、进阶混合架构
4.1 多阶段混合流程
4.2 基于LLM的查询路由
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
class IntelligentRouter:
def __init__(self, llm):
self.llm = llm
self.template = """分析以下查询最适合的检索方式:
查询: {query}
可选项:
1. 稀疏检索 - 适合术语精确、关键词明确的查询
2. 稠密检索 - 适合语义复杂、需要理解的查询
3. 混合检索 - 平衡情况
请只返回数字1/2/3,不要包含其他内容。选择:"""
self.prompt = PromptTemplate.from_template(self.template)
self.chain = LLMChain(llm=llm, prompt=self.prompt)
def route(self, query):
decision = self.chain.run(query=query)
return int(decision.strip())
# 使用示例
router = IntelligentRouter(llm)
decision = router.route("transformer模型的注意力机制实现")
print(f"检索路由决策: {
['稀疏','稠密','混合'][decision-1]}")
五、工程实践关键点
5.1 性能优化方案
-
分层检索架构:
def layered_search(query, documents): # 第一层:快速稀疏检索 bm25 = BM25Okapi([doc.split() for doc in documents]) sparse_ids = get_top_k(bm25, query, k=1000) # 第二层:精确稠密检索 candidate_docs = [documents[i] for i in sparse_ids] embeddings = encoder.encode(candidate_docs) query_embedding = encoder.encode(query) scores = np.dot(embeddings, query_embedding) # 返回最终结果 return sort_and_select(candidate_docs, scores, k=10)
-
缓存策略:
- 查询嵌入缓存
- 高频结果缓存
- 文档分块预嵌入
5.2 行业特定解决方案
金融领域实现示例:
class FinancialRetriever:
def __init__(self, reports, sec_filings):
self.general_retriever = HybridRetriever(reports)
self.legal_retriever = BM25Okapi(
[self._preprocess_legal(d) for d in sec_filings])
def _preprocess_legal(self, text):
# 法律文档特殊预处理
return remove_boilerplate(text).upper()
def search(self, query):
# 并行检索
general_results = self.general_retriever.search(query)
legal_query = expand_legal_terms(query)
legal_results = self.legal_retriever.search(legal_query)
# 特殊合并逻辑
return self._merge_results(general_results, legal_results)
六、评估与调优
6.1 评估指标体系
指标类型 | 评估指标 | 测量方法 |
---|---|---|
相关性 | nDCG@K | 人工标注相关性分级 |
覆盖率 | Recall@K | 已知相关文档检出率 |
多样性 | ILD | 结果间相似度倒数 |
时效性 | Freshness | 新内容检索成功率 |
延迟 | P99 Latency | 99百分位响应时间 |
6.2 自动调参框架
from sklearn.model_selection import ParameterGrid
def tune_hybrid_weights(retriever, queries, ground_truth):
param_grid = {
'alpha': np.linspace(0, 1, 11),
'top_k': [5, 10, 20]
}
best_score = -1
best_params = {
}
for params in ParameterGrid(param_grid):
total_score = 0
for query, gt in zip(queries, ground_truth):
results = retriever.search(query, **params)
total_score += evaluate(gt, results)
if total_score > best_score:
best_score = total_score
best_params = params
return best_params
# 使用示例
# best = tune_hybrid_weights(retriever, test_queries, test_gt)
七、前沿发展方向
-
神经符号混合系统:
- 结合符号推理与神经检索
- 示例:知识图谱+向量检索联合系统
-
生成式检索:
class GenerativeRetriever: def retrieve(self, query): # 首先生成潜在相关文档描述 candidates = llm.generate( f"根据查询'{ query}'生成5个可能相关的文档片段描述") # 然后检索真实匹配文档 return vector_db.similarity_search(candidates)
-
多模态混合:
- 同时处理文本、图像、表格等多模态数据
- 跨模态对齐的混合表示
-
自适应混合:
- 在线学习权重调整
- 用户反馈驱动的检索策略优化
混合检索作为大模型时代的关键基础设施,正在持续演进以应对日益复杂的信息需求。通过精心设计的混合策略,开发者可以在准确率、召回率和系统效率之间找到最佳平衡点,为上层大模型应用提供更优质的知识供给。