今天没正儿八经学习,昨晚熬夜看了森载大战,一点都不好看(悲)。早上睡了五个小时起来了,要倒一下生物钟,因为明天要早起赶高铁回家。
lc:146LRU缓存,python常用的api是move_to_end ,last = False 是LRU, True则是MRU
默写MHA一次。
茶余饭后冲浪的时候粗浅了解了一下RAG,发现很多实现场景其实用的是纯文本交互,因为大模型本身就擅长从纯文本内容里推理归纳总结。因为是纯文本,RAG检索用的embedding模型可以和推理模型完全不同,它把文本 → 向量,用于在知识库里检索,Embedding 的目标是“语义相似度”。
🌍 世界 A:向量检索世界
- 语言:向量
- 模型:bge / e5 / text-embedding
- tokenizer:只服务 embedding 本身
- 目标:找相似内容
🌍 世界 B:生成世界
- 语言:token
- 模型:DeepSeek / Qwen / GPT
- tokenizer:生成质量相关
- 目标:组织语言
这两个世界只通过“文本字符串”交汇一次。 在工程上,Embedding 模型的选择只需要满足:
- 与你的语料语言匹配 - 中文 → bge-large-zh / m3
- Query 与 Document 使用同一个 embedding
- 向量维度固定 为“检索优化训练”(不是通用 sentence embedding) embedding 模型是:
- 只做 encoding 的 Transformer
- 前向推理一次就结束 它是Inference-only encoder model哦,并不是GPT架构,Encoder 比 decoder 更适合 embedding,是因为它被设计成“为整段输入建立全局、对称、位置无关的表示”,而 decoder 的设计目标是“为下一个 token 建立条件分布”。embedding 需要“位置不敏感”,decoder 正好相反。
它的训练目标决定了“头”在学什么
Encoder embedding 模型
- 对比学习
- ranking loss
- sentence-level supervision
训练目标直接约束:
“整句向量是否表达语义相似性”
工业界的共识是:
LLM embedding = 可用,但不优雅、不稳、不便宜
cross-encoder 适合 rerank,而 bi-encoder 适合 recall
结论
recall 要“快且不漏”,rerank 要“准且可贵”。
Bi-encoder(适合 recall)query / doc 完全独立编码 👉 粗语义过滤器
Cross-encoder(适合 rerank)query 和 doc 在 attention 中全交互 👉 精语义判官
embedding 空间会出现各向异性(anisotropy)
现象
- embedding 大量集中在一个窄锥体
- 向量彼此夹角很小
- cosine similarity 区分度下降
原因
Transformer 的残差与 LayerNorm
- 多层残差叠加 → 向量均值漂移
- LayerNorm 让不同输入“形态相似”
训练目标不惩罚“塌缩”
对比学习只关心:
正样本更近
负样本更远
不关心全空间是否均匀
高频语义主导
常见抽象语义(“描述、问题、事情”)
主成分被强力共享
在embedding model里pooling 比想象的重要
embedding 模型的监督是:
sentence-level
loss 直接作用在 pooling 后的向量 👉 pooling 是 loss 的直接受体
instruction-tuned encoder 反而可能变差
把 encoder 从:
“压缩语义”
推向:
“对指令作出有用反应”
从而导致了“ 输出对 prompt 敏感、风格 / 语气 / 任务指向性、语义被条件化
看完了之后想了一下,发现了RAG的核心难点在于:词向量不能太密集,毕竟我们是在比较相似度,如果太密集了就没有区分度了,操作上是把prompt输入映射成一个点,然后把doc和它在同一空间最相似的内容拉取出来,这里都还好,但我们得到的可能是recall得到的多个相似内容,它们还需要排列重要度的rerank,要恢复原有doc中的细节结构,cross-encoder快速判断相似文本和prompt的联系紧密程度,它一般不用于recall。不是因为它不准,而是因为它太“贵”。
- 每个 (q, d) 都要跑一次 encoder
- O(N) 前向
- 无法预计算
- 无法 ANN 所以它被放在 top-k 小集合上。