Files
airport-wiki/hybrid-search.md
T

424 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 混合搜索系统
created: 2026-04-13
updated: 2026-04-15
type: integrates_with
tags: [knowledge-management, hybrid-search, bm25, vector-search, knowledge-graph]
confidence: 0.85
sources_count: 3
last_confirmed: 2026-04-13
status: active
relationships:
- target: knowledge-management/wiki-operations.md
detail: "自动化搜索触发"
---
# 🎯 混合搜索系统
基于 **LLM Wiki v2** 的可扩展搜索架构,专为机场智能化工程 wiki(当前 89 页,预计增长至 200+ 页)设计。当传统 `index.md` 目录变得不可行时,混合搜索提供三层次检索融合。
> **核心理念**:单一检索方法无法覆盖所有查询场景。关键词匹配精准但缺乏语义理解,向量搜索理解语义但可能缺乏精确匹配,图谱遍历发现隐含关系但需要结构化数据。
---
## 🏗️ 三层检索架构
### 1️⃣ BM25 关键词检索
**算法**Okapi BM25TF-IDF 的现代改进版)
**用途**:精确术语匹配、技术参数查找、缩写搜索
```python
# 伪代码实现
def bm25_search(query: str, documents: List[str], k1=1.5, b=0.75):
"""
参数:
- k1: 术语频率饱和度 (通常 1.2-2.0)
- b: 文档长度归一化 (0-1, 通常 0.75)
"""
# 1. 分词 + 词干提取
terms = stem(tokenize(query))
# 2. 计算每个文档的 BM25 分数
scores = []
for doc in documents:
score = sum(
idf(term) * (tf(term, doc) * (k1 + 1)) /
(tf(term, doc) + k1 * (1 - b + b * len(doc)/avg_doc_len))
for term in terms
)
scores.append(score)
return ranked_documents(scores)
```
**优势**
- ✅ 精确匹配技术术语(如 "InfiniBand NDR 400G"
- ✅ 支持同义词扩展(如 "GPU" → "图形处理器"
- ✅ 快速响应(毫秒级)
- ✅ 可解释性强(高亮匹配术语)
**局限**
- ❌ 无法理解语义相似性("智算中心" ≠ "数据中心"
- ❌ 对拼写错误敏感
- ❌ 无法处理复杂概念组合
**机场场景示例**
```
查询: "Tier IV 数据中心 PUE"
BM25 匹配:
- tier-iv-design.md (PUE < 1.2)
- power-and-cooling.md (PUE 计算方式)
- 机场智算中心技术方案.md (Tier IV 章节)
```
### 2️⃣ 向量语义检索
**模型**`text-embedding-3-small` (OpenAI) 或 `BGE-M3` (开源)
**维度**1536 维向量空间
**用途**:概念搜索、相似文档发现、跨语言检索
```python
# 伪代码实现
def vector_search(query: str, embeddings: Dict[str, List[float]], top_k=10):
"""
参数:
- embeddings: {page_path: [vector]}
- top_k: 返回 top K 结果
"""
# 1. 查询编码
query_vec = embed_model.encode(query)
# 2. 计算余弦相似度
similarities = []
for page_path, page_vec in embeddings.items():
sim = cosine_similarity(query_vec, page_vec)
similarities.append((page_path, sim))
# 3. 返回 top K
return sorted(similarities, key=lambda x: x[1], reverse=True)[:top_k]
```
**嵌入生成策略**
```python
# 页面内容预处理
def prepare_for_embedding(page_content: str) -> str:
"""
优化嵌入质量的预处理:
1. 提取 frontmatter 关键字段 (title, tags, type)
2. 保留正文前 2000 tokens(最重要的内容)
3. 移除代码块、表格格式(保留纯文本)
4. 标准化术语(统一缩写/全称)
"""
return processed_text
# 批量嵌入生成(每周更新)
def regenerate_embeddings():
for page in all_wiki_pages:
content = read_page(page)
text = prepare_for_embedding(content)
embedding = embed_model.encode(text)
save_embedding(page, embedding)
log("嵌入更新完成", timestamp=now())
```
**优势**
- ✅ 理解语义相似性("AI训练集群" ≈ "GPU计算农场"
- ✅ 支持模糊查询(拼写容错)
- ✅ 发现相关但无关键词重叠的内容
- ✅ 跨语言检索潜力
**局限**
- ❌ 无法精确匹配特定参数(如 "H100 功耗 700W"
- ❌ 需要定期重新计算嵌入(内容更新时)
- ❌ 计算成本较高(API 调用或本地推理)
**机场场景示例**
```
查询: "如何降低数据中心能耗"
向量匹配:
- liquid-cooling.md (液冷节能 40%)
- tier-iv-design.md (PUE 优化)
- modern-airport-trends.md (绿色机场趋势)
- prefab-modular-dc.md (模块化节能)
```
### 3️⃣ 知识图谱遍历检索
**数据源**`entities/index.md` + 页面 `relationships` 字段
**算法**:图遍历(BFS/DFS)、路径查询、社区发现
**用途**:关系发现、影响分析、生态系统查询
```python
# 伪代码实现
def graph_traversal_search(start_entity: str,
relation_type: Optional[str] = None,
max_depth: int = 3):
"""
从起点实体开始遍历知识图谱
"""
visited = set()
results = []
def dfs(entity: str, depth: int, path: List[str]):
if depth > max_depth or entity in visited:
return
visited.add(entity)
path.append(entity)
# 获取实体的所有关系
relationships = get_relationships(entity)
for rel in relationships:
if relation_type and rel.type != relation_type:
continue
# 记录发现的关系路径
results.append({
"path": path.copy() + [rel.target],
"relation": rel.type,
"confidence": rel.confidence,
"depth": depth + 1
})
# 递归遍历
dfs(rel.target, depth + 1, path.copy() + [rel.target])
dfs(start_entity, 0, [])
return results
```
**图谱查询类型**
1. **直接关系查询**`find_related("郑州航空港区机场", relation_type="deploys")`
2. **路径查找**`find_path("NVIDIA", "华为", max_depth=3)`
3. **社区发现**`find_community("aodb-core", min_confidence=0.8)`
4. **影响力分析**`find_influencers("liquid-cooling", direction="upstream")`
**优势**
- ✅ 发现隐含关系(间接连接)
- ✅ 理解系统依赖和影响链
- ✅ 支持推理查询("如果X故障,影响什么?")
- ✅ 可视化展示(关系图)
**局限**
- ❌ 依赖结构化数据质量
- ❌ 需要手动维护关系(或自动提取)
- ❌ 无法处理非实体内容(概念解释)
**机场场景示例**
```
查询: "哪些机场使用ADB SAFEGATE的AODB"
图谱遍历:
起点: ADB SAFEGATE → provides → aodb-core
遍历: aodb-core ← deploys ← [shenzhen-airport, jfk-airport, ...]
结果: [深圳机场, 纽约肯尼迪机场, ...]
```
---
## 🔄 结果融合策略
### 倒数排名融合(RRF
```python
def reciprocal_rank_fusion(bm25_results: List[str],
vector_results: List[str],
graph_results: List[str],
k: int = 60):
"""
RRF 公式: score = Σ(1 / (k + rank))
- k: 平滑参数,通常 60
- rank: 在单个列表中的排名 (1-based)
"""
# 初始化得分字典
scores = defaultdict(float)
# 处理 BM25 结果
for rank, doc in enumerate(bm25_results, 1):
scores[doc] += 1 / (k + rank)
# 处理向量结果
for rank, doc in enumerate(vector_results, 1):
scores[doc] += 1 / (k + rank)
# 处理图谱结果(可能需要转换实体→页面)
for rank, entity_path in enumerate(graph_results, 1):
# 将实体路径转换为相关页面
pages = entity_path_to_pages(entity_path)
for page in pages:
scores[page] += 1 / (k + rank) / len(pages)
# 按总得分排序
return sorted(scores.items(), key=lambda x: x[1], reverse=True)
```
### 查询类型自适应权重
| 查询类型 | BM25权重 | 向量权重 | 图谱权重 | 说明 |
|----------|----------|----------|----------|------|
| **技术参数** | 0.6 | 0.3 | 0.1 | 精确数字、规格、型号 |
| **概念解释** | 0.3 | 0.6 | 0.1 | 定义、原理、背景 |
| **关系查询** | 0.1 | 0.2 | 0.7 | 依赖、影响、连接 |
| **综合搜索** | 0.4 | 0.4 | 0.2 | 默认权重分配 |
### 去重与多样化
```python
def diversify_results(merged_results: List[Tuple[str, float]],
max_similar: float = 0.8):
"""
确保结果多样性,避免同质化
"""
diversified = []
seen_content = set()
for doc, score in merged_results:
# 计算与已选结果的相似度
max_sim = 0
for selected in diversified[:5]: # 与前5个比较
sim = content_similarity(doc, selected)
max_sim = max(max_sim, sim)
# 如果太相似,降低权重
if max_sim > max_similar:
adjusted_score = score * (1 - max_sim)
else:
adjusted_score = score
diversified.append((doc, adjusted_score))
return sorted(diversified, key=lambda x: x[1], reverse=True)
```
---
## 🚀 实施路线图
### 阶段 1:基础 BM25 + 简易向量(当前)
- ✅ Ripgrep 实现关键词搜索
- ✅ 同义词词典扩展(`search/synonyms.txt`
- 🔄 OpenAI embeddings API 调用(按需)
- 📊 搜索日志记录与分析
### 阶段 2:本地向量库 + 基础图谱(1-2周)
- 🔄 本地嵌入模型部署(`BGE-M3``text-embedding-3-small`
- 🔄 每周批量嵌入更新
- 🔄 实体关系图谱基础遍历
- 📊 搜索结果质量评估框架
### 阶段 3:完整混合搜索 + 自动化(1个月)
- 🔄 RRF 融合算法实现
- 🔄 查询分类器(自动识别查询类型)
- 🔄 图谱嵌入(Node2Vec 或 GraphSAGE
- 🔄 自动化搜索优化(基于用户反馈)
### 阶段 4:高级功能(未来)
- 🔄 多语言检索支持
- 🔄 时序搜索(基于 `updated` 日期)
- 🔄 个性化排名(基于用户历史)
- 🔄 可视化搜索界面
---
## 📋 技术栈建议
### 轻量级方案(Python 优先)
```yaml
bm25:
- whoosh 或 tantivy (Python)
- 同义词: pywsd 或 nltk.wordnet
vector:
- sentence-transformers (BGE-M3)
- 或 OpenAI API (text-embedding-3-small)
graph:
- networkx (内存图)
- 或 redisgraph (持久化)
fusion:
- 自定义 RRF 实现
```
### 生产级方案
```yaml
bm25:
- Elasticsearch 或 Typesense
vector:
- Qdrant 或 Weaviate (向量数据库)
graph:
- Neo4j 或 Amazon Neptune
fusion:
- 自定义微服务或 LangChain
```
---
## 📊 性能指标与监控
### 搜索质量指标
| 指标 | 计算方法 | 目标值 |
|------|----------|--------|
| **MRR** | Mean Reciprocal Rank | >0.6 |
| **NDCG@10** | 归一化折损累计增益 | >0.7 |
| **点击率** | 结果点击/展示 | >25% |
| **查询分类准确率** | 自动分类准确率 | >85% |
### 性能指标
| 指标 | 计算方法 | 目标值 |
|------|----------|--------|
| **P95 延迟** | 95% 查询响应时间 | <2s |
| **吞吐量** | QPS (查询/秒) | >10 |
| **缓存命中率** | 缓存结果/总查询 | >40% |
| **嵌入新鲜度** | 嵌入更新延迟 | <7天 |
### 监控仪表板
```python
# 搜索日志格式
search_log = {
"query": "Tier IV PUE 标准",
"query_type": "technical", # 自动分类
"results_count": 15,
"fusion_method": "rrf_k60",
"response_time_ms": 1240,
"components_timing": {
"bm25": 120,
"vector": 980,
"graph": 140
},
"user_feedback": None, # 点击或评分
"timestamp": "2026-04-13T10:30:00Z"
}
```
---
## 🔧 维护指南
### 每周维护任务
1. **嵌入更新**:重新计算所有页面的向量嵌入
2. **同义词更新**:根据搜索日志添加新同义词
3. **图谱验证**:检查关系一致性和置信度衰减
4. **性能分析**:分析慢查询,优化索引
### 每月优化任务
1. **权重调整**:基于用户反馈调整融合权重
2. **模型评估**:评估嵌入模型效果,考虑升级
3. **查询分析**:识别常见查询模式,优化处理
4. **容量规划**:预测增长,规划扩容
### 故障恢复
```bash
# 搜索系统故障恢复流程
1. 降级到纯 BM25 搜索
2. 禁用向量和图谱组件
3. 检查嵌入存储完整性
4. 逐步恢复各组件
5. 验证搜索结果质量
```
---
## 📚 相关文档
- [[SCHEMA.md]] - LLM Wiki v2 架构定义
- [[entities/index.md]] - 知识图谱数据源
- [[knowledge-management/wiki-operations.md]] - 自动化维护
- [[search-logs-analysis.md]] - 搜索日志分析报告
---
> **实施状态**:当前处于阶段 1(基础 BM25 + API 向量)。下一步:部署本地嵌入模型,实现每周批量更新。最后更新:2026-04-13。