QAnything 阅读优化策略03——查询转换

查询转换(Query Transformation)

查询转换是将用户查询从文本形式转化为检索引擎能处理的格式(如 embedding 向量),同时做必要的清洗和保护。这是让"人类语言"适配"机器引擎"的关键桥梁。


一、是什么

查询转换是将用户查询从文本形式转化为检索引擎能处理的格式(如 embedding 向量),同时做必要的清洗和保护。

核心输入 :改写后的检索查询

核心输出:归一化的 embedding 向量 + 保护后的查询文本


二、为什么重要

检索引擎不认识"人类语言",它只认识向量。

转换质量直接影响检索质量:

  • 图片标记 ![figure] 会干扰 embedding 模型
  • 过长的 query 会导致 Rerank 模型截断
  • 不同组件需要不同的 Token 计数精度

与传统方案的对比

优化点 传统方案 传统方案的问题 QAnything 方案 优势
向量化 平均池化(mean pooling) 所有 token 平均,重要信息被稀释 CLS token 提取 [:,0] 全局语义更聚焦
归一化 不归一化 余弦相似度计算需要除法,长向量主导排序 L2 归一化 余弦相似度 = 点积,加速计算
图片处理 原样发送 ![figure](xxx.jpg) 干扰语义 发送前过滤图片标记 检索向量更纯净
Token 计数 统一用一个 tokenizer tiktoken 计 100 token,实际可能 120 三级 tokenizer + 安全余量 各组件精度匹配
推理框架 PyTorch 直接推理 推理慢,部署体积大,无算子融合 ONNX Runtime + 全图优化 推理速度提升 2-3x
分数输出 原始 logits(无界) 阈值难设,不可解释 Sigmoid + 线性拉伸 0~1 可解释,区分度高

三、怎么做

3.1 Embedding 向量化 + L2 归一化

问题:文本需要转为向量才能在 Milvus 中检索。

方案:提取 CLS token 作为全局语义表示,然后 L2 归一化。

python 复制代码
# Embedding ONNX 模型推理
embedding = outputs_onnx[0][:, 0]  # 提取 CLS token(全局语义)

# L2 归一化:使所有向量落到单位球面
norm_arr = np.linalg.norm(embedding, axis=1, keepdims=True)
embeddings_normalized = embedding / norm_arr

归一化的价值

  • 归一化后余弦相似度 = 点积,加速后续相似度计算
  • 所有向量长度一致,避免"长向量主导排序"的问题

为什么用 CLS token

  • BERT 类模型的 [:, 0] token 经过自注意力聚合,代表整句话的全局语义
  • 比平均池化更能捕捉句子的核心含义

3.2 图片引用过滤

问题 :查询中的 ![figure](xxx.jpg) 会干扰 Embedding 模型的语义理解。

方案:发送前过滤掉图片和公式标记。

python 复制代码
# Embedding 客户端:发送前过滤
def _process_query(query):
    return '\n'.join([line for line in query.split('\n')
                      if not line.strip().startswith('![figure]')
                      and not line.strip().startswith('![equation]')])

为什么不在索引阶段过滤

  • 索引阶段的图片引用是文档内容的一部分
  • 但查询阶段用户不会主动写图片标记,这些通常是系统拼接进来的

3.3 三级 Tokenizer 精度体系

问题:不同组件对 token 计数的精度要求不同,用错 tokenizer 会导致切分不准或预算超支。

Tokenizer 使用场景 为什么用它
tiktoken (GPT) LLM Token 预算计算 直接影响 API 成本,需要精确
embedding_tokenizer 文件切分判断 必须与 Embedding 模型的 max_length 对齐
rerank_tokenizer Rerank 资格判断 必须与 Rerank 模型的 max_length 对齐
python 复制代码
# LLM Token 估算:额外加安全余量
total_tokens *= 1.1   # tiktoken 精度较高,加 10%
total_tokens *= 1.2   # 如果用 cl100k_base 兜底(中文模型偏差大),加 20%

安全余量的原因

  • tiktoken 是 GPT 专用 tokenizer,与国产 LLM(如 Qwen)有偏差
  • cl100k_base 是通用 tokenizer,中文场景偏差更大
  • 加余量是为了防止实际 token 超过预算

3.4 Rerank 查询长度保护

问题:Rerank 模型 max_length = 512,如果 query 太长就没有空间放 doc。

方案:query > 300 token 时跳过 Rerank,给 doc 留出 ~200 token 空间。

python 复制代码
# 三个条件全部满足才执行 Rerank
if rerank and len(source_documents) > 1 and num_tokens_rerank(query) <= 300:
    source_documents = await self.rerank.arerank_documents(...)

为什么是 300 而不是 512

  • Rerank 输入 = query + doc,512 是总长度
  • 给 doc 留 200 token 空间,防止截断

3.5 ONNX Runtime 推理加速

问题:PyTorch 推理速度慢,部署体积大。

方案:使用 ONNX Runtime 进行模型推理。

python 复制代码
sess_options = SessionOptions()
sess_options.graph_optimization_level = GraphOptimizationLevel.ORT_ENABLE_ALL  # 全图优化
# 自动线程调度 + GPU/CPU 自适应
providers = ['CUDAExecutionProvider', 'CPUExecutionProvider']

优化项

  • 算子融合:将多个小算子合并为一个大算子
  • 常量折叠:编译期计算常量表达式
  • 自动线程调度:根据 CPU 核心数分配线程
  • 设备自适应:自动选择 GPU 或 CPU

3.6 Rerank Sigmoid 分数校准

问题:交叉编码器输出 logits(无界值),需要映射为 0~1 之间的可解释分数。

python 复制代码
def sigmoid(x):
    scores = 1 / (1 + np.exp(-x))                       # 标准 sigmoid → (0, 1)
    scores = np.clip(1.5 * (scores - 0.5) + 0.5, 0, 1) # 线性拉伸 → 增强区分度
    return scores

线性拉伸的作用

复制代码
标准 sigmoid 输出:
0.48  0.50  0.52  0.55  → 区分度低,难以设定阈值

拉伸后:
0.47  0.50  0.53  0.575 → 高分更高,低分更低,区分度增强

四、解决的问题汇总

手段 解决的问题
Embedding 归一化 余弦相似度计算效率
图片引用过滤 无效 token 干扰语义
三级 Tokenizer 不同组件精度需求不同
Rerank 长度保护 Rerank 模型输入截断
ONNX 加速 推理速度慢
Sigmoid 校准 分数无界不可解释
相关推荐
荆棘鸟智能33 分钟前
城市感知设备怎么统一接入?从多协议网关到设备模型的中间件架构设计
人工智能·算法·边缘计算
INGNIGHT4 小时前
270 · 电话号码的字母组合II(Trie)
linux·算法
2401_839080545 小时前
C++常见八股
数据结构·c++·算法
青山是哪个青山5 小时前
LeetCode 188:买卖股票的最佳时机 IV
算法
mikuyyds5 小时前
geo-toolbox 插件算法解析:RUSLE 与 MUSLE 的工程化落地
算法·rust·gis
a187927218315 小时前
【算法】树(二):队列与祖先——BFS 骨架三配件、短路透传与合流
算法·leetcode·二叉树··bfs·算法讲解·树遍历
syagain_zsx6 小时前
算法基础篇 · 03 枚举(C++ 题解)
c++·算法·二进制·枚举
weixin_307779136 小时前
C++代码实现MATLAB中的ode23tb函数功能
开发语言·c++·算法·matlab
我是章汕呐7 小时前
地级市能源消耗量及消耗强度数据【2006-2023年】平衡面板
人工智能·经验分享·算法·回归
charliejohn7 小时前
计算机考研 408 数据结构 堆的插入与删除 堆排序
算法