👍17❤1
继续学习 Context Engineering 相关的文章,主要看了这两篇:
- 来自 Augment 的 《How we made code search 40% faster for 100M+ line codebases using quantized vector search》
- 来自 Anthropic 的 《Contextual Retrieval in AI Systems》
📒 关于 query 的性能:
1. 利用 ANN 大幅减少 embeddings vectors 数量,提高检索速度。
我理解类似于对向量进行聚类,然后只对聚类中心进行搜索,最后再在聚类内进行精确搜索。
但是不确定 Augment 是自己手写了一个 ANN 的聚合层,还是直接使用了类似 pg_vector 的 IVF 等功能。
2. 对 ANN 方案的优化,对 embeddings index 做 SNAPSHOT。只有搜索的 chunk 在 SNAPSHOT 中时才触发 ANN 加速,否则走传统的线性扫描。
这样就可以适应无时不刻都在动态更新的代码库。
📒 关于 query 的准确率和召回率:
1. embeddings vectors 擅长 semantic search,但对精确匹配不友好。结合 BM25 来提高精确匹配的能力。
2. 在 embeddings 以前,先为 chunk 添加上下文信息
有一个优化技巧是,先利用 prompt cache 缓存全文,然后再使用这个 cache 为每一个 chunk 生成上下文。
3. 玄学参数,每次 RAG 提供 20 个 context chunks 的效果最好。Anthropic 的做法是,用混合搜索检索出 400 个 chunks,然后使用 cohere rerank 选出 top20。
4. rerank 会带来额外的延迟,所以 chunks 数量和延迟是一个 trade-off。
👇 next
- 来自 Augment 的 《How we made code search 40% faster for 100M+ line codebases using quantized vector search》
- 来自 Anthropic 的 《Contextual Retrieval in AI Systems》
📒 关于 query 的性能:
1. 利用 ANN 大幅减少 embeddings vectors 数量,提高检索速度。
我理解类似于对向量进行聚类,然后只对聚类中心进行搜索,最后再在聚类内进行精确搜索。
但是不确定 Augment 是自己手写了一个 ANN 的聚合层,还是直接使用了类似 pg_vector 的 IVF 等功能。
2. 对 ANN 方案的优化,对 embeddings index 做 SNAPSHOT。只有搜索的 chunk 在 SNAPSHOT 中时才触发 ANN 加速,否则走传统的线性扫描。
这样就可以适应无时不刻都在动态更新的代码库。
📒 关于 query 的准确率和召回率:
1. embeddings vectors 擅长 semantic search,但对精确匹配不友好。结合 BM25 来提高精确匹配的能力。
2. 在 embeddings 以前,先为 chunk 添加上下文信息
有一个优化技巧是,先利用 prompt cache 缓存全文,然后再使用这个 cache 为每一个 chunk 生成上下文。
3. 玄学参数,每次 RAG 提供 20 个 context chunks 的效果最好。Anthropic 的做法是,用混合搜索检索出 400 个 chunks,然后使用 cohere rerank 选出 top20。
4. rerank 会带来额外的延迟,所以 chunks 数量和延迟是一个 trade-off。
👇 next
👍6
https://tee.fail/ wiretap 的团队继续发力,TEE 加密芯片对内存加密使用了确定性算法,同样的明文会生成同样的密文,导致可以通过内存分析破译私钥。继上次破解 SGX 老款芯片后,这次把最新款的 TDX 和 SEV-SNP 也攻破了,可以说 TEE 全军覆灭。
AMD 和 Intel 都表示不会修复,内存监听和改写不属于 TEE 的防御范畴。
看来,TEE 确实只能用来防内鬼,并不能构成一个可以放心地托管给别人的飞地。
* prev
AMD 和 Intel 都表示不会修复,内存监听和改写不属于 TEE 的防御范畴。
看来,TEE 确实只能用来防内鬼,并不能构成一个可以放心地托管给别人的飞地。
* prev
👏5
《Optimize generative AI applications with pgvector indexing: A deep dive into IVFFlat and HNSW techniques》,由 aws 撰写的一片关于 pgvector 索引的文章。
在 LLM RAG 领域,为了处理较长的输入,通常会将文本拆分成较小的 chunks,然后在一些预处理后,将这些 chunks 通过 embeddings 模型生成 vector,存储于向量数据库中。当用户发起查询时,系统会将查询文本同样通过 embeddings 模型生成 vector,然后在向量数据库中进行相似度搜索,找到最相关的 chunks 作为上下文补充。
postgres 搭配 pgvector 插件,是一种常见的向量数据库实现方式。在向量数据库中进行查询,其实就是寻找和目标向量“最相似”的一组向量,“相似”的度量手段有三种:
* L2 距离(Euclidean Distance):计算两个向量之间的欧氏距离。
* Cosine 相似度(Cosine Similarity):计算两个向量之间的夹角余弦值。
* 内积(Inner Product):计算两个向量的点积。可以衡量向量的相似性。
默认情况下,也就是不建立索引时,pgvector 会进行遍历搜索。为了提高搜索性能,提供了两种索引索引:
* IVFFlat 索引(Inverted File with Flat quantization):IVFFlat 是一种基于有监督聚类的近似最近邻搜索算法。它通过将向量空间划分为多个 regions。搜索时,首先仅需要搜索各个 regions 的中心点,找出相关 region 后,再搜索 region 内的向量。
* HNSW 索引(Hierarchical Navigable Small World graphs):HNSW 是一种基于图结构的近似最近邻搜索算法。可以理解为 skiplist,先从最上层(节点最少的层)开始搜索,找到最近点后,作为下一层的起始点继续搜索,逐层往下,直到最底层。
这两种索引都可以显著减少搜索时需要比较的向量数量,从而提升查询速度。而且,为了避免局部最优解,可以设定以多个起始点的方式进行搜索。
文中对 58.6 K 个,总大小为 364 MB 的向量集进行了测试(pgvector 0.6):
* 不使用索引,搜索耗时 650 ms
* 使用 IVFFlat 索引,建立索引 15.5 s,搜索耗时 2.4 ms
* 使用 HNSW 索引,建立索引 30 s,搜索耗时 1.58 ms
可以看出,使用索引对搜索性能提升是很大的。
👆 prev
在 LLM RAG 领域,为了处理较长的输入,通常会将文本拆分成较小的 chunks,然后在一些预处理后,将这些 chunks 通过 embeddings 模型生成 vector,存储于向量数据库中。当用户发起查询时,系统会将查询文本同样通过 embeddings 模型生成 vector,然后在向量数据库中进行相似度搜索,找到最相关的 chunks 作为上下文补充。
postgres 搭配 pgvector 插件,是一种常见的向量数据库实现方式。在向量数据库中进行查询,其实就是寻找和目标向量“最相似”的一组向量,“相似”的度量手段有三种:
* L2 距离(Euclidean Distance):计算两个向量之间的欧氏距离。
* Cosine 相似度(Cosine Similarity):计算两个向量之间的夹角余弦值。
* 内积(Inner Product):计算两个向量的点积。可以衡量向量的相似性。
默认情况下,也就是不建立索引时,pgvector 会进行遍历搜索。为了提高搜索性能,提供了两种索引索引:
* IVFFlat 索引(Inverted File with Flat quantization):IVFFlat 是一种基于有监督聚类的近似最近邻搜索算法。它通过将向量空间划分为多个 regions。搜索时,首先仅需要搜索各个 regions 的中心点,找出相关 region 后,再搜索 region 内的向量。
* HNSW 索引(Hierarchical Navigable Small World graphs):HNSW 是一种基于图结构的近似最近邻搜索算法。可以理解为 skiplist,先从最上层(节点最少的层)开始搜索,找到最近点后,作为下一层的起始点继续搜索,逐层往下,直到最底层。
这两种索引都可以显著减少搜索时需要比较的向量数量,从而提升查询速度。而且,为了避免局部最优解,可以设定以多个起始点的方式进行搜索。
文中对 58.6 K 个,总大小为 364 MB 的向量集进行了测试(pgvector 0.6):
* 不使用索引,搜索耗时 650 ms
* 使用 IVFFlat 索引,建立索引 15.5 s,搜索耗时 2.4 ms
* 使用 HNSW 索引,建立索引 30 s,搜索耗时 1.58 ms
可以看出,使用索引对搜索性能提升是很大的。
👆 prev
❤14👍4🐳1
https://laisky.notion.site/Time-Zone-Handling-for-Software-Engineers-A-Comprehensive-Technical-Handbook-2b3ba4011a8680f2b895f51f19b62dad?source=copy_link
让 DeepResearch 帮忙总结了一篇关于时区的报告。最近都不怎么喜欢搜索文章了,想到什么问题就扔给 DeepResearch 让它给我写一篇报告。
因为中国只有一个时区,很多开发人员都会忽略时区问题,我加入很多团队都帮忙处理过时区相关的问题(另一个经常被忽略的是编码问题)。
首先,在用户看不见的后端使用 UTC 时间是一个很好的习惯,但是 UTC 并不是银弹,并不能取代时区。
时区并不仅仅只是相对于 UTC 的一个固定偏移量,而是代表某一地区时间变化的历史和规则。比如某地可能在某一个时刻,决定让时钟拨快或拨慢一小时,这些规则的处理都必须依赖准确的当地时区数据,而不是 UTC 能够解决的。同理,不同的时区也不能随意的互相替换,即使在当前时刻它们的 UTC 偏移量相同。
比如关于冬令时/夏令时的调整,就会导致当地的某一时刻在两个不同时区出现两次,而另一个时刻则根本不存在。
关于时间的存储,UTC 仅能满足对于时刻的存储需求。只要涉及到当地事件、时间的相对计算、日程安排(牵涉星期、月份日期、节假日)等,都必须结合使用当地时区信息进行计算。而且由于用户可能会进行跨时区迁移,最好能够让用户自行选择自己的时区信息(比如 Google Calendar 的做法)。
重点:
* 如果你只需要时刻信息(Instant),使用 UTC 存储和传输是一个好习惯。
* 但是如果你需要任何基于当地时间的计算,必须携带时区信息。
BTW,时区的英文缩写存在重名,在沟通中不要使用简写。比如 CST 既可以是 China Standard Time 也可以是 Central Standard Time。 我以前和美国的团队协作时就遇到过歧义。
让 DeepResearch 帮忙总结了一篇关于时区的报告。最近都不怎么喜欢搜索文章了,想到什么问题就扔给 DeepResearch 让它给我写一篇报告。
因为中国只有一个时区,很多开发人员都会忽略时区问题,我加入很多团队都帮忙处理过时区相关的问题(另一个经常被忽略的是编码问题)。
首先,在用户看不见的后端使用 UTC 时间是一个很好的习惯,但是 UTC 并不是银弹,并不能取代时区。
时区并不仅仅只是相对于 UTC 的一个固定偏移量,而是代表某一地区时间变化的历史和规则。比如某地可能在某一个时刻,决定让时钟拨快或拨慢一小时,这些规则的处理都必须依赖准确的当地时区数据,而不是 UTC 能够解决的。同理,不同的时区也不能随意的互相替换,即使在当前时刻它们的 UTC 偏移量相同。
比如关于冬令时/夏令时的调整,就会导致当地的某一时刻在两个不同时区出现两次,而另一个时刻则根本不存在。
关于时间的存储,UTC 仅能满足对于时刻的存储需求。只要涉及到当地事件、时间的相对计算、日程安排(牵涉星期、月份日期、节假日)等,都必须结合使用当地时区信息进行计算。而且由于用户可能会进行跨时区迁移,最好能够让用户自行选择自己的时区信息(比如 Google Calendar 的做法)。
重点:
* 如果你只需要时刻信息(Instant),使用 UTC 存储和传输是一个好习惯。
* 但是如果你需要任何基于当地时间的计算,必须携带时区信息。
BTW,时区的英文缩写存在重名,在沟通中不要使用简写。比如 CST 既可以是 China Standard Time 也可以是 Central Standard Time。 我以前和美国的团队协作时就遇到过歧义。
laisky on Notion
🤖Time Zone Handling for Software Engineers: A Comprehensive Technical Handbook | Notion
Introduction
👍10❤3
https://www.notion.so/laisky/Cloudflare-outage-on-November-18-2025-2bcba4011a8681e79964ff8933d3c5b2
CloudFlare 对于 2025-11-18 的故障报告。边缘服务设定了严格的内存限制,其中bot modules 限制了能够处理的规则行数。当接收到超过限制的规则文件后导致 panic。而新的 FL2 系统在 bot modules panic 时,没能仅降级 bot 服务,而是全链路 panic,导致全站 5xx。旧版的 FL 系统就很好的仅降级了 bot score 服务,没有对用户业务造成中断。
我个人认为的经验教训就是:
1. bot modules panic 不是问题,有助于尽早暴露错误,但是必须被隔离。
2. FL2 在 bot modules panic 后,应该进行告警和服务降级,而不是整体 panic(Blast Radius)
3. chaos engineering 应该对各种交互都进行测试,比如文件过大、格式错误等等。任何关键服务都不应该信任外部输入,即使这个外部输入来自友方。
CloudFlare 对于 2025-11-18 的故障报告。边缘服务设定了严格的内存限制,其中bot modules 限制了能够处理的规则行数。当接收到超过限制的规则文件后导致 panic。而新的 FL2 系统在 bot modules panic 时,没能仅降级 bot 服务,而是全链路 panic,导致全站 5xx。旧版的 FL 系统就很好的仅降级了 bot score 服务,没有对用户业务造成中断。
我个人认为的经验教训就是:
1. bot modules panic 不是问题,有助于尽早暴露错误,但是必须被隔离。
2. FL2 在 bot modules panic 后,应该进行告警和服务降级,而不是整体 panic(Blast Radius)
3. chaos engineering 应该对各种交互都进行测试,比如文件过大、格式错误等等。任何关键服务都不应该信任外部输入,即使这个外部输入来自友方。
laisky on Notion
Cloudflare outage on November 18, 2025 | Notion
On 18 November 2025 at 11:20 UTC (all times in this blog are UTC), Cloudflare's network began experiencing significant failures to deliver core network traffic. This showed up to Internet users trying to access our customers' sites as an error page indicating…
https://laisky.notion.site/msanft-CVE-2025-55182-Explanation-and-full-RCE-PoC-for-CVE-2025-55182-2c2ba4011a8681b89b60cf02827a6276?source=copy_link
之前提到的 next/react 严重服务端 RCE 漏洞 CVE-2025-55182
攻击者传递两个 chunk。chunk 0 作为攻击载体,chunk 1 作为正常 chunk,然后:
1. 利用自定义 then 将 chunk.prototype.then 挂载到 chunk 0,使得 chunk 0 变成 thenable,成为可被执行的 Promise
2. chunk 1 中,通过 $@0,将 chunk 0 作为 decodeReplyFromBusboy 的返回值,被 await 执行(thenable 对象都会被作为 Promise 而被 await 执行)
3. chunk0 中,通过自定义 react 状态机 status,触发 initializeModelChunk 中对 _response 的读取
4. 在 chunk 0 中,$B 会让 react 调用 response._formData.get()。但是 chunk 0 自定义了 _response 中的 _formData 和 _get,导致读取 _response body 的操作变成了一次代码执行
在我看来严重隐患似乎存在于两个地方:
1. 允许用户操作 prototype 的 function constructor,可以通过限制仅允许访问 ownProperty 来抑制
2. $@0 直接将 chunk 返回,而且 react 会将这个 chunk 视为一个可信的内部对象,这个对象通过 status 来控制状态,_response、_get 来控制数据。也就是说,外部的不可信输入直接控制了状态和数据。我觉得这个设计的问题可比 prototype 的访问越权严重多了。
之前提到的 next/react 严重服务端 RCE 漏洞 CVE-2025-55182
攻击者传递两个 chunk。chunk 0 作为攻击载体,chunk 1 作为正常 chunk,然后:
1. 利用自定义 then 将 chunk.prototype.then 挂载到 chunk 0,使得 chunk 0 变成 thenable,成为可被执行的 Promise
2. chunk 1 中,通过 $@0,将 chunk 0 作为 decodeReplyFromBusboy 的返回值,被 await 执行(thenable 对象都会被作为 Promise 而被 await 执行)
3. chunk0 中,通过自定义 react 状态机 status,触发 initializeModelChunk 中对 _response 的读取
4. 在 chunk 0 中,$B 会让 react 调用 response._formData.get()。但是 chunk 0 自定义了 _response 中的 _formData 和 _get,导致读取 _response body 的操作变成了一次代码执行
在我看来严重隐患似乎存在于两个地方:
1. 允许用户操作 prototype 的 function constructor,可以通过限制仅允许访问 ownProperty 来抑制
2. $@0 直接将 chunk 返回,而且 react 会将这个 chunk 视为一个可信的内部对象,这个对象通过 status 来控制状态,_response、_get 来控制数据。也就是说,外部的不可信输入直接控制了状态和数据。我觉得这个设计的问题可比 prototype 的访问越权严重多了。
laisky on Notion
msanft/CVE-2025-55182: Explanation and full RCE PoC for CVE-2025-55182 | Notion
https://laisky.notion.site/Agent-Skills-Comprehensive-Guide-2e4ba4011a868055b2b0e2e128da1538?source=copy_link
学习了一下 Anthropic 的 Agent Skills 设计。通过在文件系统中定义一套文件结构,让 Agent 可以按需加载(Progressive Disclosure)相关的技能描述和脚本。
Skills 通过 metadata + instructions + scripts 定义一个领域技能。Agent 在启动时全量加载 metadatas,然后按需加载 instructions,而 instructions 会指导 agent 调用 scripts。scripts 的内容不会被加载,只有 output 会被加载进入 context。
通过一个三层的 lazy-loading 设计,相当于 RAG + tools,既减少了对 context 的占用,也赋予了 agent 工具调用的能力。
但是我认为,Anthropic 没有选择优化 MCP,而是硬造了一个新轮子,给 Agent 世界带来更多的混乱,有些可惜。
Skills 的功能完全可以通过对 MCP 的些微优化来实现,只需要在 MCP 中增加两个 tools:
-
-
实际上,已经有很多人发布了相关的 skills-mcp 工具,只要搜索
学习了一下 Anthropic 的 Agent Skills 设计。通过在文件系统中定义一套文件结构,让 Agent 可以按需加载(Progressive Disclosure)相关的技能描述和脚本。
Skills 通过 metadata + instructions + scripts 定义一个领域技能。Agent 在启动时全量加载 metadatas,然后按需加载 instructions,而 instructions 会指导 agent 调用 scripts。scripts 的内容不会被加载,只有 output 会被加载进入 context。
通过一个三层的 lazy-loading 设计,相当于 RAG + tools,既减少了对 context 的占用,也赋予了 agent 工具调用的能力。
但是我认为,Anthropic 没有选择优化 MCP,而是硬造了一个新轮子,给 Agent 世界带来更多的混乱,有些可惜。
Skills 的功能完全可以通过对 MCP 的些微优化来实现,只需要在 MCP 中增加两个 tools:
-
find_skills(query): 根据 query 查找相关的 skills metadata 列表-
describe_skill(skill_id): 根据 skill_id 获取对应的 instructions。instructions 内会指导 agent 如果通过调用其他 tools 完成任务。实际上,已经有很多人发布了相关的 skills-mcp 工具,只要搜索
github skills-mcp 就能找到很多。👍17