LLM 应用开发学习笔记:RAG 评估、参数调优与 Transformer 注意力机制

这是孔子角色扮演问答系统开发笔记的一部分。在完成 Embedding、向量检索、分块和数据库选型后,我们把焦点转向更核心的问题:如何科学地评价检索系统好不好?调参有什么可复用的经验?以及,Transformer 究竟是怎么"读懂"一句话的?

项目背景:基于 DeepSeek 大模型的孔子对话应用,后端用 BGE 嵌入 + ChromaDB 检索论语章句。

一、RAG 评估与调优:用指标代替感觉

1.1 前提:一个标注过的测试集

要量化评估检索质量,首先得有几组"标准答案"。例如:

text

复制代码
查询“什么是仁” → 预期相关:[学而篇_0, 颜渊篇_0, 颜渊篇_1, ...]
查询“怎么学习” → 预期相关:[学而篇_0, 为政篇_10, ...]
...

有了这样的标注集,才能算指标。目前本项目还没有(仅测试了功能"不崩溃"),这在学习阶段是正常的,也是下一步要补齐的事情。

1.2 两个核心指标

Hit Rate@K(命中率)

在返回的 Top-K 个结果里,至少有一条是相关的,算一次命中。

  • 10 个查询中,8 个命中 → Hit Rate@5 = 80%

  • 回答的问题是:"东西捞到了没有?"

  • 它对 K 的大小敏感:K 越大,命中率自然越高,但同时输入 LLM 的 token 成本也越高。

  • 只看"有/没有",不关心排在第几位。

MRR(Mean Reciprocal Rank,平均倒数排名)

第一个相关的结果排在第几位?取它的倒数,再对所有查询取平均。

公式:MRR = 平均(1 / 第一个相关结果的排名)

举个例子:

  • 问题 1:第一个相关结果排在第 1 位 → 1/1 = 1.0

  • 问题 2:排在第 3 位 → 1/3 = 0.33

  • 问题 3:完全没命中 → 0

  • MRR = (1.0 + 0.33 + 0) / 3 ≈ 0.44

MRR 回答的问题是:"捞到之后,最好的那个排在最前面吗?" 它对排序精度极其敏感------排第一和排第五,分数差 5 倍。

Hit Rate 90% 但 MRR 只有 0.42,翻译成人话就是:"东西确实在袋子里,但每次都得翻到最底下才能摸到。"

1.3 两个指标的互补关系

Hit Rate MRR
问什么 有没有捞到? 第一个命中的排第几?
低了怎么办 加大 K / 混合检索 / 优化分块 加 Reranker / 混合检索 / 调相似度权重
局限 不管排序质量 只看第一个命中,后续的全部忽略

两个指标要一起看。只追求 Hit Rate 可能把 K 调得巨大,往 LLM 里塞一堆无关上下文;只追求 MRR 可能在"确定性高"的查询上过度优化,忽略那些召回本身就困难的边缘问题。

1.4 改进路线图

  1. 混合检索(向量 + 关键词)

    这是解决"白话问句 vs 古文章句"语义鸿沟的直接手段。比如用户问"仁是个什么玩意儿",向量检索可能效果一般,但"仁"这个字可以用传统的倒排索引精确匹配。RRF(Reciprocal Rank Fusion)把两套排序结果加权融合,往往能同时提升 Hit Rate 和 MRR。

  2. 重排序(Reranker)

    先用向量检索粗筛 Top-20(快速),再用一个更精确的 Reranker 模型精排 Top-5(慢但准)。比喻很形象:HR 初筛 100 份简历,技术主管再从中精挑 5 份进面试。

1.5 项目现状与下一步

当前项目在 test_edge_cases.py 第 204 行只验证了 assert len(results) == 3------测的是功能不崩,不测检索质量。检索链路也是纯向量检索,没有混合检索,没有 Reranker。下一步可以手动标注 10 个问题及预期论语章句,写个脚本把 Hit Rate 和 MRR 跑起来,从此调优有据可依。


二、实践:调 Top-K、调温度、对比效果

2.1 当前参数总览

参数 当前值 位置
RAG Top-K 5 chat.py 第 68、95 行
闲聊 temperature 1.1 client.py 第 49 行
RAG temperature 0.8 chat.py 第 80、108 行
意图分类 temperature 0.0 chat.py 第 35 行

2.2 Top-K 怎么调

  • 增大(5→10):召回更多上下文,Hit Rate 提升,但 token 消耗增加,且 LLM 可能"每条引一点",把回答答成流水账。

  • 减小(5→3):更聚焦,但有可能漏掉最相关的那条。

  • 原则:不要一次性翻倍,阶段性调整(3→6→8),每个档位验证效果。如果 K 已经调到 8 以上效果仍然不理想,根因通常不在 K,而要回头检查分块策略或 Embedding 质量。

2.3 Temperature 怎么调

RAG Temperature 控制回答在多大程度上忠于检索到的原文。

  • 降低(0.8→0.3):回答更加忠实于论语原文,但也可能变成复读机,丧失解释力。

  • 升高(0.8→1.2):解释力更强,语气更生动,但也可能脱离原文开始"编造"论语内容。

  • 保守区间 0.8-1.0,生动区间 1.1-1.3,不建议超过 1.5

闲聊 Temperature 是另一个维度。古文角色扮演需要在"灵活"和"守规矩"之间找平衡,1.1 是当前项目的经验值,并非绝对标准。

2.4 常见问题速查

用户抱怨 可能原因 先试什么
回复和问题不搭 Top-K 太小,最相关条文没进来 加大 Top-K
照抄原文,没有解释 Temperature 太低 提高 temperature
编造论语原文 Temperature 太高 / 上下文里混进了不相关条文 降低 temperature,同时检查检索质量
又死板又离谱,同时出现 两个参数都不在最优区 组合调:提高 temperature + 加入 top_p 来裁掉低概率噪音

2.5 验证闭环

调参最忌讳"改了以后感觉好像好了一点"。一个简单的验证闭环:

  1. 准备 5-10 个覆盖不同主题的测试问题。

  2. 改参前跑一遍,人工记录回复质量(是否引用原文、是否有解释、是否贴合问题)。

  3. 改参后用同一组问题再跑一遍,对比。

  4. 如果效果不变------问题就不在参数上,需要回头检查分块或检索链路。


三、Transformer 与注意力机制:词语如何"看见"彼此

3.1 问题的起点:为什么同一个"仁"字向量不同?

BGE 和 LLM 底层都是 Transformer 架构。它们真正强大的地方在于,同一个字在不同句子里,最终的向量表示完全不同。"杏仁"和"仁爱"的"仁",在 Transformer 眼里不是同一个东西。这是怎么做到的?核心就在注意力机制

3.2 注意力:词与词之间互相"看"

处理一句话时,每个词都要做一件事:看看周围的词,谁对我理解当前这句话有帮助?

  • "杏仁好吃" → "仁"发现旁边是"杏"和"好吃" → 我是"杏仁"的仁

  • "仁者爱人也" → "仁"发现旁边是"者"和"爱人" → 我是"仁爱"的仁

这种"互相看"的机制,被抽象成三个矩阵:Q、K、V。

3.3 Q、K、V:三个关键角色

角色 比喻
Q(Query,查询) "我想知道谁对我重要?" 举手提问的学生
K(Key,键) "我这里有什么信息?" 每个学生胸前的标签
V(Value,值) "我的实际含义是什么?" 每个学生手里的讲义

以"什么是仁"为例,整个过程分四步:

  1. 每个词通过训练好的矩阵乘法,生成自己的 Q、K、V。

  2. "仁"的 Q₃ 去和所有词的 K 做点积,算出匹配分数:Q₃·K₁("什么")=0.85,Q₃·K₂("是")=0.10,Q₃·K₃("仁")=0.05。

  3. 用这些匹配分数作为权重,对所有词的 V 做加权求和:新的"仁" = 0.85×V₁ + 0.10×V₂ + 0.05×V₃。

  4. 新的"仁"向量融入了"什么"的信息------它知道自己正在被提问。

注意:每个词都会这样更新一次,但侧重不同。最终每个词都带上整句话的语境。

3.4 多头注意力:12 个角度同时看

BGE 用的是 12 头注意力。这意味着同一层里,有 12 组独立的 Q、K、V,从 12 个不同角度观察句子:

  • 一个头关注语法关联(哪个词在修饰我?)

  • 一个头关注情感色彩(褒还是贬?)

  • 一个头关注条件限定(经常?偶尔?)

12 个头的输出最后拼接在一起,经过线性变换融合成一个更丰富的新向量。

一个很好的比喻:房间里装了 12 个不同角度的摄像头。单一角度看可能被遮挡或误解,12 个画面一合成,全貌就清晰了。另一个是"盲人摸象"的比喻------每个头只摸到象的一部分(鼻子、腿、身体),但合成起来就能大致还原大象的外形。

3.5 12 层堆叠:从字面到语义的层层抽象

理解深度 "学而时习之"的处理
Layer 1 直接邻居 "学"发现"而"在身旁
Layer 2 视野扩大 "学"通过"而"间接看到"时"
Layer 4 短语理解 识别出"学习并时常复习"
Layer 8 语义抽象 判断"学"是动词,不是"学校"
Layer 12 完整语境 每个词的向量都已包含整句话的信息

12 层 Transformer 就像 12 轮讨论会。从字面到短语再到语义,每一层都让词的表示更加抽象和完整。继续用盲人摸象的比喻:多层堆叠就是不断抽象的过程------Layer 1 发现"这个动物很大,鼻子很长,会喷气",到 Layer N 抽象出"体型庞大,有长鼻子,皮肤粗糙",最终概括为"大象"。

3.6 为什么"学而时习之"和"温故而知新"向量接近?

经过 12 层注意力之后:

  • "学而时习之"里,"学"融入了"习"和"时","习"也融入了"学"和"时",整体语义向"复习 + 经常"收敛。

  • "温故而知新"里,"温"融入了"故"和"知新","故"融入了"温"和"知新",整体语义向"复习 + 新知"收敛。

两个句向量都含有很强的"复习"语义方向,所以在向量空间中夹角很小,余弦相似度高。但"经常"和"知新"的侧重点不同,又保证它们不会完全重合------相似但不同一。

最后一步 Mean Pooling 把所有词的最终向量取平均,得到代表整个句子的 1024 维向量。这个平均不是原始词向量的平均,而是被语境更新了 12 轮的词向量的平均。

3.7 与项目的关系

在我们项目里,这套 Q-K-V 机制被用在两处:

  • BGE 模型embedder.py):12 层 Transformer,用注意力把句子编码成 1024 维向量。

  • DeepSeek 大模型client.py):远更深的 Transformer(几十层),同样用 Q-K-V 注意力机制,但任务是预测下一个 token------一个负责编码语义,一个负责生成文本。原理同源,用途各异。


以上三个主题,从 RAG 的评估指标到 Top-K 与 temperature 的调参实战,再到 Transformer 内部那套精妙的注意力机制,构成了 LLM 应用开发者必须穿透的三个层次:衡量效果、控制行为、理解模型。希望这份整理也能为你的项目提供一些清晰而可落地的参考。

相关推荐
Stark-C4 小时前
Obsidian官方同步贵?在NAS上自建服务器,实现多端笔记完美同步
运维·服务器·笔记
吃好睡好便好5 小时前
在Matlab中绘制三维直方图
开发语言·学习·算法·matlab·信息可视化
不是山谷.:.5 小时前
websocket的封装
开发语言·前端·网络·笔记·websocket·网络协议
大志若愚YYZ5 小时前
FreeRTOS中的两个Delay函数(vTaskDelay vs vTaskDelayUntil)
学习
问心无愧05135 小时前
ctf show web入门153
笔记
烤麻辣烫5 小时前
计算机思维--经典互联网应用
开发语言·学习·搜索引擎·数据库开发
EthanChou20205 小时前
AI辅助开发笔记
笔记
wuxinyan1235 小时前
工业级大模型学习之路018:LangChain零基础入门教程(第一篇):LangChain架构与生态介绍
人工智能·python·学习·langchain
中屹指纹浏览器5 小时前
指纹浏览器代理链路匹配机制与网络风控溯源阻断方案
经验分享·笔记