1
00:00:00,100 --> 00:00:06,432
本内容改编自小山学堂《学 AI 产品，从入门到精通》，为二次演绎配音版。

2
00:00:06,382 --> 00:00:11,826
这一集讲 Agent 工程里最容易被低估的一层，记忆和检索。

3
00:00:11,826 --> 00:00:15,360
上下文窗口是有限的，用完就崩。

4
00:00:15,360 --> 00:00:17,896
长期记忆靠什么找回来。

5
00:00:17,896 --> 00:00:24,362
检索到的东西，又怎么变成一个有来源、有边界、能被评测的回答依据。

6
00:00:24,362 --> 00:00:26,694
为什么产品经理要关心。

7
00:00:26,694 --> 00:00:29,531
因为这一层直接决定三件事。

8
00:00:29,531 --> 00:00:36,009
你的 Agent 能聊多久才崩，它记不记得上个月的事，以及它给出的答案能不能追责。

9
00:00:36,009 --> 00:00:41,153
这三个问题，每一个都是产品体验问题，不是工程细节。

10
00:00:41,153 --> 00:00:48,810
前面几集讲过，它每次回答都在猜下一个词，参数出厂就冻结，对话里学不进任何东西。

11
00:00:48,810 --> 00:00:50,925
这一集往前走一层。

12
00:00:50,925 --> 00:00:53,978
既然它记不住，工程上就要替它记。

13
00:00:53,978 --> 00:01:00,661
上下文怎么撑得更久，历史怎么找得回来，找到的东西又怎么变成能追责的依据。

14
00:01:00,661 --> 00:01:04,375
这三层合起来，就是 Agent 的记忆系统。

15
00:01:04,540 --> 00:01:06,449
先看一个硬约束。

16
00:01:06,399 --> 00:01:09,464
模型的上下文窗口是有限的。

17
00:01:09,464 --> 00:01:17,276
假设它是二十五万六千个词元，但要预留一部分给模型回复，真正的安全空间只有二十万。

18
00:01:17,276 --> 00:01:19,860
一次长对话就能把它装满。

19
00:01:19,860 --> 00:01:20,942
怎么办。

20
00:01:20,942 --> 00:01:27,216
课程给了四层压缩策略，像防洪堤，快满的时候自动泄洪降水位。

21
00:01:27,216 --> 00:01:31,387
第一层，裁剪，在百分之六十的水位触发。

22
00:01:31,387 --> 00:01:36,339
删掉早期工具返回的超长原始数据，只保留摘要。

23
00:01:36,339 --> 00:01:44,992
比如天气接口返回一千二百个词元的数据，压成一句，北京明日多云，十二到二十度，八十个词元。

24
00:01:44,992 --> 00:01:46,831
用户完全无感。

25
00:01:46,831 --> 00:01:50,605
第二层，微压缩，在百分之七十五触发。

26
00:01:50,605 --> 00:01:54,139
把早期的长对话生成简短摘要替换。

27
00:01:54,139 --> 00:02:04,512
比如用户说过，那个文件不是某种格式，我要另一种格式，标题改成什么什么，压成一句，用户要求换格式、改标题、调配色。

28
00:02:04,512 --> 00:02:07,757
轻微信息损失，关键信息保留。

29
00:02:07,757 --> 00:02:11,507
第三层，折叠，在百分之八十五触发。

30
00:02:11,507 --> 00:02:15,209
把多轮早期对话折叠成一条摘要消息。

31
00:02:15,209 --> 00:02:24,427
比如前八轮、十二条消息、四千二百个词元，压成一句，某个技术栈项目，当前在改报表页，三百五十个词元。

32
00:02:24,427 --> 00:02:27,132
细节丢失，但主线保留。

33
00:02:27,132 --> 00:02:31,206
第四层，紧急压缩，在百分之九十五触发。

34
00:02:31,206 --> 00:02:35,209
只保留系统提示、全局摘要和最近三轮。

35
00:02:35,209 --> 00:02:40,461
二十轮完整对话、一万八千个词元，压成二千五百个词元。

36
00:02:40,461 --> 00:02:43,790
明显信息损失，但避免崩溃。

37
00:02:43,790 --> 00:02:49,872
设计上的关键点是，没有压缩的话，二十万的上下文只够一次长对话。

38
00:02:49,872 --> 00:02:54,680
有了四层压缩，同样的窗口可以支撑五倍以上的对话量。

39
00:02:54,680 --> 00:02:57,733
直到真的删无可删，才会超限。

40
00:02:57,733 --> 00:02:59,896
还有一个数字要记住。

41
00:02:59,896 --> 00:03:05,281
安全空间二十万，是已经扣掉了预留给模型回复的五万六千。

42
00:03:05,281 --> 00:03:10,413
你能用的不是窗口的全部，而是窗口减去回复空间。

43
00:03:10,413 --> 00:03:15,353
这个差值在设计长对话产品的时候，经常被人忘掉。

44
00:03:15,353 --> 00:03:17,432
顺序为什么不能乱。

45
00:03:17,432 --> 00:03:24,019
第一层剪的是工具返回的原始数据，它最长也最不重要，用户根本不会回头看。

46
00:03:24,019 --> 00:03:27,552
第二层压的是已经完成的对话，主线还在。

47
00:03:27,552 --> 00:03:30,593
第三层开始丢细节，只保主线。

48
00:03:30,593 --> 00:03:35,786
第四层是保命，只留系统提示、全局摘要和最近三轮。

49
00:03:35,786 --> 00:03:38,358
越往后，丢的东西越贵。

50
00:03:38,358 --> 00:03:44,836
对产品经理来说，这意味着你要提前决定，哪一类内容绝对不能进压缩区。

51
00:03:44,836 --> 00:03:51,976
比如用户在第一轮说过的核心约束，如果不写进摘要，第四层一触发就永久消失了。

52
00:03:51,976 --> 00:04:00,293
这也是为什么很多产品会把关键约束固化成一条系统级记录，而不是指望它一直留在对话里。

53
00:04:00,293 --> 00:04:04,355
这四层还有一个共同点，它们都是自动触发的。

54
00:04:04,355 --> 00:04:08,995
也就是说，用户不会收到任何提示，信息就已经丢了。

55
00:04:08,995 --> 00:04:14,632
所以产品侧需要自己留一份摘要，而不是完全依赖这套机制。

56
00:04:14,764 --> 00:04:17,009
第二站讲长期记忆。

57
00:04:16,959 --> 00:04:18,293
一个类比。

58
00:04:18,293 --> 00:04:23,714
短期记忆是你的桌面，也就是上下文窗口，放得下的信息有限。

59
00:04:23,714 --> 00:04:30,613
长期记忆是你的档案柜，也就是向量数据库，需要时检索相关档案放到桌面上。

60
00:04:30,613 --> 00:04:36,430
桌面放不下所有东西，但你可以随时从档案柜里调取最相关的文件。

61
00:04:36,430 --> 00:04:41,935
短期记忆让 Agent 记住当前对话，长期记忆让它记住上个月的事。

62
00:04:41,935 --> 00:04:47,416
两者配合，它才能既了解你现在在做什么，也记得你过去的偏好。

63
00:04:47,416 --> 00:04:50,180
这里有三个设计决策值得记住。

64
00:04:50,180 --> 00:04:53,498
第一，什么信息该存入长期记忆。

65
00:04:53,498 --> 00:04:58,113
用户偏好、项目配置、历史问题、常用操作。

66
00:04:58,113 --> 00:05:01,082
这些决定了 Agent 的个性化程度。

67
00:05:01,082 --> 00:05:04,651
第二，检索质量取决于向量化模型。

68
00:05:04,651 --> 00:05:10,637
修登录接口，和登录接口并发五百，模型能匹配到同一条记忆吗。

69
00:05:10,637 --> 00:05:14,327
这个问题决定你的记忆是不是真的找得回来。

70
00:05:14,327 --> 00:05:16,899
第三，记忆太多也是问题。

71
00:05:16,899 --> 00:05:21,502
每次最多召回五条，怎么保证最重要的排在最前面。

72
00:05:21,502 --> 00:05:23,930
课程里有个演示很直观。

73
00:05:23,930 --> 00:05:32,921
记忆库里存了八条历史记忆，向量维度是七百六十八，每次最多召回五条，还有一个最低分数的门槛零点三。

74
00:05:32,921 --> 00:05:37,007
这几个数字就是一套长期记忆的全部配置。

75
00:05:37,007 --> 00:05:43,101
什么该存，用什么模型编码，召回多少条，低于多少分直接丢弃。

76
00:05:43,101 --> 00:05:46,214
桌面的类比还能再往下推一步。

77
00:05:46,214 --> 00:05:50,625
桌面上的东西你随时能看见，模型能直接用到。

78
00:05:50,625 --> 00:05:55,529
档案柜里的东西必须先拿出来放到桌上，才能被用到。

79
00:05:55,529 --> 00:05:59,784
也就是说，检索这个动作本身就占用上下文。

80
00:05:59,784 --> 00:06:03,966
你召回五条记忆，就占了五条记忆的上下文。

81
00:06:03,966 --> 00:06:10,060
所以召回多少，表面看是一个检索参数，本质上是一个预算参数。

82
00:06:10,204 --> 00:06:13,411
第三站讲这条链是怎么搭起来的。

83
00:06:13,361 --> 00:06:19,779
原始内容，比如一句退款多久到账，或者文档、图片这些业务数据。

84
00:06:19,779 --> 00:06:25,140
第一步，用同一个模型把内容编码成固定长度的浮点向量。

85
00:06:25,140 --> 00:06:31,065
第二步，做近似最近邻搜索，用少量精度换取数量级更高的速度。

86
00:06:31,065 --> 00:06:36,570
第三步，返回前若干条文档，再交给应用或者大模型使用。

87
00:06:36,570 --> 00:06:39,491
为什么普通关键词搜索不够。

88
00:06:39,491 --> 00:06:42,567
因为字面不同，意思可能很相近。

89
00:06:42,567 --> 00:06:48,805
怎么退钱和退款流程未必共享关键词，但在语义空间里距离很近。

90
00:06:48,805 --> 00:06:55,031
这里要提醒一句，向量化捕捉的是统计语义，不是可靠的事实判断。

91
00:06:55,031 --> 00:06:57,231
为什么不能逐条硬算。

92
00:06:57,231 --> 00:07:01,317
一百万条向量逐一精确比较，成本太高。

93
00:07:01,317 --> 00:07:05,212
所以先用索引缩小候选集，再计算距离。

94
00:07:05,212 --> 00:07:11,846
这也意味着你需要用召回率和延迟两个指标一起评测，而不是只看其中一个。

95
00:07:11,846 --> 00:07:14,250
相似度的方向别弄反。

96
00:07:14,250 --> 00:07:21,774
欧氏距离越小越近，内积越大越近，余弦相似度越大越近，文本语义通常用余弦。

97
00:07:21,774 --> 00:07:32,604
最关键的一条约束是，写入和查询必须使用同一个模型、同一种预处理方式和同一个维度，建索引和搜索的度量方式也必须一致。

98
00:07:32,604 --> 00:07:35,428
否则，有结果不等于结果可信。

99
00:07:35,428 --> 00:07:38,060
向量数据库到底负责什么。

100
00:07:38,060 --> 00:07:43,493
存，同时保存向量、主键和来源、类别、时间这些字段。

101
00:07:43,493 --> 00:07:49,358
找，用向量索引完成前若干条搜索，并用条件过滤缩小范围。

102
00:07:49,358 --> 00:07:53,950
管，管理集合、索引、加载和数据生命周期。

103
00:07:53,950 --> 00:07:57,676
它不替你生成向量，也不替大模型回答。

104
00:07:57,676 --> 00:08:04,875
一句话，向量化决定含义如何表示，向量数据库决定如何可靠且快速地存与找。

105
00:08:04,875 --> 00:08:07,459
还有一条边界容易被忽略。

106
00:08:07,459 --> 00:08:11,966
向量数据库不替你生成向量，也不替大模型回答。

107
00:08:11,966 --> 00:08:15,284
它只负责存、找、管这三件事。

108
00:08:15,284 --> 00:08:20,031
把它当成一个会思考的黑箱，是很多项目失望的起点。

109
00:08:20,031 --> 00:08:22,892
这里有三个坑值得单独点出来。

110
00:08:22,892 --> 00:08:26,726
第一个坑，把语义相近当成事实相同。

111
00:08:26,726 --> 00:08:31,714
向量化捕捉的是统计上的语义距离，不是判断真假。

112
00:08:31,714 --> 00:08:37,700
两句都像退款说明的话，可能一句真一句假，但在空间里挨得很近。

113
00:08:37,700 --> 00:08:41,630
第二个坑，用关键词那一套思维去看待它。

114
00:08:41,630 --> 00:08:49,851
产品型号、错误码、人名，这些精确词恰恰是语义搜索最容易漏的，所以才需要混合检索。

115
00:08:49,851 --> 00:08:52,567
第三个坑，度量方式不一致。

116
00:08:52,567 --> 00:08:58,385
写入用一种度量，搜索用另一种，结果看起来有，实际上不可信。

117
00:08:58,516 --> 00:09:01,711
第四站把它翻译成你熟悉的东西。

118
00:09:01,661 --> 00:09:05,891
集合可以类比成表，是一组具有相同结构的记录。

119
00:09:05,891 --> 00:09:13,007
结构定义和字段，可以类比成表结构和列，约束主键、向量维数和标量类型。

120
00:09:13,007 --> 00:09:17,166
一条记录就是一行，而主键必须能稳定定位。

121
00:09:17,166 --> 00:09:20,591
索引还是索引，用来加速近邻搜索。

122
00:09:20,591 --> 00:09:22,995
一条知识库记录长这样。

123
00:09:22,995 --> 00:09:26,769
主键四十二，用于更新、删除、追踪。

124
00:09:26,769 --> 00:09:29,269
向量字段，用于搜索。

125
00:09:29,269 --> 00:09:32,827
文本字段写着退款通常三天到账。

126
00:09:32,827 --> 00:09:36,252
还有一个类别字段，用于过滤和查询。

127
00:09:36,252 --> 00:09:38,307
三个动作要分清。

128
00:09:38,307 --> 00:09:44,149
搜索，输入查询向量，按距离返回前若干条，可以附加条件。

129
00:09:44,149 --> 00:09:47,250
它回答的问题是，语义上谁最像。

130
00:09:47,250 --> 00:09:52,057
查询，不传向量，按主键或者条件表达式取数据。

131
00:09:52,057 --> 00:09:55,687
它回答的问题是，哪些记录满足条件。

132
00:09:55,687 --> 00:10:00,218
加载，搜索前把索引和数据准备到查询节点。

133
00:10:00,218 --> 00:10:05,182
创建成功不代表已经可以搜，资源不足时也要规划释放。

134
00:10:05,182 --> 00:10:07,742
索引选型不是越高级越好。

135
00:10:07,742 --> 00:10:14,197
精确索引无需训练，但要全量比较，适合小数据集或者做召回率基线。

136
00:10:14,197 --> 00:10:21,228
聚类索引通过聚类缩小候选，需要调参数，适合数据量较大、成本可控的场景。

137
00:10:21,228 --> 00:10:28,139
图索引高召回、低延迟，但占更多内存、建索引较慢，在线检索常用。

138
00:10:28,139 --> 00:10:35,952
生命周期是，定义结构，创建集合，写记录，建索引，加载，然后才能搜索或者查询。

139
00:10:35,952 --> 00:10:44,257
主键是业务追踪锚点，向量字段负责相似度，标量字段负责权限、租户、时间和状态过滤。

140
00:10:44,257 --> 00:10:46,745
写入和删除也有讲究。

141
00:10:46,745 --> 00:10:55,230
写入要批量，用稳定主键，并且用覆盖写或者业务去重实现幂等，因为插入本身不会自动去重。

142
00:10:55,230 --> 00:11:02,250
同时要保留模型名、模型版本和内容版本，内容更新时要重新生成向量。

143
00:11:02,250 --> 00:11:11,757
删除则建议先用状态字段做逻辑删除，并在搜索条件里排除，因为物理删除之后，空间回收不会立刻生效。

144
00:11:11,757 --> 00:11:14,389
还有一条实操建议很实用。

145
00:11:14,389 --> 00:11:22,670
先用精确索引在小规模数据上跑一遍，拿到召回率的基线，再去比较图索引的召回率和延迟。

146
00:11:22,670 --> 00:11:27,851
没有基线，你根本判断不出调优是变好了还是变差了。

147
00:11:27,988 --> 00:11:30,510
第五站讲最关键的一步。

148
00:11:30,460 --> 00:11:39,294
搜索返回的是可能相关的片段，检索增强生成还要把它们变成有来源、有边界、能被评测的回答依据。

149
00:11:39,294 --> 00:11:41,229
在线链路分四步。

150
00:11:41,229 --> 00:11:44,750
第一步，用写入时同一个模型编码问题。

151
00:11:44,750 --> 00:11:49,438
第二步，先做租户和权限过滤，再做向量检索。

152
00:11:49,438 --> 00:11:53,813
第三步，精排、去重，并控制上下文长度。

153
00:11:53,813 --> 00:11:58,500
第四步，要求模型只依据证据回答，并给出来源。

154
00:11:58,500 --> 00:12:01,818
而离线的摄取决定了线上的上限。

155
00:12:01,818 --> 00:12:04,065
三个地方最容易出问题。

156
00:12:04,065 --> 00:12:05,568
第一，切分。

157
00:12:05,568 --> 00:12:10,327
按标题、段落和语义边界切块，保留少量重叠。

158
00:12:10,327 --> 00:12:14,089
切太大噪声多，切太小上下文断裂。

159
00:12:14,089 --> 00:12:15,952
第二，元数据。

160
00:12:15,952 --> 00:12:21,601
保存来源标识、版本、章节、租户、权限和更新时间。

161
00:12:21,601 --> 00:12:24,570
引用、过滤和删除都依赖它。

162
00:12:24,570 --> 00:12:26,205
第三，版本。

163
00:12:26,205 --> 00:12:31,770
内容或者模型变化要重算，蓝绿切换可以避免新旧向量混用。

164
00:12:31,770 --> 00:12:34,318
检索质量还有个工具箱。

165
00:12:34,318 --> 00:12:42,960
标量过滤解决租户、权限、时间、语言的约束，注意权限必须在检索阶段执行，不能只靠提示词。

166
00:12:42,960 --> 00:12:52,863
向量加关键词的混合检索，兼顾语义和产品型号、错误码这类精确词，但两种分数尺度不同，不宜直接相加。

167
00:12:52,863 --> 00:12:58,597
按排名融合多路结果，简单稳健，再用精排模型处理候选。

168
00:12:58,597 --> 00:13:06,938
分区和数据生命周期属于扩展能力，先用清晰的集合与过滤设计，不要一上来就追求高级特性。

169
00:13:06,938 --> 00:13:13,500
在线链路这四步里，最容易被跳过的是第三步，精排和控制上下文长度。

170
00:13:13,500 --> 00:13:20,784
很多人拿到检索结果就直接全塞给模型，塞得越多，模型越容易被无关片段带偏。

171
00:13:20,784 --> 00:13:25,363
控制长度不只是为了省钱，更是为了提高信噪比。

172
00:13:25,363 --> 00:13:30,219
而离线摄取里的切分，决定了线上能拿到的最细粒度。

173
00:13:30,219 --> 00:13:35,015
切得太大，一条里混了三个主题，引用就没法精确。

174
00:13:35,015 --> 00:13:38,897
切得太小，一句话被拆开，谁都读不懂。

175
00:13:38,897 --> 00:13:45,315
这个参数看起来是工程细节，实际上直接决定你的引用能不能点开对得上。

176
00:13:45,460 --> 00:13:49,220
第六站讲怎么判断这套东西做得好不好。

177
00:13:49,170 --> 00:13:51,213
评测必须分两层。

178
00:13:51,213 --> 00:13:56,285
先测检索这一层，召回率、排序质量和过滤正确性。

179
00:13:56,285 --> 00:14:01,009
再测答案这一层，忠实度、引用准确率和拒答率。

180
00:14:01,009 --> 00:14:03,809
检索这一层看三个指标。

181
00:14:03,809 --> 00:14:07,138
召回率回答的是，该找的找到了吗。

182
00:14:07,138 --> 00:14:10,756
排序质量回答的是，找到的排得对吗。

183
00:14:10,756 --> 00:14:15,239
过滤正确性回答的是，不该出现的有没有被挡住。

184
00:14:15,239 --> 00:14:17,980
答案这一层看另外三个。

185
00:14:17,980 --> 00:14:21,682
忠实度回答的是，回答有没有超出证据。

186
00:14:21,682 --> 00:14:25,143
引用准确率回答的是，来源对不对得上。

187
00:14:25,143 --> 00:14:29,458
拒答率回答的是，找不到的时候它敢不敢说不知道。

188
00:14:29,458 --> 00:14:31,850
这里有一句话最该记住。

189
00:14:31,850 --> 00:14:35,275
只看回答像不像，会掩盖召回失败。

190
00:14:35,275 --> 00:14:42,247
也就是说，答案看起来很顺，可能只是模型自己补的，根本没用上你检索到的东西。

191
00:14:42,247 --> 00:14:46,658
所以做验收的时候，一定要先看检索层的指标。

192
00:14:46,658 --> 00:14:52,607
如果召回率本身就低，再怎么调提示词，都是在给一个空档案柜擦灰。

193
00:14:52,607 --> 00:14:55,684
所以检索增强不是搜到就塞。

194
00:14:55,684 --> 00:15:02,379
切分、元数据、权限过滤、融合和引用，共同决定它是不是可靠。

195
00:15:02,524 --> 00:15:05,719
最后给你五条今天就能用的判断。

196
00:15:05,669 --> 00:15:08,649
第一条，把上下文当预算管。

197
00:15:08,649 --> 00:15:15,080
四层压缩是防洪堤，先裁工具返回，再压早期对话，最后才动系统提示。

198
00:15:15,080 --> 00:15:19,719
知道哪一层先触发，你才知道信息是从哪里开始丢的。

199
00:15:19,719 --> 00:15:25,200
第二条，权限必须在检索阶段执行，不能只靠提示词约束。

200
00:15:25,200 --> 00:15:29,106
写在提示词里的权限，等于没有权限。

201
00:15:29,106 --> 00:15:35,597
第三条，写入和查询必须用同一个模型、同一个维度、同一种度量方式。

202
00:15:35,597 --> 00:15:39,407
有结果不等于结果可信，这是最容易踩的坑。

203
00:15:39,407 --> 00:15:44,274
第四条，主键是业务追踪锚点，标量字段负责过滤。

204
00:15:44,274 --> 00:15:48,722
想清楚哪些字段要能筛，比选什么索引更重要。

205
00:15:48,722 --> 00:15:51,198
第五条，评测分两层。

206
00:15:51,198 --> 00:15:53,686
先看召回，再看答案。

207
00:15:53,686 --> 00:15:57,111
只看回答像不像，会掩盖召回失败。

208
00:15:57,111 --> 00:16:03,157
把这五条记住，你会发现 Agent 的记忆和检索，本质上是一套产品问题。

209
00:16:03,157 --> 00:16:09,479
能聊多久、记得多少、能不能追责，都是用户能直接感受到的体验。

