“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
RAG 上下文剪枝:用小型 LLM 剔除 68% 的冗余上下文,保留 96% 的召回率
通过在检索器和生成器之间插入一个轻量级 LLM 对检索到的文档块进行列表式评分与剪枝,可在保留 96% 召回率的前提下剔除约 68% 的上下文,将单次查询成本降低约三分之一。
背景:RAG 的成本困境
在构建面向复杂产品知识库(技术文档、API 参考、PDF、论坛、支持线程)的 AI 问答助手时,RAG(检索增强生成)仍然是处理大规模、高复杂性知识库的最佳方案。典型的 RAG 流程分为两步:
- 检索器:通过嵌入向量搜索和关键词搜索,将数十万文档块缩减为几百个候选块,再经重排序器排序,最终选出约 15 个最相关的块。
- 生成器:将选出的块与问题一起输入给最大的、最昂贵的 LLM,由其生成答案。
问题在于:生成器为它忽略的每一块文档付费。在我们的实际系统中,检索到的文档块占据了单次查询成本的约三分之二,远高于答案生成、对话历史和系统提示的总和。每减少一个文档块,查询成本就降低约 4%。而且,在智能体(Agent)场景下,每次工具调用都会将输出注入上下文,上下文会迅速膨胀;更紧凑的检索结果为智能体节省了宝贵的上下文空间,减少了“上下文腐烂”的风险。
然而,代价是召回率。如果剪枝去掉了答案所需的文档块,就相当于用几美分换来了一个错误答案。剪枝器的核心指标就是压缩率与召回损失的权衡。
为什么简单的方案行不通
方案一:基于重排序分数的截断
既然我们已经用重排序器(reranker)对候选块进行了排序,一个直观的想法是:直接暴露重排序分数,设定一个固定阈值(如 0.7),低于阈值的块全部丢弃。但这个方案存在两个根本问题:
重排序分数是序数,不是度量。它只表示块 A 比块 B 更相关,但分数本身没有跨查询的校准意义。Cohere 也明确指出了这一点。因此,任何固定阈值都无法通用。唯一可行的截断是位置截断(top-N),但这会盲目丢弃最后一个块,无论它是否是答案的关键部分。
相关性不是单个块的属性。大多数 RAG 流水线中的重排序器是逐点交叉编码器(pointwise cross-encoder),它们独立地对每个查询-块对打分,从不考虑该块与其他检索到的块之间的关系。
来看一个匿名的生产示例:假设问题涉及“审计日志”,检索到了两个块:块 A 明确提到了审计日志,块 B 讨论了相关系统组件但未提及“审计日志”。逐点评分中,块 B 因未命中关键词而被判为噪声,得分很低。然而,块 B 提供了块 A 中缺失的关键前提信息,两者组合才能完整回答问题。逐点评分永远无法发现这种“集合层面的相关性”。
同样,当问题包含多个子问题时,每个子问题的答案可能分散在不同的块中,单独看每个块都不完整,但合在一起才能回答。
方案二:锚定文档法
我们曾尝试一种更精巧的方法:锚定文档(Anchor Documents)。原理是在重排序结果中插入一些合成块,每个合成块代表一个明确的相关性等级(从“关键”到“无关”),然后丢弃所有排在最低保留等级锚点之后的真实块。这个方法优雅且只需一次额外的 LLM 调用。
但它在实践中失败了,原因与方案一相同:它仍然依赖重排序器的逐点分数。锚点虽然解决了跨查询的校准问题,但无法改变重排序器本身对部分相关和间接相关块的错误评分——这些块经常被排在明显无关的块之后。为了保留它们,锚点必须设置得非常低,结果几乎剪不掉任何东西。
这个失败给了我们关键启示:剪枝器必须同时看到问题和所有检索到的块,因为它要判断的是“集合”而非“个体”。
我们的方案:列表式 LLM 评分
我们在重排序器和生成器之间增加了一步:一个轻量级 LLM 调用。这个小型 LLM 接收问题以及所有检索到的文档块,对每个块按照一个五级评分体系进行评分:
| 分数 | 等级 | 含义 |
|---|---|---|
| 5 | ESSENTIAL(关键) | 没有这个块就无法产生答案,无论是直接回答,还是作为其他块依赖的定义或前提。 |
| 4 | CONTRIBUTING(贡献) | 单独不能回答问题,但与其他块组合后提供完整答案所需的信息。 |
| 3 | SUPPORTING(支持) | 与主题相关且可能有用,但没有它答案也很可能完整。 |
| 2 | TANGENTIAL(边缘) | 属于同一领域或共享术语,但没有具体贡献。 |
| 1 | UNRELATED(无关) | 没有有意义的关联。 |
只有分数达到或超过某个阈值的块才会保留。这个设计同时解决了前述两个问题:
- 跨查询的校准:每个等级的定义是固定的,分数 4 在所有查询中含义一致,因此可以使用固定的截断阈值。
- 集合级判断:LLM 同时看到问题和所有块,可以判断“这个块在这个集合中是否贡献了缺失的信息”,从而正确处理部分相关和间接相关的场景。
三个关键调节旋钮
- 模型选择:剪枝器的成本必须由它节省的费用来覆盖,因此旗舰模型从一开始就被排除。我们在多个小型快速模型上测试,发现它们的判断质量相似,最终选择了最快、最便宜且推理努力度最低的模型。
- 阈值:这是压缩率与召回率之间的主要调节旋钮。
- keep-top-k:无论评分如何,重排序结果中排名最高的前 k 个块强制保留,以保护最强相关的块免受可能的评分错误影响。
对照实验
为了验证方案的有效性,我们还测试了两个更简单的设计:
- 预算选择(Budget-select):保留前几个块,然后让 LLM 最多再添加 N 个块。优点是上下文大小可预测,但一旦预算用尽,后续块无论多相关都会被丢弃。
- 最简单的剪枝器:直接问 LLM“应该保留哪些块”,不定义评分等级。
如果我们的方案不能超越“直接问”这种简单方法,那它就不值得构建。
实验结果
我们使用一组标注了答案所需文档块的真实问题来测量召回率,然后通过回放一个随机月的生产流量(使用每次查询实际发送给生成器的文档块)来验证压缩率、成本和延迟。
每个数据点代表一个配置,横轴是压缩率(剪枝器丢弃的检索块比例),纵轴是召回保留率(在剪枝后仍然拥有答案所需全部文档块的问题占比)。100% 表示没有问题丢失关键块,90% 表示每十个问题中有一个丢失了。越靠右上越好。
图中的曲线连接了每种策略的最佳配置,灰色虚线是基线:简单的 top-N 截断(直接从重排序结果中返回更少的块)。
结果非常清晰:
- 所有 LLM 策略都大幅超越基线。
- 在召回率 98% 的水平上,top-N 截断只能丢弃 1 个块(约 7% 压缩率),而所有 LLM 策略都能达到 30% 以上压缩率,其中评分策略接近 50%。
- 在所有压缩率水平上,五级评分策略(Scoring)完全支配了其他两种 LLM 策略。
我们最终选择了一个偏激进的配置:召回保留率约 96%,压缩率约 68%。这意味着每 25 个问题中大约有 1 个会丢失一个需要的块,但作为交换,三分之二的上下文被剪掉。
结论与影响
通过在 RAG 流水线中增加一个轻量级 LLM 作为剪枝器,我们实现了:
- 压缩率:剔除约 68% 的检索上下文
- 召回率:保留约 96% 的必要文档块
- 成本:单次查询成本降低约三分之一(扣除剪枝器自身成本后)
这个方案的核心洞察是:相关性是一个集合属性,而非个体属性。只有让剪枝器同时看到所有候选块,才能做出正确的取舍。