当前 RAG 系统使用 BM25 关键词检索,存在核心缺陷:搜索"海上交通安全法与水污染防治法"时检索到行政检查清单而非法律原文,因为 BM25 只看关键词共现频率,无法理解语义。用户提议引入 qwen-embedding-v4 + qwen-rerank-8B + RRF 混合检索,预期显著提升检索准确性。
查询
├─► BM25 检索 (现有 search_engine.py) → 排名列表 A
├─► 向量检索 (qwen-embedding-v4) → 排名列表 B
└─► RRF 融合 (k=60) → top-20 候选
└─► Rerank (qwen-rerank-8B) → 过滤 threshold=0.5 → top-5 结果
| 文件 | 用途 |
|---|---|
qaagent67/scripts/search_engine_v2.py |
混合检索引擎 (BM25+向量+RRF+Rerank) |
qaagent67/scripts/build_vector_index.py |
向量索引构建 (重新分块+调 embedding API) |
qaagent67/scripts/rebuild_index_v2.py |
BM25 索引重建 (适配新分块参数) |
| 文件 | 改动 |
|---|---|
qaagent67/agent-config.yml |
新增 rag.hybrid/embedding/rerank 配置段 |
qademo/app.py |
改 1 行 import: from search_engine → from search_engine_v2 |
| 文件 | 说明 |
|---|---|
qaagent67/scripts/search_engine.py |
现有 BM25 引擎,被 v2 内部调用 |
qaagent67/scripts/rebuild_index.py |
现有索引构建,保留为参考 |
knowledge/maritime/rag_index.pkl |
现有 BM25 索引,保留为 fallback |
knowledge/maritime/rag_keywords.pkl |
现有关键词索引,保留为 fallback |
分块参数:
\n\n[TABLE_START]...[TABLE_END])流程:
rag_vectors_v2.npy (numpy float32 [N, dim]) + rag_vectors_meta_v2.pklrag_index_v2.pkl + rag_keywords_v2.pklAPI 调用:
POST https://api.siliconflow.cn/v1/embeddings
{"model": "Pro/Qwen/Qwen3-Embedding-0.6B", "input": ["text1", ...], "encoding_format": "float"}
预估:
核心函数:
def search(query, top_k=5):
# 1. BM25 检索 (调现有 search_engine.search)
bm25_results = bm25_search(query, top_k=20)
# 2. 向量检索 (embed query → cosine similarity)
query_vec = _embed_query(query)
vector_results = _vector_search(query_vec, top_k=20)
# 3. RRF 融合
fused = _rrf_fuse(bm25_results, vector_results, k=60) # top-20
# 4. Rerank
reranked = _rerank(query, fused[:20])
# 5. 过滤 threshold + 返回 top-k
return [r for r in reranked if r['score'] >= 0.5][:top_k]
降级策略:
返回格式: 与现有 search() 完全一致: {source, chunk_id, score, text}
rag:
enabled: true
collection: maritime_rag
chunkSize: 1024
chunkOverlap: 200
chunkSeparator: "\n\n"
topK: 5
hybrid:
enabled: true
rrfK: 60
rerankCandidates: 20
similarityThreshold: 0.5
embedding:
model: Pro/Qwen/Qwen3-Embedding-0.6B
baseUrl: https://api.siliconflow.cn/v1
apiKeyEnv: SILICONFLOW_API_KEY
batchSize: 16
rerank:
model: Pro/Qwen/Qwen3-Reranker-0.6B
baseUrl: https://api.siliconflow.cn/v1
apiKeyEnv: SILICONFLOW_API_KEY
topN: 5
# Before:
from search_engine import search
# After:
try:
from search_engine_v2 import search
except ImportError:
from search_engine import search
| 文件 | 格式 | 大小估算 |
|---|---|---|
rag_vectors_v2.npy |
numpy float32 [N, dim] | ~225 MB (55K×1024×4) |
rag_vectors_meta_v2.pkl |
pickle list of (source, chunk_id, text) | ~50 MB |
rag_index_v2.pkl |
pickle BM25 索引 | ~30 MB |
rag_keywords_v2.pkl |
pickle 关键词倒排 | ~20 MB |
不依赖向量数据库 — numpy brute-force cosine similarity 对 55K chunks 只需 <100ms。
仅新增 numpy,已在 Docker 镜像的 pip install 中。无需 chromadb/faiss 等。
# 构建索引 (一次性)
docker exec qademo python3 /app/agentexample/qaagent67/scripts/build_vector_index.py
# 重启 Web 服务 (自动使用 v2)
docker restart qademo
环境变量: SILICONFLOW_API_KEY=<your-key> (申请: https://cloud.siliconflow.cn/account/ak )
| 方面 | 影响 |
|---|---|
| 现有 BM25 代码 | 不动,被 v2 内部调用 |
| Web 前端 | 无改动 |
| Wiki 模式 | 不受影响 |
| 查询延迟 | +200-500ms (embed+rerank API) |
| 首次加载 | ~2s (numpy mmap) vs 6s (pickle BM25) |
| 索引构建 | 一次性 ~6 分钟 + ~$0.30 |
| 每次查询成本 | ~$0.001 (1次embed + 1次rerank) |
python search_engine_v2.py "海上交通安全法与水污染防治法" — 应检索到法律原文