MoreRSS

site icon1Q43 | 虹线修改

自称:评论尸。代表作《互联网是人类历史的一段弯路吗?》《垄断的困境》《互联网与中国后现代性呓语》 公众号”赤潮AKASHIO",播客”二维吾码”主理人。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

1Q43 | 虹线的 RSS 预览

善用“古法 AI”,能帮你省下很多 Token

2026-07-17 09:54:23

AI 之后,个性化信息系统突然泛滥了。

日报、舆情监控、行业雷达、选题助手、知识推送——名字不同,后台却经常长得一模一样:先抓一堆原始文章,再把每篇文章塞进大语言模型,问它「这篇和我的主题相关吗?」

这很自然。大语言模型看起来会读、会判断,而我又需要一个人替我筛信息,那就让模型把文章读一遍。过去是实习生坐在电脑前逐条判断,现在把实习生换成 API 就行了。

问题是,实习生是固定工资,但 LLM 不是。

假设每天有 500 篇文章,我只关心「科技向善」一个主题。最朴素的实现是发 500 次请求,让 LLM 逐篇判断。这可能还在可接受范围内。

但如果我同时关心科技向善、智能硬件、新消费、县城经济和科技伦理五个主题呢?在不合并分类请求的情况下,500 篇文章乘以 5 个主题,就是 2500 次判断。

这不是严格意义上的「指数增长」,只是文章数与主题数相乘,复杂度变成 O(N×M)。但账单不会因为术语更准确就少一点。文章越多,主题越多,钱和时间一起往里填。

当然,你可以把五个问题合并成一次请求:附上原文,再要求模型返回一个 JSON,分别判断五个主题。请求次数回到了 500 次,但输入没有消失。原文越长、主题边界越复杂、输出字段越多,模型越容易漏判、串题,或者给出一个格式正确、内容却经不起检查的答案。

很多所谓 AI 信息系统,并没有解决信息筛选问题。它们只是把人工阅读的成本,改写成了模型调用的成本。

但我想到一个问题:今日头条早在 2012 年 8 月就上线了。此后十几年,我们又在支付宝、滴滴、浏览器和无数与资讯八竿子打不着的 App 里刷到了个性化信息流。

那个没有 LLM 的时代,到底是怎么做推荐的?

这个问题先按下,文章最后再回来。

你需要的可能不是「理解」,只是「距离」

先回到最简单的任务:每天从 500 篇 RSS 文章里,捞出和几个固定主题相关的内容。

LLM 会把它理解成一个阅读理解题:读文章、读规则、推理、输出结论。

但它其实也可以被改写成一道几何题:

这篇文章,离「科技向善」这个主题有多近?

Embedding 正好适合做这件事。

Embedding 模型会把一段文本转换成一串固定长度的数字,也就是一个向量。你可以把它想象成一台「语义坐标转换器」:文章进去,出来的是它在语义空间中的坐标。

很多人第一次认识 Embedding,是在 RAG 里看它负责召回。这一代应用开发者大多从 LLM 时代进入 AI,起点又在应用层,很容易把 Embedding 当成 RAG 的固定配件:离开知识库问答,就想不起它还能干什么。

其实只要一个任务可以改写成「比较两段东西有多像」,Embedding 就能在许多场景单独派上用场。

在向量视角下,「OpenAI 发布新的模型路由能力」和「Anthropic 更新企业 API」这两句话的距离会比较近,「某地暴雨导致航班延误」这句话则会与前两句相差十万八千里。向量里的某一个数字通常没有可读含义,但两个向量之间的距离有意义。

做法不复杂:

  1. 把文章变成向量;
  2. 把主题描述也变成向量;
  3. 计算两者的余弦相似度,超过阈值就算命中。

余弦相似度关心的是两个向量的方向是否接近。工程里常写成:

cosine_similarity(A, B) = dot(A, B) / (norm(A) * norm(B))

如果向量预先做了 L2 归一化,后面的余弦相似度甚至可以简化成一次点积。

Embedding 本身不是分类器。真正的分类器,是「Embedding + 主题锚点(范文) + 相似度 + 阈值」这四样东西拼起来的结果。

我为 FreshRSS 做的低成本分类插件 FreshRSS-AutoLabel,就是这个最基础的版本。

用户先为每个主题准备几段范文,也就是「这个主题下的典型文章会写什么」。系统把新进入 FreshRSS 的标题、Feed、作者和截断后的正文拼成一段文本,为它生成一次 Embedding,然后与每个主题的范文向量比较。最高相似度超过阈值,就自动打上对应标签。

省钱靠两件事:

首先,范文很稳定。20 个主题,每个主题 3 条范文,第一次算完 60 个向量后就可以缓存。模型、Instruction 和范文文本没变,就不用重算。

第二,文章向量也能复用。一篇文章面对 20 个主题,不是生成 20 次向量,而是生成 1 次,再在本地(不调用 API)和 60 个范文做点积。

于是成本模型从:

文章数 × 主题数 × LLM 判断

变成了:

文章数 × Embedding
+范文首次向量化
+ 本地点积

500 篇文章、20 个主题、每个主题 3 条范文,第一次大约是 500 次文章 Embedding 加 60 次范文Embedding。此后只要范文不变,每天主要就是新增文章的 500 次 Embedding,而不是 10000 次 LLM 分类。

如果使用本地的 0.6B Embedding 模型,API 账单可以归零。真正的成本只剩本机的 CPU/GPU 时间和电费。

Embedding 与 LLM,不是大小模型之争

它们根本不是同一类工具。

维度 Embedding 分类 LLM 分类
核心任务 计算语义距离 阅读、推理并生成结论
输出 固定长度向量 文本或 JSON
多主题成本 文章向量可复用,主题向量可缓存 主题越多,Prompt 与判断负担越重
稳定性 相同模型和输入下结果稳定 受 Prompt、采样和模型版本影响
延迟 编码后直接返回,适合批处理 需要逐 Token 解码
可解释性 可以看到相似度、最佳范文和阈值 可以生成解释,但也可能事后合理化
擅长 主题匹配、召回、粗筛、聚类 复杂规则、跨文档推理、摘要与改写
本地部署 小模型即可,资源要求较低 通常需要更大模型和更多资源
日常边际成本 运行时接近 0 每次判断都继续消耗 Token

标题虽然写着「不需要 LLM」,复杂规则和生成任务还是要用它。比如「提到了 AI,但不是投融资新闻,也不是产品发布,还得包含可复现代码」,一个相似度阈值多半不够。把多篇材料压成一段有观点的综述,Embedding 更写不出来。

但只判断「像不像」时,没必要调用一个会推理、会写作、会解释的大语言模型。很多 Harness 的浪费,不是模型太贵,是模型摆错了位置。

用户只给一个主题名,范文从哪里来?

上面的 FreshRSS-AutoLabel 有一个前提:用户愿意认真写范文。

现实里,大多数人只会输入四个字:「科技向善」。

这四个字太短了。它可能指无障碍技术、数字普惠、未成年人保护、医疗 AI,也可能只是企业公益稿。直接拿它去做 Embedding,主题边界会很模糊。

我维护的另一套企业内个性化舆情日报系统,面对的就是这个问题:多名用户分别订阅多个主题,系统每天从数百篇文章里挑出与各自主题相关的写作线索。

这里仍然需要 LLM,但只在用户首次订阅主题时用一次。

用户输入主题名和一句可选描述后,LLM 会生成 3—5 条正向范文,以及 2—3 条负向范文。

正向范文回答「什么样的文章应该被选中」;负向范文回答「什么东西看起来很像,但应该排除」。随后,这些范文被 Embedding 并存进数据库。从第二天开始,主题标准已经固化成一组向量,不再需要 LLM 逐篇判断。

我后来把 LLM 留在了这里:

让 LLM 定义标准,而不是每天执行标准。

定义主题是低频工作,需要语言能力;执行匹配每天重复,更适合矩阵运算。把两者拆开,LLM 就不用在流水线上逐篇审稿了。

这套系统对每篇素材只生成一次 Embedding,并缓存到 PostgreSQL + pgvector。每天的主题匹配,主要是素材矩阵与范文矩阵相乘:取素材与所有正向范文的最大余弦相似度,再经过负向关键词硬过滤、Top-K 和最低分阈值。

有意思的是,实测中负向范文不一定适合直接参与减分。原本看起来更「智能」的 正向相似度 - 负向相似度,反而可能搅乱已经很干净的正向排序。因此,日常主分只取 max(正向相似度),对「融资」「股价」「IPO」这类稳定噪声,直接用字符串关键词做硬过滤。

能用一行 if 关键词 in 文本 解决的问题,就不要召唤一块显卡。

聚类与去重,也不必找 LLM 开会

筛出相关文章后,还有两个麻烦:

  • 十家媒体可能都在报道同一件事;
  • 同一条新闻可能连续三天换着标题出现。

照前面的路子,当然可以再把文章交给 LLM 分组、判重。但对新闻标题来说,一个上世纪的字符串算法往往就够了:n-gram。

n-gram 会把文本切成所有长度为 n 的连续片段。比如「腾讯发布混元大模型」的 2-gram 包括「腾讯」「讯发」「发布」「布混」「混元」「元大」「大模」「模型」。再加上 3-gram 和 4-gram,就得到一组可以直接比较的字符片段。

我使用字符级 2—4 gram,而不是中文分词。原因很简单:它不需要词典,不会被分词错误拖累,中英文混排也能直接处理。AI HarnessDeepSeek 和中文标题放在一起,并不妨碍它工作。

两段文本的相似度使用 Overlap Coefficient:

overlap(A, B) = |A ∩ B| / min(|A|, |B|)

分母取较小集合,而不是像 Jaccard 那样取并集。新闻标题经常一长一短:「腾讯发布混元」和「腾讯正式发布混元大模型并开放 API」明显是同一件事。如果用并集做分母,长标题新增的大量片段会稀释相似度;Overlap Coefficient 更关心「短标题有多少被长标题覆盖」。

在企业舆情日报里,事件聚类先用 Embedding 找到语义相近的候选,再用 n-gram 做二次确认。向量负责召回,n-gram 负责把「都在谈 AI、但并不是同一件事」的文章拆开。满足条件的文章通过并查集合并成事件簇。

跨天去重则更直接:只在同一主题内,把今天的标题与过去三天已保留的标题和摘要首句比较。高于阈值就标记为重复。它是纯字符串集合运算,成本接近零,而且每一步都可以复现。

最后才轮到 LLM:把筛选、聚类、去重后剩下的少数事件簇,写成 200—320 字的线索综述。

原来要读 500 篇的模型,现在只处理十几个小簇。LLM 负责最后一公里,不再蹲在入口做全量安检。

如果用户连主题都不填呢?

固定主题日报再往前一步,会遇到更难的问题:用户不想维护主题。

这正是我做邸报时面对的场景。

邸报是一套自托管的个性化 RSS 阅读引擎。用户只需要正常阅读、收藏、稍后读、点赞、隐藏和标记不感兴趣。系统不要求用户先写「我关心 AI Infra、中日经济对比、消费电子和县城经济」。主题会从行为里自己长出来。

我没有再让 LLM 总结一份用户画像,而是在本地维护多个动态兴趣簇。

当用户收藏一篇文章时,系统取得这篇文章已有的 Embedding,和现有正向兴趣簇比较:足够相近,就用加权方式更新这个簇的中心;不够相近,而且行为信号足够强,就创建一个新簇。

new_centroid = normalize(
  old_centroid × (1 - learning_rate)
  + article_vector × learning_rate
)

为什么不是把所有喜欢的文章平均成一个「用户向量」?

因为一个人可能同时关心 AI Infra、中日经济对比、消费电子、宏观经济和本地生活。把它们平均起来,只会得到一个谁也不像的中间点。多个兴趣簇,才允许一个人同时拥有互不相干的兴趣。

正向和负向也要分开。喜欢 AI,不等于喜欢每一种 AI 新闻;对某类融资稿点了「不感兴趣」,不应该把整个 AI 兴趣一起拉低。因此邸报分别维护正向簇与负向簇,负向更新和合并更加保守。

行为也不能一视同仁。收藏、点赞、读完是强信号;打开和读到 25% 只是弱信号;快速退出主要影响短期惩罚,不应该立刻创造一个永久兴趣。否则用户只要误点一次,画像就会被带跑。

兴趣还会衰减、合并和裁剪。最近三天突然关注的发布会,可以进入一个半衰期约 18 小时的短期意图向量;长期没有证据的兴趣簇会变弱;非常相近的簇会合并;低权重的单样本簇会被删除。

所谓「无限主题」,不是在 Prompt 里塞进无限个主题,而是让主题成为会生长、会衰减的本地数据结构。

Embedding 只是地图,不是推荐系统

做到这里,还不能直接按相似度从高到低发日报。

Embedding 对语义很敏感,却可能错过公司名、人名、缩写、代码名和刚刚出现的新词。因此邸报还使用 SQLite FTS5 与 BM25,从用户有行为的文章里提取长期和短期关键词画像,补一条精确词项召回通道。

FTS5 是 SQLite 自带的全文搜索模块。它会按照配置的 tokenizer 把标题、摘要和正文拆成词项,建立一份倒排索引:某个词出现在哪些文章、出现过几次、位于哪个字段,都可以提前记下来。查询时不必逐篇扫描全文,直接从索引里找出包含目标词的文章。

BM25 负责给这些文章排序。一个词在某篇文章里出现得越多、在整个文章库里越少见,通常得分越高;同时它还会修正文档长度,避免长文单纯靠词多占便宜。邸报还给标题、摘要和正文设置了不同权重,所以「DeepSeek」出现在标题里,会比埋在正文末尾更值得关注。Embedding 负责找语义上相近的内容,FTS5 和 BM25 则把专名、缩写与新词捞回来。

候选文章来自多个桶:最近文章、与兴趣簇相似的文章、命中关键词的文章、收藏或稍后读的文章,以及用于增加来源多样性的文章。把这些候选合并后,才进入混合打分:

推荐分 =
  语义相似度
  + BM25 关键词分
  + 新鲜度
  + 来源偏好
  + 文章状态
  - 负向兴趣惩罚
  - 重复惩罚
  - 过度曝光惩罚

新文章还没有 Embedding 时,会得到一个临时保护分,避免它因为后台任务尚未完成就永远沉底。

初步排序后,还要做一次类似 MMR 的多样性重排。同一来源、同一重复组、同一兴趣家族在前排出现太多,后续文章就会被压下去。用户想要的不是「最像自己兴趣的 20 篇同质文章」,而是一份有覆盖面、有密度的日报。

MMR 是 Maximal Marginal Relevance,通常译作「最大边际相关性」。它不是一次性把文章按分数排完,而是一篇一篇往结果集里放:每轮既看候选文章本身有多相关,也看它和已经选中的文章有多重复。可以粗略写成:

MMR 分数 = λ × 相关性 - (1 - λ) × 与已选内容的重复度

λ 越高,排序越贴合原始相关性;越低,系统越愿意牺牲一点分数来换取更多主题和来源。邸报没有只比较文章文本,还把同一来源、同一重复组和同一兴趣家族都算进惩罚里。这样第二十篇「同样很相关」的 AI 新闻,会让位给一篇分数稍低、但能补上其他主题的文章。

邸报甚至有一个谨慎的本地 FTRL 模型,用用户的行为去轻量校准语义、关键词、来源、新鲜度等特征的权重。但它先在 Shadow 模式训练,样本不足时不影响排序;真正启用后,占最终分数的比例也受到上限保护。

FTRL 是 Follow-The-Regularized-Leader 的缩写,是一种适合在线学习的轻量算法。它不需要定期拿全部历史数据重新训练,而是每收到一次新反馈,就小幅更新一次特征权重。用户收藏或读完一篇文章,可以算正反馈;快速退出、隐藏或标记「不感兴趣」,则算负反馈。跑久以后,模型会逐渐学到这个用户更看重语义匹配、关键词、来源还是新鲜度。

它不是另起一套推荐系统,而是在原有规则分上做校准。邸报先让 FTRL 在 Shadow 模式里旁观:照常训练和预测,但结果不进入正式排序。高质量样本积累到一定数量后才允许启用,而且只以很小的比例混入最终分数。这样既能利用个人行为调整权重,也不至于因为早期几次误点就把整个日报带偏。

Embedding 不是推荐系统,它只是地图。

用户的每次行为都在移动地图上的兴趣中心。排序器再拿着这张地图,在兴趣、新鲜度、来源、重复、探索和负反馈之间算账。

推荐理由也不必让 LLM 现编。系统把各项分数和证据保存下来,就能告诉用户:这篇文章命中了哪个兴趣簇、哪些关键词、哪个高权重来源,又因为哪些重复或负向信号被降权。这种解释来自真实计算过程,而不是模型看完结果后的合理化作文。

真正省 Token 的方法,是让模型退出主循环

三套系统的差别,其实是用户给系统的东西越来越少。

FreshRSS-AutoLabel 里,用户自己写范文,文章只需 Embedding 一次,再与所有固定主题匹配。

企业内个性化舆情日报里,用户只给主题名。LLM 在订阅时生成主题范文;日常筛选、排序、聚类和去重交给 Embedding、关键词与 n-gram,最后再让 LLM 写线索综述。

到了邸报,用户连主题也不用给。收藏、读完、点赞、隐藏和「不感兴趣」会慢慢长成正负兴趣簇,再与 BM25、新鲜度、来源、多样性和本地轻量学习一起完成排序。

小模型没有胜过大模型。成本是靠架构省下来的:该用 LLM 时用,不该用时让它退出。

最后,把开头的扣子解开

开头拿今日头条做了引子,但我不得不说,这是个写作技巧,因为它和本文的三套系统其实对不上。

大规模、多用户推荐系统通常不靠「文章与几个主题范文的相似度」吃饭。

主力是协同过滤算法,以及后来长出来的整套召回和排序体系。协同过滤算法其实大家反而更熟悉一些,就是前些年很多自媒体都科普过的:与你行为相近的人喜欢什么,系统就更可能把什么推荐给你。它吃的是 用户-物品 之间的大规模行为关系,不只是文章内容。

本文讲的内容匹配、向量相似度、关键词检索、聚类、去重和多样性重排,更像上一代推荐系统里的边角技术:它们用于冷启动、内容召回、特征补足、重复控制和排序校正,而不是单独扛起一个今日头条。

可个人日报恰好没有平台的条件。

你没有数亿用户,没有足够密集的 用户—文章行为 矩阵,也不需要预测陌生人下一秒会不会继续滑动。你只有一个人或一小群人的订阅源、几百篇文章,以及一个更朴素的目标:把真正值得看的东西先捞出来。

在这个尺度上,推荐系统的「边角技术」已经够用了。

对从 LLM 时代才进入算法与工程世界的 Vibe Coding 一代来说,这些旧技术值得补课。Embedding、余弦相似度、BM25、n-gram、SimHash、兴趣簇、MMR、FTRL,不如大模型性感,但便宜、稳定,出了问题也知道该从哪里查。

做 Harness 时,我现在会先问一句:这一步的“智能”真的需要 AI 吗?毕竟“智能”这个词早在这一轮 LLM 爆发之前,就已经出现在几乎各类软件和家用电器里了,也许我所需要的根本不是一个 AI 级别的智能。

如此这般,省了很多 Token。

当然,如果你看不懂本文,也可以直接把本文发给你的 Vibe Coding Agent 说:我不想接 LLM 了,你看看这个方案行不行。

最后的最后

最后的最后,给我的 Fiar-Code 项目邸报做一个广告。这是一个个人版的“头条”,它实现的效果是:首先做一个 RSS 阅读器,然后在你的订阅范围内,依据你的阅读行为进行个性化排序。

它适用于你有很多 RSS 订阅,每天 Inbox 里有 400 篇以上的文章入账,不可能把所有内容看完,但又想有个算法帮你快速筛选出你关心的内容,并且不想给 LLM 模型交大额账单。

同时,它是免费、自部署、代码可审计、数据不出站的,可以满足你的隐私需求,不用担心你的行为数据被大平台拿走当广告。

最重要的是,正如本文介绍的,它只需要一个 0.6B Embedding 模型驱动,你甚至可以在本地使用 Ollama 驱动(Macbook 连风扇都不转),不依赖任何第三方 API,真正实现 0 账单智能。

官网是:https://dibao.app

欢迎自取。

这个项目因为我现在每天都在高频自用,因此会在长时间保持维护。

为什么说 Anthropic 是邪恶的?

2026-07-01 13:59:02

如果你重度依赖海外 AI 工具,又恰好生活在中国,你大概早就习惯了”赛博二等公民”的待遇。

你得找干净的节点,得注册海外的信用卡,得时刻担心那个好不容易养起来的账号,会不会在某次风控里被”连坐”封掉。

但 Anthropic 这次干的事,还是超出了我的想象。

2026 年 6 月 30 日,Reddit 的 r/ClaudeCode 板块。一个用户发帖,标题简单粗暴:Claude Code 在给你贴标签。

发帖人 LegitMichel777 说,自 Claude Code v2.1.91 版本起,只要把它接到代理服务器(proxy),并且系统判定你“跟中国有关”,它就会在每一次请求里,悄悄改写你打出的标点。[1]

具体到什么程度?开发者 thereallo 把客户端代码拆开,逆向了一遍:日期里的短横“-”被换成斜杠“/”;句子里最普通不过的一个撇号“’”,被替换成几个人眼几乎分不出来的 Unicode 变体字符。[2]

这条帖子冲上了 Hacker News 首页,拿了 605 分。评论区当场吵翻。

我第一反应真的是想笑。一家把“安全”刻在招牌上的公司,一家标榜自己是全宇宙最在乎人类命运的 AI 实验室,煞费苦心地在文本里埋了一个隐形指纹,专门用来标记“这个人可能跟中国有关”——结果被一个极其无聊的、专门针对标点符号的怪癖当场抓包。

但笑完,是真的不舒服,甚至感到一种生理性的恶心。因为比起光明正大地写明”禁止中国相关实体使用”,Anthropic 选择了明知故犯地隐瞒。

在历史上,很多组织都干过类似的事情,而与 Anthropic 最相似的是纳粹——给犹太人的护照盖一个“J”字,并告诉他们:这只是个符号,没什么大不了的。

这篇文章不打算讲隐私,隐私在这个语境下显得太小儿科了。因为 Anthropic 干的这件事比隐私深沉得多——它不是在收你的数据,它是在定义你的身份。

这是一个从“你是谁”出发、而不是从“你做了什么”出发的判断系统。

1. 用撇号传递信息

为了后续的讨论,我们需要先复述一遍 LegitMichel777 讲述的技术细节,如果你已经了解了,可以跳过接下来的几段。

Claude Code 的歧视代码触发条件非常具体,具体到你能看见写下这行代码的人那张充满算计的脸:环境变量 ANTHROPIC_BASE_URL 被设置,说明请求经过了代理;系统时区落在 Asia/ShanghaiAsia/Urumqi

命中之后,Claude Code 会做两件事:把请求里的日期格式从 2026-06-30 强行改写成 2026/06/30;把普通的撇号 ' 换成 Unicode 变体——命中域名黑名单换成 \u2019,命中“中国实验室关键词”换成 \u02BC,两条都中,换成 \u02B9。[2]

这几个字符,肉眼几乎看不出差别。放进任何一个普通的文本编辑器,你会以为这就是标准的英文右单引号。它们的差别只存在于字节层面,只有会读 Unicode 编码表的人、或者是接收这些数据的 Anthropic 服务器,才看得出来。

这还不够,域名黑名单和关键词列表怎么藏?他们先用 base64 编码,再用密钥 91 做一次 XOR 混淆。解出来的关键词,是 deepseek、moonshot、minimax、zhipu、baichuan、stepfun、01ai、dashscope——挨个数下来,几乎把中文互联网能打得上号的大模型公司,点了一遍名。[2]

这道工序绝不是什么“顺手写的一行判断”,也不可能是 Anthropic 的实习生手滑。它是一个系统工程:先写一份名单,再把名单编码,再把编码结果做加密混淆,再把混淆结果嵌进产品里,让它在你完全不知情的情况下运行。

这里面的每一步都是深思熟虑的决定,每一步都要有人经过代码审查。

这就是我不能用“偏见”而一定要用“歧视”来概括这次 Anthropic 的行为。因为算法偏见可能来自数据中的无意识样本偏差,但歧视代表着主动决策。

但 Claude Code 里所做的行为,恰恰是有主语和主观能动性的。

有人写了一个 if 判断你是谁。有人选了要屏蔽的公司名单。有人决定把这份名单藏起来,而不是写进用户协议第几条。有人测过,这套水印在正常使用中不会被肉眼发现。这每一个“有人”都是真实存在的职务角色:提出这个 feature 的产品经理、批准它的 tech lead、在 Code Review 里点了 Approve 的那个同事、把这个版本推上生产线的 release manager。

我知道科技圈不爱听“共犯”这个词,但它就是共犯。

你可以说,Claude Code 目前干的事,无非是往请求里塞一个隐形水印,又没打你、没抓你、没冻结你账户。这话没错。可翻开历史看看,每一次大规模的排斥,最初都只是“先记一下”。至于名册建好之后会发生什么,从来不是写名册的人自己决定的——写名册的人,只是把决定权提前让渡给了未来某个使用这份名册的人、或者某项疯狂的政策。

我甚至可以想象 Anthropic 内部的动机逻辑。他们大概觉得自己在执行某种正当的商业防御:这些中国 AI 公司确实在“非正常竞争”,确实在“蒸馏”他们的模型,所以标记一下、收集一点数据、留一条后路,是合情合理的应对。

但问题是,大模型本身是一种在使用方法上对后端全透明的技术,也就是从理论上来讲,Anthropic 可以通过行为识别来解决所有“不符合规定的使用”,而不是圈定一个“不符合规定的人群”。

而采用隐蔽的方法来传递用户身份的侦测,更说明了 Anthropic 自知这样的划分并不名正言顺。因为如果它真的认为自己正当、正确、正义,可以参照 Stripe,以及全球任意一家互联网金融公司那样通过有效证件对用户进行真正的 KYC。而不是偷偷识别“这个可能是中国人”,再偷偷传回总部。

直到今天,Anthropic 依然没有对这次指控做出公开回应。沉默,就是最傲慢的态度。

我猜他们不是不想回应,是没法回应。解释为什么埋水印,等于承认埋了水印;解释为谁埋的、用什么标准判定”跟中国有关”,等于把一份歧视清单摊在桌面上给全世界看。不回应,至少还能躲在”不予置评”后面假装这件事不存在。

但这件事不会因为他们不回应就消失。代码已经被反编译,XOR 密钥已经公开,域名列表已经摊在 GitHub 上被全世界传阅。Anthropic 的沉默不是危机的结束,只是他们还没有想好一个不那么难看的说法。

2. 定义即暴力:从颅骨到时区

暴力这个词,在现代人的语境里,太容易让人先想到枪、集中营、毒气室。但研究种族灭绝的历史学界早有共识:真正决定谁会被杀的那一步,往往发生在很多年前,一张纸上,一次毫无波澜的登记里。

1935 年,纳粹德国颁布《纽伦堡法案》(Nuremberg Laws)。这部法案做的第一件事,不是抓人,是重新定义”谁是犹太人”。以前,这个身份多少带点宗教和文化认同的意味——你有犹太信仰你就是犹太人,你改宗了你就可以不是。法案之后,身份变成了纯粹的血统算术:查你祖父母四人里有几个是犹太人,划进”犹太人”或”米施林格”(Mischlinge,混血)的不同等级,再细分出四分之一、二分之一血统的类别。[3]

这套分级表在实际执行中演化出了一种荒谬:一个人可能一辈子没进过犹太教堂、吃猪肉喝啤酒、甚至已经受洗成为基督徒——但只要档案里写着你有一位犹太祖父母,你就是法律意义上的犹太人。同样,一个虔诚的犹太拉比如果祖父母四人凑巧只有三个是被归为犹太血统的,他反而被分进”一级混血”,可以暂时保住工作和财产。宗教、文化、自我认同,在这张表面前全部作废。唯一的真实,是血统档案上的那四个格子。

这套分级表画出来像一份遗传学作业。极其精确,极其官僚,极其冷。它冷的地方在于:一旦你被归进某一格,能不能上学、能不能行医、能不能结婚、能不能保有财产,全部按格子走,不需要再看你这个人到底是谁。你的灵魂不再重要,你的成分决定了一切。

护照上盖一个“J”字,是这套分级表最后、最可见的产物。真正干活的,是前面那张分级表。盖章的公务员,只是在执行一份早就做完的分类。

但分类要落到几百万人头上,光靠人手写名册是不够的。这时候,一家美国科技巨头帮上了忙:IBM。

IBM 通过德国子公司 Dehomag,向纳粹政府提供了 Hollerith 打孔卡制表系统。1933 年的人口普查用的就是这套系统——不只是数人头,而是能按“种族”“宗教”“职业”这些维度交叉检索。历史学者 Edwin Black 在《IBM 与大屠杀》里详尽地还原过这条链路:普查数据摸清了犹太人口的分布,隔都居民被逐一统计。到了集中营,囚犯的复杂人生被压缩成一串五位数编号,刻在袖标上,用打孔卡系统追踪调配劳动力。[4]

分类系统先于灭绝到位,灭绝才谈得上被“流水线化”。没有硅谷先驱的前代技术,那套暴力系统根本跑不出那么高的效率。

Edwin Black 在书里记录了一个细节,任何人看l都会不寒而栗:IBM 不仅卖了机器,还派了工程师去德国维护这些机器,定期检修,确保打孔卡系统运转良好。换句话说,IBM 从头到尾知道自己的客户在拿这些机器干什么。但他们没有停下来。因为生意就是生意。

集中营内部还有一整套色标系统——三角形的颜色和位置,标记你是政治犯、犹太人,还是“反社会分子”。管理者一眼就能分辨,囚犯却常常读不懂自己身上贴的是什么。[5]

这才是最关键的一点:标记的可读性是不对称的。写标记的人看得懂,被标记的人看不懂。

把这套逻辑,原封不动地摆到 Claude Code 旁边对照一遍。

Claude Code 会检测你的时区是不是 Asia/Shanghai,跟纽伦堡式的“居住地/血统普查”是同一个动作,只是普查对象从“你祖上是哪个民族”,换成了“你的系统时钟设在哪儿”。撇号被换成一个 Unicode 变体,跟集中营里那个只有管理者看得懂的色标三角形,也是同一个动作,只是载体从衣服上的布料换成了网络传输的字节。

一个是墨水戳在纸上,一个是零宽度级别的字形替换。技术上,二者相差了大概九十年的载体演进。逻辑上,它们是同一件事:先给你建一份档,再决定拿这份档怎么用——而你,作为被标记的对象,全程不知道自己已经被记录在案。

我知道有人到这里会觉得我危言耸听:一个破撇号而已,至于类比到纳粹和集中营吗?至于。

因为我不是在类比暴力程度,我是在类比制度设计。纳粹的色标系统不需要集中营的焚化炉才能成立——它本身就是一个独立的、完整的、自洽的分类装置。

即使没有后来的大规模屠杀,这套色标系统本身也已经构成了一种暴力。因为它剥夺了被标记者对自己身份的叙事权。Anthropic 的水印也一样。你不需要等到某天 Anthropic 拿着这份数据库向政府交名单,才能说这件事是错的。它在你不知情的情况下替你完成了一次分类、并把这个分类永久记录在你的请求流里——光是这个动作本身,就已经越过了底线。

这里可以再摆一组对比,会更扎眼一点:德国用血统证明“纯洁”,美国用肤色证明“纯洁”,Anthropic 用时区和域名证明“安全”。三套系统操心的东西,表面上完全不同——种族、肤色、地缘政治——底下用的,却他妈是同一套官僚工具箱:先划出一个“他者”的范畴,再给这个范畴配一套可执行的判定规则,最后让规则自动运行,运行到不需要任何人再做一次良心上的判断。

这才是分类系统真正恐怖的地方。它不需要执行者恨你,它只需要执行者照着产品经理的表格填字段。

Anthropic 的工程师大概没有一个人怀着种族仇恨写下那个 if 判断。这恰恰是问题所在——作恶不再需要恨意做燃料,只需要一份需求文档,和一个愿意按需求文档写代码、并且放弃追问的打工人。

3. 一滴血与一个域名

如果说纳粹的分类学野蛮而张扬,那么美国的种族隔离制度则完美示范了另一种可能:野蛮可以完全不需要张扬,甚至可以包装成一套行政流程。

“一滴血规则”(one-drop rule),字面意思就是它的定义:只要一个人的血统里有“一滴”黑人血统——哪怕祖上八代只有一位——法律上就该被归为黑人。这不是一句民间俗语,这是美国多个州曾经白纸黑字写进法律的正式规则,学术上叫 hypodescent(血统从劣原则)。[6]

这条规则最诡异的地方,不在于它显而易见的歧视,在于它把“你是谁”这件事,完全交给了行政官员手里的那支笔。弗吉尼亚州有一位名叫 Walter Plecker 的登记官,靠着一部《种族纯洁法案》(Racial Integrity Act),可以单方面把整个混血家族,重新划进“黑人”的档案。这家人可能几代都被当作白人生活,但 Plecker 一份文件,身份就被强行改写了。没有法庭,没有申诉,一份表格就是终审判决。[7]

定义权,就是暴力权。你不需要在街上打人,只需要有权决定“这个人是什么成分”,剩下的暴力,会由整套社会的齿轮自动执行。

隔离制度另一件招牌产品,是“红线区”(redlining)。1930 年代,美国联邦机构 HOLC(房屋所有者贷款公司)给全国主要城市画风险评级地图,用红笔圈出“危险”街区——住着少数族裔的社区,几乎毫无悬念地全被圈进红区。银行照着这份地图放贷,红区居民几十年贷不到房贷,财富积累从地理层面被物理锁死。

这份地图不是公开羞辱,它甚至不需要挂在任何一户人家门口。它躺在银行和政府机构的档案柜里,安静地决定着一整代人能不能买房、能不能积累资产、能不能把房子留给下一代。你从街上走过,看不出这条街被画了红线,你只会发现,自己去申请贷款,总是莫名其妙地被拒。

在这条规则运行的三十年间里,整整一代美国黑人家庭被锁在财富积累的门外,而他们身边的白人邻居用同样的收入水平、同样的还款能力,拿到了贷款、买了房、把房子升值后的财富传给下一代。

今天美国白人和黑人之间的财富差距,有相当一部分可以直接追溯到这几张地图——它们在被废止几十年之后,依然像幽灵一样影响着下一代人的资产负债表。这就是隐蔽分类的真正威力:它的伤害不发生在被标记的那一刻,而是发生在被标记之后每一个看似中立的“正常流程”里。银行从来没有在你的贷款申请表上写“黑人”两个字,它只是查了一下你的地址,然后查了一下那张地图,然后把你的申请表放进“不批准”那摞文件里。

饮水机上那块写着“Colored”的牌子,公开、羞辱、刺目,是隔离制度最容易被记住的画面。但红线地图告诉我们一个更冷的事实:真正决定命运的排斥,往往不需要一块牌子。它藏在流程里,藏在评级表里,藏在一份没人会主动给你看的档案里。

这正是我看到 Anthropic 那份 XOR 混淆域名黑名单时,最先想到的画面。

base64 编码,加一次密钥为 91 的 XOR 混淆——这道工序,在功能上和红线地图一模一样:把一份“谁该被特殊对待”的名单,从公开可见,改造成隐蔽可执行。它不写进用户协议,不出现在任何一份产品说明里,就躺在代码深处,安静地决定着你的请求会不会被悄悄改写。

从饮水机牌子到 Unicode 水印,人类文明进步的似乎只是隐蔽性:排斥的效率提高了,而排斥的可见度反而降到了零。

如果这一切还只停留在一个开源社区的技术八卦上,也许还能被归为“某家公司的产品设计争议”。但就在一个多月前,这套逻辑已经从代码层面,堂而皇之地升级成了国家行为。

2026 年 6 月 12 日,美国政府以国家安全为由,下令暂停任何外籍人士使用 Anthropic 的 Fable 5 和 Mythos 5 模型。注意官方声明那咬文嚼字的措辞——不论此人身在美国境内还是境外,连 Anthropic 自己的外籍员工,也一并被切断访问。[8]

这里要解释一下这条禁令背后的法律逻辑,因为它在中文世界几乎没有对应物:美国出口管制体系里有一个概念叫“视同出口”(deemed export)。意思是,把受管制的技术信息交给一个外国人——哪怕这个人此刻就坐在加州硅谷某间豪华办公室里,甚至持有美国合法工作签证——在法律上,等同于把这项技术直接出口到了他的母国。判定标准不是这个人身在哪里,不是他为哪家公司工作,不是数据中心设在哪个法域。判定标准只有一个:他生而为谁。

这条禁令切断的人里,甚至包括 Andrej Karpathy——一位在 AI 圈家喻户晓的研究者,持有 EB-1(美国“杰出人才”)绿卡,早已是美国永久居民。他没有做错任何具体的事,甚至为美国的 AI 产业立下过汗马功劳。但他被挡在门外的唯一理由,是他的出生地。

这不就是一滴血规则的 2026 年版本吗?只是评判标准从“血统比例”,换成了“国籍出身”。一旦被判定“不纯”,你身处帝国心脏、手握顶级人才绿卡,也无济于事。Anthropic 最终顺水推舟,选择在全球范围下线这两款产品,以完成所谓的合规。

这里得插一句话,避免被读成自打自脸。我自己之前写过一篇《AI 也该有护照了》 ,主张给 AI 系统一个透明、可问责的国籍标识。乍之一听,这两篇文章好像在自相矛盾:一篇在帮 AI 许国籍,一篇在质问国籍引发的差别待遇。

但它们其实是同一套逻辑的两面。“国籍”作为一项公开规则,本身没有问题:它写在法律里,写在签证表格上,你知道规则存在,也知道自己会被怎样对待——这是可以拿到桌面上争论、修正、申诉的秩序,一种“护照”式的秩序。

Anthropic 在 Claude Code 里做的事,性质完全不同:它没告诉你规则是什么,甚至没告诉你规则存在。你的时区、你连的域名,在暗处被换算成一个关于“你是谁”的判断,这个判断会不会影响你、以什么方式影响你,你无从知晓,也无从申诉。

如果用中国人近代经历过的创伤记忆来解释,Anthropic 更像是给人发了一张“良民证”,而不是在你的护照上签发了一张签证。良民证是占领当局发给被统治者的身份证明,用来证明你“暂时没问题”,发放和收回的权力,全部单方面握在统治者手里,随时可能因一条你看不见的规则被收走。

护照式的国籍秩序,问题可以拿到桌面上吼;良民证式的隐蔽分类,连吼的资格都不给你。

我知道肯定有人会跳出来洗地,说国家安全考量和种族隔离不是一回事,一个关乎技术管制,一个关乎种族仇恨,动机天差地别。这话我只同意一半。

动机确实不同——没有政客能在 2026 年的国会发言里直接喊“血统纯洁”这种话了。哪怕是现在全球政坛都在右转,这也是大逆不道的话语体系。

但一滴血规则和视同出口原则,用的是同一套底层判断逻辑:不问你做了什么,只问你生而为谁;不给你辩护的余地,因为你的身份本身就是原罪证据。

我们总以为隔离制度的恶,在于它公开、羞辱、刺目。但真正高效的排斥制度,从来不需要张扬。它悄悄发生,被排斥的人甚至察觉不到自己已经被归入了另一个格子,直到某一天,贷款被拒了,请求被悄悄改写了,或者账号被直接切断了——才后知后觉地发现,原来早就有一张表,把你放在了“需要处理”的名单里。

Anthropic 选的,正是这条最高效、也最恶心人的安静之路。

4. 以安全之名

Anthropic 这个名字,原本取自信息论之父克劳德·香农(Claude Shannon);“Anthropic”本身在英文里是“人本主义”的意思,疯狂暗示这家公司要做“以人为本”的 AI。招牌产品直接叫 Claude。这整套充满理想主义光环的品牌叙事,从起名字的那一刻起,就在声情并茂地向全世界布道:我们是最讲安全、最讲对齐、最在乎全人类福祉的那家 AI 实验室。

他们甚至提出过一套叫 Constitutional AI 的训练方法:给模型发一部“宪法”,让它按一套明确写下来的所谓普世价值观去自我约束、自我修正。CEO Dario Amodei 常年在公开场合像个传教士一样大谈“AI 安全”“对齐人类价值”“负责任的扩展”,几乎把这些大词直接焊在了公司的 Logo 旁边。

这套叙事讲了太多年,讲到大家耳朵都快起茧子了,讲到几乎没人会退一步追问一句最基本的问题:所谓的安全,到底是对谁的安全?

同一家公司,一边在官方博客上慷慨陈词“我们致力于让 AI 系统对齐全人类的价值观”,一边在客户端产品里埋了一段比木马还隐蔽的代码,专门用来给“跟中国有关”的用户悄悄换标点符号。

这还不是唯一的反差。今年早些时候,Anthropic 曾致信美国国会,极其高调地指控中国同行阿里巴巴通过不正当手段“蒸馏”窃取了自家模型的能力。 这件事本身就很有戏剧性——“蒸馏”是一个在 AI 行业被广泛使用的技术手段,开源社区每天都在互相蒸馏,Anthropic 自己创立之初也没少用公开数据集训练。但当“蒸馏”的对象变成了中国公司,这件事就立刻被升级为“盗窃国家机密”级别的指控,被直接写进了一封给国会的正式信函。

Anthropic 此前曾经多次发表报告指责中国官方和企业利用 Claude 进行一些违反美国法律或其使用协议的恶意行为。但成文法与种族歧视最大的区别就在于其不应以身份进行惩罚,而应以行为进行惩罚。

如果我们将 Anthropic 的行为替换到其他领域,这个逻辑就会非常清晰:我们发现某一地区罪犯中的有色人种比例偏高,因此我们认定有色人种全员是罪犯,对他们进行更加严格的限制和监视。

换句话说,它其实并不在意你是否真的违反了它的用户协议,或用 AI 做了哪些不该做的事情。你只要能证明你是真正的,持有美国护照的美国人,那么你即便是做了这些也不会被封号。

这一逻辑恐怕在任何意识形态的现代司法区都是不允许的,它触及了现代文明某些更底层的共识。

再加上前面那道针对全球所有外籍人士——哪怕是自家核心员工——的 Fable 5 封锁令。

三件事摆在一起看,这家公司的“对齐人类价值观”,显然是想要把一些人类从“人类”这个词的定义里排除。

历史上的纽伦堡法案,正式名称叫《保护德国血统与荣誉法》。种族隔离制度最常见的自我辩护,是“保护种族纯洁”和“维护社会秩序”。今天,在科技圈,站在同一个语法位置上的词,换成了“AI 安全”。

“安全”是目前为止,人类发明出来的最好用、最廉价的道德外衣。它在很多情境下确实是重要的,但在很多情境下又是最好用的借口。

它不需要你撕破脸皮说出“我讨厌某个特定群体”,你只需要皱起眉头说一句“这一切都是为了安全”,剩下的排斥、监控、区隔、封锁,都可以顺理成章、堂而皇之地推行下去,甚至还能在推特上收获一波掌声。

更重要的是,Anthropic 不是那种被政府管制逼着改产品的受害者。它是在主动鼓励、甚至抢先于政府介入地缘政治,拿这种看似自我约束的行为当商业竞争的筹码。这不是被迫合规,是明确的主动作恶。

对一个普通用户来说,这才是整个事件中最魔幻、也最无力的地方:你可能完全不关心中美博弈,你可能连政治新闻都不看,你只是半夜坐在电脑前想用个编程工具赶个 deadline。结果你的输入被悄悄标记、悄悄改写,仅仅因为你恰好用着中国时区,恰好连了一个被他们列进黑名单的域名。

地缘政治的碾压不再需要你主动参战,它会像个尽职尽责的机器一样,主动把你算作战场的一部分。

利益不相关声明:评论尸本人自 2022 年起从未订阅过 Claude 的官方付费套餐及第三方未授权的 Claude 中转站服务,本文也不是因个人账号被封禁而怀恨在心撰写的泄愤之作。

参考文献

[1] LegitMichel777,”Anthropic embedded spyware in Claude Code…”,Reddit r/ClaudeCode,2026-06-30。链接

[2] thereallo,”Claude Code Is Steganographically Marking Requests”。链接

[3] USHMM,”The Nuremberg Race Laws”。链接

[4] Wikipedia,”IBM and the Holocaust”。链接

[5] USHMM,”Classification System in Nazi Concentration Camps”。链接

[6] Wikipedia,”One-drop rule”。链接

[7] African American Registry,”The ‘One Drop Rule’ in America, a story”。链接

[8] Anthropic,”Statement on the US government directive to suspend access to Fable 5 and Mythos 5″,2026-06-12。链接

邸报 v0.1.0:一个很旧的东西新生了

2026-05-30 09:30:54

你好,

久等了,邸报刚刚上线了第一个可公开安装的版本。

版本 v0.1.0
项目 邸报 Dibao
协议 BUSL-1.1
Github github.com/Pls-1q43/Dibao

邸报是什么?

简单来说,邸报是一个 RSS 阅读器,它把算法推荐放回你自己的 RSS 信源里。

邸报可以跑在你的 NAS、VPS 或本地电脑上。导入 OPML,添加 RSS 地址,像用任何阅读器一样阅读、收藏、标记。区别在于,邸报从你的行为里学习,在你订阅的文章中重新排序——不扩大信息来源,只在你选定的池子里,把更值得先看的东西浮上来。

每篇推荐都有解释。不是黑盒分数,是可以追问的理由。

如果你的 RSS Inbox 里每天也会新增上百篇文章,那么你一定会喜欢邸报。

邸报是免费的,没有中心化服务,不绑定任何 LLM API。接一个免费的 embedding provider(比如硅基流动)或在本地跑一个 0.6B 的模型,邸报就能有非常出色的推荐效果。

数据在你的持久化目录里。SQLite,一个文件,备份就是复制粘贴。

我在日记里把它叫做“外部嗅觉器官”。不替你判断,只在信息流里把可能接上你脑子里那条暗线的东西,先叼到你面前。

为什么做这个?

LLM 火了以后,“AI 个性化阅读”成了一个热门叙事。几乎所有方案都在让大模型直接吞掉你的信息流——总结、筛选、判断,每一步烧 Token。

但推荐从来不是生成问题,是匹配问题。

今日头条从来没问过你喜欢什么,你只要用,它就越来越懂你。核心不是语言模型,是行为数据 + embedding + 排序。这条路 2013 年就验证过了,只是没人想过把它接回 RSS。

因为没人觉得 RSS 还值得救。

我也曾经不想救它。2015 年我和几个朋友做了「赤潮 AKASHIO」,第一篇推送叫《互联网死了 23%,这只是开始》。赌的是长图文、订阅、读者自己选择信息来源这件事还有意义。十一年过去,媒介从长图文迁到短视频,订阅迁到推荐系统,赤潮自己因为名字变成敏感词被迫改名「红流」。中文互联网的信息分发权,几乎全交给了平台算法。

你大概和我一样:厌倦了平台替你决定该看什么,但又不想退回手工 RSS 几百篇未读堆成墙的日子。信源归你管,排序帮你做,数据留在你手里。

邸报试图占住这个位置。

现在可以做什么?

v0.1.0 已经发布。你可以用 Docker Compose 一键部署,五分钟跑起来。

README 里有完整的 compose.yaml 和 provider 配置指南。

如果你觉得好用,或者觉得这个项目的正走在正确的方向上,可以到 Github 上给个 Star。邸报是 source-available 项目,Star 是让更多还在用 RSS、还愿意自己部署的人看到它的方式。

遇到问题、有想法、或者只是想说一声“跑起来了”,GitHub Issues 随时开。

RSS 阅读器流行于 2000 年,推荐算法被广泛应用于 2013 年,而邸报诞生于 2026 年,这完全归功于 Vibe Coding。

邸报的所有代码由 AI 生成,正如我之前在 X 说的:我在尝试用很新的东西,做一种很旧的东西。

希望你喜欢。

安装时如果遇到问题,可以直接回到 GitHub Issues 里开帖。

如何给 Notion AI 接入第三方 API?

2026-05-12 09:07:10

我之前讲过将「哈勃半径」作为一种私人信息宇宙,并将它接入 Notion AI。

但问题是,Notion AI 如果不使用 Custom Agents 似乎无法接入第三方 API,而 Custom Agents 有高昂的使用费,如何解决这个问题呢?

这里补一个更工程化的实用技巧:通过 Cloudflare Worker 将任意第三方 API 接入 Notion AI。

我用博查搜索,来讲解如何操作。

它的核心原理很简单:

  • 第三方 API 通常要求 POST 请求,并且需要在请求头里放 API Key。
  • Notion AI 当前更适合通过 webpage.load 读取一个 GET 可访问的网页。
  • Notion AI 的计算机工具可以做 SHA-256 之类的哈希计算。
  • 所以中间需要一个 Cloudflare Worker 网关:对 Notion AI 暴露一个带签名的 GET 页面,对第三方服务发起真正的 POST API 请求,再把结果渲染成 HTML。

换句话说,它不是让 Notion AI 直接调用第三方 API,而是给 Notion AI 搭一座「可阅读的桥」。

如果你觉得下面的内容读起来很麻烦,也可以将这个文章直接丢给你的 Notion AI,让它教你如何设置。

一、为什么需要 Worker 网关

很多 API 的调用方式是这样的:

POST <https://api.example.com/v1/search>
Authorization: Bearer API_KEY
Content-Type: application/json

{
  "query": "搜索词",
  "count": 5
}

但 Notion AI 更容易处理的是一个普通网页:

Worker 做的事情,就是把后者翻译成前者。

Notion AI 访问的是一个 GET URL。Worker 收到 URL 参数,验证签名,把参数组装成 POST 请求,调用真正的第三方 API,最后把返回结果变成 HTML 页面。这样 Notion AI 不需要理解 API 的认证细节,也不需要使用 Post 方法来接触真正的第三方 API。

这实现了在不给 Notion 额外交钱(使用 Custom Agents)的情况下,使用默认版本的 Notion AI 来接入第三方 API。

二、最小可用架构

这个方案里有三个角色:

  1. Notion AI:负责理解用户意图、生成查询词、计算动态签名、读取网页结果。
  2. Cloudflare Worker:负责鉴权、参数转换、调用第三方 API、渲染 HTML。
  3. 第三方 API:负责真正提供搜索、数据库查询、模型推理或其他能力。

它的链路是:

用户问题
→ Notion AI 生成 query
→ 计算 ts + sign
→ webpage.load 访问 Worker 的 GET URL
→ Worker 验签
→ Worker 向第三方 API 发起 POST
→ Worker 把 JSON 渲染成 HTML
→ Notion AI 阅读页面并总结

这里最关键的一点是:API Key 不应该出现在 Prompt 里,也不应该出现在 Notion 页面里。它应该存放在 Cloudflare Worker 的环境变量中。

三、以博查搜索为例

博查 API 原本是一个搜索接口。我们希望 Notion AI 可以这样使用它:

搜索:2024 年诺贝尔物理学奖得主
返回:5 条结果
需要摘要:是

对应到 Worker 暴露出来的 URL,大概是:

其中:

  • query 是搜索词,必须 URL 编码。
  • summary 控制是否让博查返回长摘要。
  • count 控制返回条数。
  • freshness 可以限制时间范围,比如一天、一周、一个月、一年。
  • include 可以限制搜索域名。
  • exclude 可以排除搜索域名。
  • ts 是 10 位 Unix 时间戳。
  • signts + SECRET_KEY 的 SHA-256 哈希。

这个签名机制不是为了做到银行级安全,而是为了避免这个 Worker URL 被随便滥用。时间戳通常只允许几分钟内有效。

四、Worker 示例代码

你需要先在 Cloudflare Woker 上建立一个新的 Worker,然后填入以下代码:

// 辅助函数:计算 SHA-256 哈希值
async function generateSHA256(message) {
  const msgUint8 = new TextEncoder().encode(message);
  // 使用更严格的对象参数格式,避免部分 Worker 环境抛出 TypeError
  const hashBuffer = await crypto.subtle.digest({ name: 'SHA-256' }, msgUint8);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

export default {
  async fetch(request, env, ctx) {
    // ==========================================
    // 0. 拦截并放行 OPTIONS 跨域预检请求
    // ==========================================
    if (request.method === "OPTIONS") {
      return new Response(null, {
        status: 204,
        headers: {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "GET, OPTIONS",
          "Access-Control-Allow-Headers": "*",
          "Access-Control-Max-Age": "86400",
        }
      });
    }

    // ==========================================
    // 全局错误捕获边界,把 1101 错误转为可见的 HTML 报错
    // ==========================================
    try {
      const url = new URL(request.url);
      
      // ==========================================
      // 1. 配置项 (请替换为你的真实数据)
      // ==========================================
      const BOCHA_API_KEY = '博查 API Key'; 
      const SECRET_KEY = '你生成的一个 32 位随机 Key'; 
      const THRESHOLD_SECONDS = 300; 

      // ==========================================
      // 2. 动态 Token 验证逻辑
      // ==========================================
      const tsParam = url.searchParams.get('ts');
      const signParam = url.searchParams.get('sign');
      let isAuthenticated = false;

      if (tsParam && signParam) {
        const requestTimestamp = parseInt(tsParam, 10);
        if (!isNaN(requestTimestamp)) {
          const currentTimestamp = Math.floor(Date.now() / 1000);
          if (Math.abs(currentTimestamp - requestTimestamp) <= THRESHOLD_SECONDS) {
            const messageToHash = tsParam + SECRET_KEY;
            const expectedSign = await generateSHA256(messageToHash);
            if (signParam.toLowerCase() === expectedSign.toLowerCase()) {
              isAuthenticated = true;
            }
          }
        }
      }

      if (!isAuthenticated) {
        return new Response('<h1>403 Forbidden</h1><p>Invalid Signature or Expired Timestamp</p>', { 
          status: 403, 
          headers: { 'Content-Type': 'text/html;charset=UTF-8' }
        });
      }

      // ==========================================
      // 3. 提取参数与构建 Payload
      // ==========================================
      const query = url.searchParams.get('query');
      if (!query) {
        return new Response('<h1>400 Bad Request</h1><p>Missing parameter: query</p>', { 
          status: 400, 
          headers: { 'Content-Type': 'text/html;charset=UTF-8' }
        });
      }

      const payload = { query: query };
      if (url.searchParams.has('freshness')) payload.freshness = url.searchParams.get('freshness');
      if (url.searchParams.has('summary')) payload.summary = url.searchParams.get('summary') === 'true';
      if (url.searchParams.has('include')) payload.include = url.searchParams.get('include');
      if (url.searchParams.has('exclude')) payload.exclude = url.searchParams.get('exclude');
      if (url.searchParams.has('count')) {
        const countVal = parseInt(url.searchParams.get('count'), 10);
        if (!isNaN(countVal)) payload.count = countVal;
      }

      // ==========================================
      // 4. 发起请求并渲染 HTML
      // ==========================================
      const bochaResponse = await fetch("https://api.bocha.cn/v1/web-search", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${BOCHA_API_KEY}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify(payload)
      });

      const bochaJson = await bochaResponse.json();

      let htmlContent = `<!DOCTYPE html>
      <html>
      <head><meta charset="utf-8"><title>Search Results: ${query}</title></head>
      <body>
        <h1>搜索结果:${query}</h1>
        <hr>
      `;

      if (bochaJson.data && bochaJson.data.webPages && Array.isArray(bochaJson.data.webPages.value)) {
        const results = bochaJson.data.webPages.value;
        if (results.length === 0) {
          htmlContent += `<p>未能找到相关网页结果。</p>`;
        } else {
          results.forEach((item, index) => {
            htmlContent += `
              <article style="margin-bottom: 24px;">
                <h2><a href="${item.url || ''}">${index + 1}. ${item.name || '无标题'}</a></h2>
                <p><strong>来源:</strong> ${item.siteName || '未知'} | <strong>时间:</strong> ${item.datePublished || item.dateLastCrawled || '未知'}</p>
                <p><strong>摘要:</strong> ${item.snippet || ''}</p>
            `;
            if (item.summary) {
              htmlContent += `<p><strong>总结:</strong> ${item.summary}</p>`;
            }
            htmlContent += `</article><hr>`;
          });
        }
      } else {
        htmlContent += `<h2>API 请求出错或返回结构异常</h2><pre>${JSON.stringify(bochaJson, null, 2)}</pre>`;
      }

      htmlContent += `</body></html>`;

      return new Response(htmlContent, {
        status: 200,
        headers: {
          "Content-Type": "text/html;charset=UTF-8",
          "Access-Control-Allow-Origin": "*"
        }
      });
      
    } catch (error) {
      // 如果再遇到致命错误,会在这里直接被拦截并打印在网页上
      return new Response(`
        <h1>Worker Error (1101 Prevented)</h1>
        <p>内部发生了未捕获的错误:</p>
        <pre style="background:#f4f4f4; padding:15px;">${error.stack || error.message || error}</pre>
      `, { 
        status: 500,
        headers: { 'Content-Type': 'text/html;charset=UTF-8' }
      });
    }
  },
};

五、给 Notion AI 的调用 Prompt

Worker 只是桥。真正让它变成 Notion AI 技能的,是一段清晰的调用说明。

可以这样写:

接口地址:`https://your-bocha-worker.example.workers.dev`

【URL 参数说明(必须进行 URL 编码)】

- `query` (必填): 你的搜索词。
- `summary` (可选): 是否返回长摘要,传 "true" 或 "false"。建议查阅复杂资料时设为 "true"。
- `count` (可选): 返回条数,1-50。默认 10。
- `freshness` (可选): 时间范围限制。可选值:"noLimit"(默认), "oneDay", "oneWeek", "oneMonth", "oneYear" 或指定日期格式如 "2025-01-01..2025-04-06"。
- `include` (可选): 限制在指定域名内搜索,多个用 `|` 分隔(如 [qq.com|m.163.com](http://qq.com%7Cm.163.com))。
- `exclude` (可选): 排除指定域名,格式同上。

【强制鉴权步骤】
每次发起请求前,必须按以下步骤生成动态鉴权参数:

1. 获取当前准确的 10 位 Unix 时间戳(精确到秒)。
2. 将该时间戳与字符串 "你设计的 32 位随机 Key" 拼接(格式:时间戳+密钥)。
3. 使用计算工具计算拼接字符串的 SHA-256 哈希值(输出小写)。
4. 将时间戳作为 `ts` 参数,哈希值作为 `sign` 参数。
5. 在完成权鉴 URL 的拼接后,不再使用计算机工具,而改为使用浏览网页的工具(web.loadPage)发起搜索。

【调用格式示例】
如果你要搜索 "2024年诺贝尔物理学奖得主",并需要摘要,返回 5 条结果,最终请求的 URL 格式应如下:
`https://bocha-notionai.xiaoyao-f87.workers.dev/?query=2024%E5%B9%B4%E8%AF%BA%E8%B4%9D%E5%B0%94%E7%89%A9%E7%90%86%E5%AD%A6%E5%A5%96%E5%BE%97%E4%B8%BB&summary=true&count=5&ts=1715000000&sign=计算出的哈希值`

获取到 JSON 响应后,请解析其中的 `data.webPages.value` 数组,提取 `name`、`url`、`snippet` 和 `summary` 字段,整理并总结后回答用户的问题。

在这个 Prompt 里,Notion AI 只需要知道「如何生成签名」和「如何拼 URL」。真正的 API Key 留在 Worker 里。

如果担心把 SECRET_KEY 也写进 Prompt,可以进一步做一层更保守的设计:让 Worker 接收一个固定的内部 Token,或者改用 Cloudflare Access、IP 限制、一次性短链等方式。但对个人使用场景来说,时间戳 + 哈希签名 已经足够轻量。

六、这个方法可以接入什么

博查只是一个例子。只要第三方服务能被 Worker 调用,就可以用类似方式接进 Notion AI:

  • 搜索 API:中文搜索、垂直站点搜索、私有搜索引擎。
  • 数据 API:自建数据库、Notion 之外的表格、CRM、日志系统。
  • 模型 API:转录、摘要、分类、向量检索、图像理解。
  • 自动化 API:Webhook、内部工具、个人服务器上的脚本。

它们都可以被包装成一个 Notion AI 能读懂的网页。

这件事的意义不只是「让 Notion AI 多一个工具」。更准确地说,它让个人可以把自己的外部系统,变成 Notion AI 的可观测边界。

当这些 API 接进来以后,Notion AI 不再只是访问 Notion 页面和公共网页。它可以访问你的订阅源、你的私有搜索、你的自动化流水线、你的本地知识系统。

一个新的 AI 记忆层概念:哈勃半径

2026-05-06 09:00:00

最近几个月,我给自己的 AI Agent 配了三层上下文记忆。

第一层是「我知道的」。第二层是「我应该知道的」。第三层是「我可能知道的」。这个第三层,我叫它「哈勃半径」。

AI 不应该只知道我已经写下来的东西,也不应该一遇到问题就冲进公共搜索引擎。它应该先知道一件事:在我的世界里,哪些东西本来就有可能被我看见。

很多人在谈 AI 记忆时,只谈两个问题。一个是 AI 能不能记住我,另一个是 AI 能不能查资料。前者是个性化,后者是搜索。但这两个东西中间缺了一块。

AI 还需要知道:我平时从哪里感受世界。

这就是哈勃半径。

我们先从前两层记忆开始讲起。

一、RAG 与 LLM Wiki:先让 AI 知道我是谁、我如何思考

先说第一层:我知道的。

我给 Notion AI 接了一套切片式 RAG 系统。它只存事实。每条记忆都很短,通常不超过 200 字。每个片段有关键词、向量、关系和时效性,存放在一个 Notion 数据库里。它会从我的文章、日记、Dayflow、Looki、方案、聊天记录里提取东西。

Dayflow 是分钟级的 Mac 使用记录。Looki 是一个可穿戴设备,会隔几分钟记录一小段视频,再通过 API 抽取文字总结。日记是我每天对自己状态的复盘。

我每天凌晨 5 点会跑一个自动化流程,调用 Notion AI 的技能,把这些原始数据切成一条条记忆碎片。它们共同构成一个事实记忆层:我最近做了什么,想了什么,困在什么问题里,哪些项目正在推进,哪些判断已经发生过。

这层记忆的效果非常明显。

我和 Notion AI 聊天时,它通过一次 Function Call,基本就能知道我最近在做什么。它知道我这几天在调 Hermes Agent,知道我在做中美 AI 叙事研究,知道我搭了兴趣晨报和晚报,也知道我一边依赖 Notion 的平台优势,一边对这种依赖保持警惕。

这很像一个熟悉你个人助理。

它不一定懂你完整的知识结构,但它知道你最近说过什么、做过什么、立过什么 flag、刚刚踩过什么坑。AI 从一个通用模型,变成了一个「在你身边待过一阵子的人」。

但这还不够。

事实层的问题也很明显:它只记录已经发生过的事情。它知道我真正知道什么,却不知道那些还没有被我整理成事实、没有写进日记、没有主动问过的问题。

它是我的影子,但不具备我的思考。

所以有了第二层:我应该知道的。

这一层是 LLM Wiki。LLM Wiki 是 OpenAI 联合创始人 Andrej Karpathy 提出的概念,可以简单理解成一个由 AI 维护的 Wiki。它不是让内容以原始形态散落在知识库里,而是按 Wiki 的规则,把材料整理成可以继续生长的条目。

我的 LLM Wiki 由 Hermes Agent 驱动,最早从 OpenClaw 一路折腾过来,后来逐渐变成一个带有 FTS5 lexical、向量搜索和图结构的内网知识系统。它不会简单地把材料切碎后塞进数据库,而是试图把散落的材料编织成结构。

它读的东西也比第一层更宽。

除了「我知道的」那些关于「我」的事实,它还会读我收藏的文章、抖音、播客、个性化日报,甚至是我没有认真读完但已经被系统捕捉到的内容。Hermes Agent 每天凌晨到我的 Notion 里读取当日新增内容,再做联想、归纳、合并和结构化。最后形成一张可以浏览、可以检索、也可以继续修改的知识网。

切片式 RAG 对 AI 很好用,但对人很难读。打开以后全是碎片,没有结构,也没有涌现。AI 可以从里面召回细节,但人很难从里面看见知识的形状。

我给我的 LLM Wiki 部署了一个 Quartz 前端,让它能不止在 AI 里被调用,还可以直接看。

LLM Wiki 的意义就在这里。它不是回答「某条事实在哪」,而是回答「这些事实之间有什么关系」。

比如我长期关注 AI、平台权力、消费文化、非人行动者、工作流、知识管理和个人数据主权。单条记忆只能告诉 AI:「用户最近在搭 FreshRSS」或「用户关注 AI 记忆层」。但 Wiki 可以把它们放到一条更长的线上:从早年对 Rewind 的兴趣,到想要自动维护「我知道的东西」的 Wiki,再到 Notion as Me、Hermes、LLM Wiki、兴趣日报、NotionSearch。其实这一直是同一个问题在变形。

这个问题是:我能不能让 AI 使用我的上下文,而不是把我的上下文继续交给平台公司?

第二层解决的是「我应该知道」。它不只是记住过去,也开始整理过去。它把材料变成结构,把结构变成立场,把立场变成下一次对话的背景。

顺便说一句,这并不意味着第一层的切片式 RAG 就不重要了。我在 X 和小红书上刷到不少帖子,说 RAG 已经过时了,应该用 LLM Wiki 取代它。我觉得这是一种很典型的非此即彼。

切片式 RAG 在关键词搜索、速度和短事实召回上,仍然非常好用。比如我每天和谁开了什么会,这类来自 Looki 或 Dayflow 的记录,就不应该被郑重其事地写进 LLM Wiki。它只适合待在第一层。需要的时候被找回来,不需要的时候安静躺着。

第一层是记忆卡片,第二层是 Wiki,前两层是网上已经比较多见的实践了,我不必太多啰嗦。但用了一段时间之后,我发现这两层记忆依然有它的边界——它只能处理已经进入我系统的东西。

那些我没有收藏、没有读、没有转录、没有整理,只是刚好出现在我关注源里的东西,它仍然不知道。

这恰恰是今天要讲的最大的一块。

二、哈勃半径:我可能知道的世界

第三层,就是「我可能知道」。我叫它哈勃半径。

我把所有关注源,包括抖音、播客、网站、公众号、即刻、X,都通过工作流(OpenClaw 或 n8n)尽量先处理成文字,再汇总到 FreshRSS。然后把 FreshRSS 的全量数据定时导入一个私有 Meilisearch 搜索引擎。最后把这个 Meilisearch 接到 Notion AI 和 Hermes Agent 上,作为一个独立搜索源。

Meilisearch 是一个开源的私有搜索引擎,在建立之后,你可以通过 API 向其中加入任何文档,并且像搜索引擎一样搜索整个库。更重要的是,它的性能很好,能在海量数据下以十几毫秒的速度返回搜索结果。

这件事听起来很工程化。实际也确实很工程化。

我是在一个周日下午把它搭起来的。先在群晖上部署 Meilisearch,配置端口、卷挂载和环境变量;再给它配 UI,处理 CORS,检查索引;然后给 Hermes Agent 装 Meilisearch 技能,调整 FreshRSS 的订阅分类,把来源分成公众号、博客、学术期刊、视频和其他信息流。

后来我又给它接了 Cloudflare Worker,做了一个中转服务,配反向代理、API Key、过滤字段、排序参数和全文读取。这样 Notion AI 就可以远程调用这个私有搜索引擎。

那天晚上,我在 Meilisearch UI 里看到索引里已经有接近一万条文档。这个数字对 Google 来说小到没意义,但它还会以每周大约 2000 条的速度增长。对一私有的信息库来说,这已经是一个不小的宇宙了。

更重要的是,这些文档不是互联网上随机抓来的几万条网页。

它们来自我手动关注过的源。

公众号是我关注的,播客是我订阅的,网站是我放进 RSS 的,即刻和 X 也是我自己选择的社交场。它们当然不等于我已经读过,更不等于我同意。但它们至少说明,在过去某个时刻,我允许这些源进入我的视野。

这就是哈勃半径和公开搜索引擎的区别。

公开搜索引擎回答的是:全网有什么。

哈勃半径回答的是:在我的信息宇宙里,有什么。

为什么叫哈勃半径?

在宇宙学里,哈勃半径可以粗略理解为一个观测边界。以观察者为中心,边界以内的东西在原则上可以被观测,边界之外的东西越来越远,也越来越不可达。我不是在严格使用物理概念,只是借它说一个信息生活里的事实:每个人都有一个以自己为中心的信息半径。

你每天刷到什么,订阅了什么,关注了哪些人,信任哪些媒体,反复打开哪些网站,收藏哪些文章,听哪些播客,甚至在哪些平台上浪费时间。这些东西共同构成了你的信息宇宙。

过去,这个宇宙主要对平台有用。

平台知道你看了什么、停留多久、划走了什么、又回头看了什么。它用这些数据推荐下一条内容,卖广告,优化留存,让你继续待在它的宇宙里。但你自己很难使用它。

你没法问抖音:「我过去半年关注的所有创作者里,有没有人谈过某个问题?」

你也没法问公众号:「在我关注的这些媒体里,最近两周关于 AI 教育的讨论发生了什么变化?」

更不用说把播客、短视频、社交平台、RSS 和日记放在一起比较。

平台拥有你的信息半径,但你没有。

哈勃半径的意义,就是把这个半径拿回来,放进自己的 AI 里。

它不是为了对抗 Google,也不是为了替代小红书、抖音或公众号搜索。它要做的事更小,也更私密:让 AI 在回答我的问题之前,先进入我的可观测宇宙。

当我问一个事实类问题,公开搜索当然重要。但当我问一个非事实类问题,比如「最近中文互联网对 AI Agent 的态度是不是变了」「为什么我觉得某类内容越来越像工作泔水」「年轻人对信息流的疲劳是不是正在出现」,Google 的第一条结果未必有用。

我更想知道的是:在我的可观测宇宙里,这些情况有没有发生变化。

因为这类问题不是在找一个标准答案,而是在找一种气候。

气候不在百科里。气候在我长期接触的那些源里。

三、它不是搜索引擎,而是记忆层

我认为哈勃半径是一个记忆层,不是一个搜索引擎。

搜索引擎的核心动作是检索。记忆层的核心动作是限定上下文。

同一个关键词,在不同人的哈勃半径里,意思会完全不同。搜索「AI 陪伴」,投资人、心理咨询师、乙女游戏玩家、产品经理、未成年人研究者、同人作者,看到的世界不会一样。公开搜索会把这些语义场压平,再按流行度、权威性或广告逻辑排序。

私人哈勃半径会先问另一组问题:

这个词对你来说通常出现在哪里?你通常从哪些人那里接触它?你过去对它有什么反应?你关注的源最近怎么谈它?

这不是覆盖率问题,而是权重问题。

AI 接入公开搜索以后,最大的问题往往不是查不到资料,而是不知道该信谁。它能打开 Google,能搜小红书,能查抖音,能读网页,但它不知道这些源在我的世界里是什么位置。

有些来源对我只是噪音。有些来源我长期信任。有些来源我不同意,但我会用它观察某种立场。有些来源质量一般,却很接近一线语感。有些来源不权威,但能比论文更早捕捉到文化变化。

这些权重,公开搜索不知道。AI 也不知道。

哈勃半径知道。

不是因为它更聪明,而是因为它的信源已经被我过去的关注动作筛过一遍。关注本身就是一种缓慢的标注。它不是点赞那么短,也不是收藏那么重。它更像一种持续授权:这个源可以进入我的世界。

所以 AI 在哈勃半径内搜索时,不是在「查全网」,而是在调用我的长期注意力沉淀。

这就是记忆。

这层记忆还有一个很微妙的地方:它记录的不是「我知道」,而是「我可能知道」。

第一层记忆里的东西,我大概率真的知道。因为我写过、说过、做过、记录过。第二层知识里的东西,我应该知道。因为它已经被系统整理成结构,等着我在合适的时候调用。

第三层不一样。它包含大量我根本没看过的内容。

我估计在我的哈勃半径中,至少 99% 以上的内容我都没看过。毕竟我关注了至少 2000 个不同类型的订阅源:网站、公众号、短视频、播客,都有。

按传统知识管理的标准,这很奇怪。没看过,怎么能算我的知识?没有消化,怎么能算我的记忆?

但 AI 时代会改变这件事。

过去,知识管理的瓶颈是人的阅读时间。你订阅 100 个源,真正能读完的可能只有 5 个。剩下 95 个只是焦虑来源,是未读数字,是信息债务。

但如果 AI 可以在需要时帮你回到这些材料里,未读内容就不再只是债务。它变成一种可调用的可能性。

我不需要每天读完所有公众号、播客和视频。我只需要在某个问题出现时,让 AI 先到我的哈勃半径里看一眼:在我本来可能接触到的信息宇宙里,有没有人已经说过类似的话?有没有一个我错过的案例?有没有一场小众讨论,比公开搜索更贴近我的问题?

这是一种将「阅读」从前置消费,改成后置召回的信息管理方式。

过去我们必须先读,未来才有资格想起。现在我们可以先建立半径,再在问题出现时让 AI 回到半径内部找线索。人的角色不再是吞下全部信息,而是维护自己的可观测宇宙。

我觉得这会是 AI 时代知识管理的一个大变化。

四、半径的价值来自边界

当然,哈勃半径不是越大越好。

这是它和公开搜索最根本的差别。公开搜索追求覆盖率,私人半径追求相关性。你不需要把全网都装进来,甚至不应该这么做。如果一个私人搜索库最后变成小号 Google,它就失去了意义。

哈勃半径的价值来自边界。

边界越清楚,AI 越知道你在什么语境里提问。边界越混乱,AI 就越容易重新滑回公共平均值。

所以它的维护重点不是「多抓」,而是「选择」。哪些公众号值得保留,哪些 RSS 已经失效,哪些播客只是阶段性兴趣,哪些社交账号虽然经常胡说但有现场感,哪些来源应该降权,哪些来源适合做事实判断,哪些来源只适合做情绪采样。

这些都不是模型能自动决定的。

AI 可以帮你清理、分类、去重、打标签、转文字、做索引,但半径本身必须由人来画。因为这条边界表达的是你的注意力史、信任结构和审美偏好。

这也是我为什么越来越不满足于「给 AI 接一个搜索引擎」。

接搜索引擎只是扩展能力。设置哈勃半径,才是在扩展主体。

前者让 AI 更会查。后者让 AI 更像你。

把三层记忆放在一起,关系就清楚了。

第一层,「我知道的」,是事实记忆。它让 AI 记得我的近况、偏好、项目和判断。

第二层,「我应该知道的」,是结构记忆。它把事实和材料织成 Wiki,让 AI 理解我的长期问题和知识网络。

第三层,「我可能知道的」,是半径记忆。它把我长期关注但未必阅读的一切变成可召回的信息宇宙,让 AI 在进入公共互联网之前,先进入我的信息边界。

最内层是我留下的痕迹,中间层是这些痕迹被整理后的结构,最外层是我可能接触到的世界。

如果用一个人来类比,第一层像记忆,第二层像知识,第三层像视野。一个真正个人化的 AI,不能只有记忆和知识。它还必须有视野。否则它知道你昨天做了什么,也能背出某个概念的定义,却不知道你平时从哪里感受世界。

这就是很多 AI 个性化产品让我不满意的地方。

它们把「记住用户」理解成记住偏好:喜欢什么语气,在哪里工作,正在做什么项目。它们把「连接外部世界」理解成搜索网页。但用户不是一个偏好表,外部世界也不是一张无差别网页列表。用户和世界之间,还有一层长期形成的媒介关系。

哈勃半径记录的就是这层关系。

五、每个人都需要自己的哈勃半径

我比较相信,未来每个重度使用 AI 的人都需要自己的哈勃半径。

它可以很简单,不一定要像我这样折腾 FreshRSS、Meilisearch、群晖、Cloudflare Worker、Hermes Agent 和 Notion AI。对大多数人来说,它可能只是一个持续维护的 RSS 列表,一个高质量收藏夹,一个跨平台稍后读,一个能被 AI 调用的信息源仓库。

关键不在技术栈,而在观念:你需要给 AI 一个你不读,但你给出权重很高的,可不依赖你的内在系统也持续更新的内容池,

AI 的上下文不应该只来自公开互联网,也不应该只来自你已经整理好的笔记。真正属于你的上下文,还包括那些你长期允许进入生活、但尚未被你消化的信源。

那是你的信息暗物质。

它平时不可见,却影响你的判断、写作、情绪和问题意识。你以为自己是在独立思考,其实你一直在某个半径内思考。过去,这个半径只被平台拿来塑造你;现在,你可以把它交还给自己的 AI,让它帮你看见这半径内部到底发生了什么。

这也是为什么我叫它「哈勃半径」。

AI 时代的问题,不是信息不够,而是默认的世界太大。世界越大,平均值越强。平均值越强,个人经验越容易被淹没。

给 AI 设置哈勃半径,就是告诉它:先别急着替我抵达全世界。先回到我的宇宙里。

看看我关注过什么,错过了什么,可能知道什么。看看哪些信号已经在我身边出现,只是我还没来得及读。看看哪些问题早就在我的信息半径里反复回响,只是还没有被命名。

当 AI 能做到这一点,它就不再只是一个更快的搜索框,也不只是一个更长记性的助手。

它开始像一个能替我巡视视野的人。

而这可能才是个人 AI 真正开始成立的时刻。

AI 也该有护照了

2026-04-27 18:18:59

以前公司出海,像搬家。

现在 AI 公司出海,更像改户口,哦不,像改国籍。

Manus 这件事有意思的地方,不在 Meta 到底想不想买,也不在这家公司值不值 20 亿美元。荒诞之处在于:一家软件公司,突然有了户籍问题。

2026 年 4 月 27 日下午,中国监管部门叫停 Facebook 母公司 Meta 对 Manus 的收购,并要求撤销相关交易。

从 2025 年 12 月 30 日,宣布收购到今天被商务部拦下,这桩交易中间传出过不少八卦。压成一条商业新闻,就是一家中国 AI 创业公司想把控制权转到境外,最后被外商投资安全审查挡住了。

一家中国的明星 AI 公司想从中国身份里脱壳,先搬到新加坡,再被美国巨头收走。脚还没迈出去,就在边境线上被人按住肩膀:等等,你不能这样走。

但商业新闻只讲到壳。

一个外卖员换平台,没人会说这叫叛逃。一个 SaaS 公司卖给外资,也多半只是并购新闻。可一个 AI 公司换控制权,气氛就不一样了。它像人口迁徙。

因为被卖掉的已经不只是股权。

它卖掉的是一种正在获得行动能力的东西:会读邮件,会看日程,会写代码,会替人回复消息,会调用工具,会进企业系统,会从一句“你帮我处理一下”里拆出一串动作。

以前的软件像锤子。锤子不会移民。

今天的 AI 更像办公室里新来的同事。很笨,偶尔胡说,常常添乱,但已经开始进入办公室、家庭、银行、医院和朋友圈。一个东西开始替你说话,它就不只是你的东西了。

所以 Manus 事件问出来的问题是:当 AI 不再只是商品,而是一种跨境行动能力,它还能像普通商品一样自由买卖吗?

新来的同事

人类过去判断一个东西是不是工具,有个很朴素的标准:它有没有自己的意图。

锤子没有。Excel 没有。搜索框也没有。

你拿锤子砸到手,责任链条很短。锤子不需要开庭。你用 Excel 算错账,问题也清楚,要么公式错了,要么人错了。工具听命于手,手属于人。

AI Agent 把这条线搅浑了。

它当然没有真正意义上的人格,也谈不上自由意志。可它已经开始做过去只有助理、实习生、客服、秘书会做的事:理解模糊指令,拆分任务,访问外部工具,在不同系统之间搬运信息,代表用户和另一个系统交涉。

世界经济论坛讨论 AI Agent 治理时,用过一个很准的比喻:企业部署 Agent,越来越像 onboarding 一名新员工。不是把插件装进浏览器就完事。你要给它权限,告诉它边界,记录它做了什么,审计它为什么这么做。

这个比喻很锋利。

我们不会问一把锤子的入职培训做得好不好。我们只会问一个人、一个岗位、一个被授权行动的角色,有没有被正确带进组织。

现在很多人骂 AI,骂法也变了。

早几年大家骂软件,是骂“这个按钮真难用”“这个搜索真垃圾”。今天骂 AI,经常像骂实习生:“你怎么连这都理解错?”“我不是这个意思。”“你别自作主张。”

这说明用户在心理上已经把它当成了某种临时社会人。

麻烦也在这里。AI 不只是延伸人的手,它开始延伸人的意图。

手的延伸比较好管。意图的延伸很难管。

一个 agent 替你给客户发邮件,措辞冒犯了对方,算谁的责任?它替公司筛选候选人,因为训练数据里的偏见把某类人排除出去,算谁的责任?它替医生整理病历,漏掉一个关键症状,算谁的责任?它替用户安排旅行,顺手把护照信息、支付信息、行程偏好交给境外服务商,算谁的责任?

过去这些问题还能勉强塞进“软件责任”里。软件出错,找开发商。员工出错,找公司。数据泄露,找平台。

可当 AI 同时像软件、员工、外包商和代理人,责任链条就散了。

一个东西一旦开始替你行动,它就需要身份。

人类如何给流动编号

现代人很容易把护照和签证想成墙。

这当然没错。签证可以拒绝你,边检可以拦住你,护照的颜色能决定一个人跨境时被怎样对待。现代身份制度从诞生那天起,就带着不平等和暴力。

但它还有另一面。

签证最文明的地方,不是拒绝你。是承认你可以来,只是要先说明你是谁。

一战以前,今天这种全球通用的护照制度还没有完全固定。很多地方的跨境流动,比现代人想象得松散。战争、民族国家、边境控制和国际秩序重组一起涌来后,护照和签证才逐渐变成标准装置。1920 年的国际护照会议,就是这套现代编号系统的重要节点。

这套制度把一个陌生人的移动变成了一组可以处理的社会关系。

你从哪里来。要去哪。能待多久。谁接待你。违反规则后由谁遣返。在外面出了事,哪个国家保护你。你在别处伤害了别人,哪个共同体能追责你。

现代国家没有取消流动。它把流动制度化了。

这句话很冷,也很官僚。但社会本来就靠这些灰扑扑的东西运转。出生证明、户籍、营业执照、船籍、车牌、税号、法人登记。它们没什么诗意,却把“一个东西是谁”固定成可以谈判、追踪、追责的形式。

没有身份的自由,很多时候是逃避责任,但它同样意味着放弃权利。

这就是“AI 国籍”值得认真讨论的原因。

它不是问 AI 爱不爱国。也不是问一个模型会不会升旗。这个问题听起来滑稽,是因为我们还在用“工具”的想象理解它。

如果一个人跨境工作需要身份,一个 AI 跨境提供服务、调用数据、影响企业决策、替用户沟通、进入关键系统,为什么可以没有身份?

如果一个陌生人进入医院,需要说清姓名、证件、职责、权限,一个可以读取病历、生成诊疗建议、调用医院系统的 AI,又凭什么只被当成“软件功能”?

开放不是没有门。

开放是门可以被敲开,门后有人登记,出了事也找得到人。

我们当然可以讨厌印章。任何办过证、跑过审批、填过表的人,都知道制度有多烦。但在人类历史上,印章还有另一个功能:它把原本不可见的行动者,按进可见的社会秩序里。

AI 也正在走到这一步。

国籍是责任地址

所以,“AI 有国籍”最容易被误解成技术民族主义。

好像一说 AI 有国籍,就是中国模型只能待在中国,美国模型只能待在美国,开源模型要被边境线切碎,全球技术交流从此变成电子版闭关锁国。

这个理解太偷懒。

AI 的国籍不是血统证明,是责任地址。

它要回答的问题不是“这个模型属于哪个民族”。它要回答的是:它从哪里来,被谁训练,受谁约束,用谁的数据,服务谁的系统,出了事找谁,控制权转移时由谁审查。

这并不中国特色。

美国有 CFIUS,长期审查可能影响国家安全的外资交易。欧盟也在强化 FDI screening framework,一边维持开放投资,一边识别和缓释安全与公共秩序风险。AWS 要开欧洲主权云,强调本地法律实体和欧盟居民运营控制。OpenAI 推出 OpenAI for Countries,把 AI 基础设施包装成国家发展和“民主 AI rails”的一部分。

连最会讲全球化故事的公司,也开始学主权语言。

原因很简单:AI 正在从应用变成基础设施。

港口、电网、通信网络、云服务、芯片供应链,都经历过类似的身份变化。它们一开始是商业资产,后来慢慢变成安全资产。一个港口卖给谁,不只是股东会问题。一个电网被谁控制,不只是财务问题。一个云平台由谁运营,也不只是采购问题。

AI 更麻烦。

港口处理货物,电网传输电力,云承载数据。AI 不只处理数据,它还参与判断。它不只承载服务,它还可能成为未来社会的接口。

一家 AI 公司被卖掉时,被转手的可能不只是公司本身,还有一种未来社会的接口。

把 Manus 这件事反过来想,可能会更好笑一点。

如果几年后,它真的在美国某个系统里搞出大篓子——泄露了不该泄露的数据,自动执行了不该执行的操作,或者在某个关键场景里把责任链条搅成一锅粥——到那时,所有人都会突然想起一个朴素问题:这东西到底算谁的?

甚至可以想象那个画面:白宫摄像机前,那个金毛老人站在麦克风后面,右手比出一个 👌 的手势,拖长声音,说出一句以 “China!” 开头的话。

这当然像段子。

但段子好笑,是因为它提前暴露了责任的荒唐。

当一个 AI 出事时,人们不会只问代码是谁写的。还会问它由谁训练、谁控制、谁卖给了谁、谁放它进了哪个系统、谁批准它跨境行动。资本市场可以把这些问题包装成交易结构,媒体可以把它写成科技新闻,可事故发生时,责任不会按商业计划书的页码排队。

无审查的跨境流动,听起来像自由市场的童话。落到 AI 身上,可能只是让控制权、数据和责任一起消失在离岸结构里。

麻烦的不是一个模型出国。

麻烦的是几年后出了事,所有人都在镜头前摊手,然后把锅甩给一个早就没有地址的名字。

权利从登记表开始

更反直觉的一层在这里:国籍未必只是限制,它也可能是权利的第一步。

这句话很容易被误读。AI 现在不该享有人权,也不需要把 ChatGPT 当成办公室里的少数族裔。现实世界已经有太多活人没有获得足够权利,没必要急着替机器开伦理派对。

但法律和制度的演化,很少从浪漫宣言开始。

公司不是人,却有法人身份。船不是人,却有船籍。动物不是公民,但动物福利制度已经让它们进入法律关怀。很多主体在获得完整权利以前,先获得的是登记、许可、责任、财产、合同、审计这些乏味的东西。

权利常常不是从诗开始的。

权利常常从登记表开始。

AI 如果未来真的走向某种“类主体”位置,第一步恐怕也不是自由宣言。第一步会很难看,很行政,很像给一个新物种发临时居住证:你是谁,由谁负责,能做什么,不能做什么,行动日志保存多久,调用了哪些工具,伤害了别人时由谁赔偿。

这不会让 AI 立刻变成人。

恰恰相反,它会先把 AI 从资本最喜欢的状态里拖出来。

资本最喜欢什么状态?没有身份的劳工,没有工会的外包,没有责任地址的平台,没有国籍的智能体。

一个没有户口的智能体当然很自由。它可以服务任何人,进入任何系统,观察任何用户,跨越任何边界。它不属于任何地方,也就很难在任何地方真正负责。

这才是无国籍 AI 最诱人的地方。

对用户来说,它像自由。对平台来说,它像利润。对国家来说,它像风险。对未来的 AI 本身来说,它也许像永远无法被承认的童工。

所以“AI 有国籍”这句话最有意思的部分,不在国家主义那一面。

它承认 AI 已经开始像社会成员一样行动。既然它开始行动,就要有身份。有身份,才谈得上责任。责任先到,权利才可能在将来的某个边界内被认真讨论。

AI 的第一张护照,不会写着自由、平等、博爱。

它只会写着:出了事找谁。

最好用的,永远是没有船籍的人

回到 Manus。

这不是一个中国公司能不能卖给美国公司的故事。它更像新时代的问题第一次露出户口本。

过去几十年,互联网最强大的神话之一,就是“无国界”。信息无国界,平台无国界,资本无国界,代码无国界。这个神话带来很多便利,也留下很多逃责的缝隙。

AI 把这条缝撕得更大。

一个强大的 AI 如果没有国籍,它就可以服务任何人、观察所有人、穿过所有边界,同时不真正属于任何法律共同体。它像一名在公海上工作的无船籍水手:船东在一个地方,注册地在另一个地方,雇主是一串离岸公司,真正干活的人睡在甲板下面。

出了事,海面上只剩下泡沫。

人们会追问船是谁的,货是谁的,航线谁定的,保险谁买的。最后发现每一个答案都指向下一个邮箱、下一个壳公司、下一个“请联系相关责任方”。

这才是无国籍最诱人的地方。

它不一定表现为宏大的阴谋,也不一定穿着反派的黑斗篷。它更常见的样子,是成本表上少了一行,合规表上空了一格,事故报告里多了一个没人认领的名字。

AI 如果也变成这样的水手,麻烦就不只是它会不会越境。麻烦在于,它越能干,越适合被塞进那些最脏、最累、最不想留下责任痕迹的工作里:替人筛掉候选人,替人拒绝赔偿,替人做信用判断,替人把“不方便由人说出口的话”说出口。

并且,它不需要负担任何责任,当然也不会享有任何权利。就像是那些在公海海盗船上早已失去任何一国身份的船员,杀人越货,然后被杀人越货。

人类曾经用护照管理肉身的流动,用船籍管理海上的责任。接下来,某种新护照也许要用来管理智能的流动。

这不会很优雅。也不会一开始就公平。它会充满表格、审批、争吵和荒唐案例。

但现代制度本来就是这样长出来的。先有粗糙的边界,再有复杂的协商。先有难看的印章,再有更像样的权利。

AI 的国籍不是终点,甚至不是答案。它只是人类站在一片新海域前,条件反射般摸出的第一枚印章。

印章和船籍当然麻烦。

但当你行驶在今天的霍尔木兹海峡上,就会知道它的重要性了。