免费POC, 零成本试错
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


我要投稿

从向量里逆向出原始文本和模型来源

发布日期:2026-03-10 06:52:06 浏览次数: 1542
作者:Jina AI

微信搜一搜,关注“Jina AI”

推荐语

揭秘向量背后的隐藏信息:从一串浮点数中竟能还原原始文本和模型来源!

核心内容:
1. 向量溯源技术:通过80万参数小模型精准识别68种生成模型,准确率达87%
2. 文本逆向工程:采用掩码扩散模型实现81%的token级原始文本还原
3. 突破性方法:将浮点数转为字符级token处理,建立独特的模型数字指纹

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

🔬 在线 Demo: embedding-inversion-demo.jina.ai

📊 技术报告: jina.ai/news/embedding-fingerprints 

📊 技术报告: jina.ai/news/embedding-inversion 

📄 论文: arxiv.org/abs/2602.11047 

💻 代码: github.com/jina-ai/embedding-fingerprints

用户把文本发到我们的 API,我们返回一串浮点数。没有标签,没有水印,没有任何元数据告诉你它从哪来、用的什么模型。大多数人看到这串数字,反应都是"不就是一堆浮点数嘛,能看出什么?"

过去两周,我们做了两项研究,发现能看出的东西远比想象中多:

  1. 模型溯源:我们训练了一个仅有 80 万参数的小模型。光看一串浮点数,就能判断出这是哪个模型生成的,准确率高达 87%,覆盖 68 个模型和任务组合。

  2. 文本逆向:我们用掩码扩散模型,直接从向量中反推出原始文本。Token 级还原准确率达到了 81%。

也就是说,向量不仅携带语义,还带着生成它的模型的基因,以及原始文本的大量信息残留。

demo: https://embedding-inversion-demo.jina.ai/

向量溯源:这串数字是谁生成的?

当有人给你一个 1024 维的向量,你能判断它是 BGE-M3 生成的,还是 jina-embeddings-v3,还是 Qwen3-Embedding 吗?

再往前走一步: 同一个模型,你能分辨推理时用的是 retrieval 指令还是 classification 指令吗?

直觉上这似乎不可能。向量就是一堆数字,模型之间的差别应该体现在语义空间的几何结构上,而不是数值本身的分布细节。但实验结果直接推翻了这个直觉。

不同模型产生的浮点数,在统计上有非常显著的差异。值域范围、各小数位数字出现的频率、维度间的相关模式...... 这些特征拼在一起,构成了模型独特的数字指纹。这有点像笔迹鉴定,同一段话让不同人抄写,内容一样,但笔画的力度、倾斜和连笔方式都会无意间暴露书写者的身份。

把浮点数当文本来读

这个方法最反直觉的地方在于输入表示。我们没有把向量当成一堆浮点数,而是把每个数字转成了字符串,像处理文本一样,逐个字符拆开喂给模型。

如下图所示,-0.1234 会变成 token 序列 [CLS] - 0 . 1 2 3 4,维度之间用 [SEP] 隔开。整个词汇表极简,只有 15 个 Token:数字 0 到 9、负号、小数点、几个特殊分隔符。

位级别分词(Digit-level Tokenization)
位级别分词(Digit-level Tokenization)

为什么不使用更直观的量化分桶(Binning):把数据范围划分为 256 个区间(bin),一个维度对应一个 Token,这样 1024 维的向量只需 1024 个 Token 就能表达完。

因为量化需要预设边界,而不同模型的数值分布天差地别:有的集中在 0 附近,有的铺满整个 [-1, 1] 区间,同一个模型不同维度的分布也完全不同。任何固定的分桶方案,都会在某些模型上造成严重的分辨率损失,掩盖掉最关键的特征。

所以我们选了最“无假设”的方案:位级别分词(Digit-level Tokenization)。虽然这会让一个 1024 维向量膨胀成 7700 个 Token 的长序列,但它原样呈现了数字的每一位,保留了所有的统计痕迹,不预设规律,让模型自己去学习其中的统计特征。

比如某些模型在特定位上出现数字 7 的频率更高,或者某些维度的排列模式更独特。这些看似无意义的微观特征,恰恰构成了模型的数字指纹。

模型架构

分类器本身是个 4 层 Transformer,128 维,4 个注意力头,总共约 80 万参数 。用 RoPE 做位置编码,SwiGLU 做 FFN,RMSNorm 归一化。CLS token 池化后投影到 68 个输出类别。

模型架构图
模型架构图,比 GPT-2 小 150 倍,但对 15 token 词汇表的分类任务完全够用。

80 万参数是什么概念?比 GPT-2 小两个数量级。但这个任务词汇表只有 15 个 token,分类目标是 68 个类别,瓶颈不在模型大小,而是如何从 7700 个 token 的长序列里提取出能区分 68 个类别的统计特征。

训练数据方面,我们准备了一万条多语言文本,分别送入 25 个以上的模型,配合不同 task prefix 编码,产生 68 个类别。每类 7000 条训练样本,3000 条验证样本。

这 68 个类别不只是 68 个模型。其中包含了同一个模型搭配不同 instruction prompt 的组合,比如 jina-embeddings-v5-text-small 配 retrieval 指令和配 classification 指令算两个不同类别。如果分类器能区分它们,说明仅仅换一个 instruction prompt,就足以在输出数值上留下可检测的痕迹。

在这些类别中,最难的分组是 1024 维度,包含 32 类模型,分类器无法通过序列长度投机取巧,必须纯粹依赖数值模式。

维度
类别数
示例模型
384
8
BGE-small, E5-small, MiniLM, GTE-small
512
2
BGE-small-zh
768
24
BGE-base, E5-base, jina-embeddings-v5-text-nano, Nomic, INSTRUCTOR, LaBSE
1024
32
BGE-M3, E5-large, jina-embeddings-v3, jina-embeddings-v5-text-small, Qwen3-0.6B, Snowflake, mxbai
1536
2
GTE-Qwen2-1.5B

68 类分类,87% 准确率

我们在 A100 上跑了 14 个 Epoch,处理了大约 430 亿个 Token。

14 个 epoch 的训练和验证曲线
14 个 epoch 的训练和验证曲线

最终,训练准确率达到了 87.3%,验证准确率为 86.0%。两条曲线贴得很近,说明模型真的学到了真实的数值规律,而不是在死记硬背训练集。

87% 准确率,随机猜的话是 1.5%。比瞎猜好 59 倍。

68 类验证集混淆矩阵,每类 3000 样本,共 204000 样本。对角线越亮说明分类越准确。
68 类验证集混淆矩阵,每类 3000 样本,共 20.4 万样本。对角线越亮说明分类越准确。

观察这 20.4 万个样本的混淆矩阵,能看到几个有趣的现象:GTE-large、LaBSE、Paraphrase MiniLM 等模型被 100% 准确识别。跨系列的区分(如 BGE vs Jina)非常容易,模型底层的架构和训练方法留下的指纹最深。最难分辨的是同一个基础模型搭配不同的任务前缀。

最让人意外的是,同一个模型、完全相同的权重,仅仅是推理时换了一个 instruction prompt,输出的数值分布就会产生可检测的差异。jina-embeddings-v5-text-small在 5 个不同 task prefix 之间达到了 92% 的区分准确率。任务适配(Task adaptation)不只是在语义空间里挪了个位置,它实际上改变了数值的统计分布。

这件事有非常直接的用途。接手了一个向量数据库但不知道当初用的什么模型?取出一条向量送进分类器就能识别。怀疑某个 API 声称用的是 model A 但实际偷偷换成了 model B?向量指纹可以验证。向量模型的提供商悄悄升级了版本?指纹同样会暴露这个变化。

从向量逆向文本

如果识别模型来源只是让人意外,那接下来的事就有点狠了:从向量里逆向出原始文本。

给你一个 1024 维的向量,还原出生成它的那段文本。

这不是全新的问题。2023 年 Morris 等人做的 Vec2Text 用 T5 编解码器(Encoder-Decoder)在 32 token 的序列上做到了 92% 的精确匹配(Exact Match)。但那个方法有个根本限制:它需要反复调用目标模型的 API 进行迭代修正,动辄 20 多轮,推理成本直接翻了一个数量级。

我们的目标更激进: 只看向量本身,不碰目标模型,一次性把文本还原出来。

用掩码扩散逆向出文本

我们将这个问题重新定义为一个条件掩码扩散(Conditional Masked Diffusion)问题。

从一个全 [MASK] 的序列开始,模型在每一步同时预测所有位置的 token,逐步替换成真实词汇。整个过程只需要 8 步。不是从左到右一个个生成,而是所有位置并行去噪。

步骤 8/8  [MASK] [MASK] [MASK] [MASK] [MASK]
步骤 6/8  [MASK] quick [MASK] [MASK] [MASK]
步骤 3/8  The   quick brown [MASK] jumps
步骤 1/8  The   quick brown fox   jumps

去噪过程: 从全掩码出发,每一步同时预测所有位置,8 步内完成还原。

我们通过自适应层归一化(Adaptive Layer Normalization,AdaLN) 将目标向量注入到 Transformer 的每一层。向量先经过一个投影层,然后在每一层生成缩放(Scale)和位移(Shift)参数,用来调制层归一化的输出。时间步也通过同样的机制注入。两个信号相加,模型同时知道"当前去噪到了哪一步"和"目标向量长什么样"。

Embedding Inversion 架构图

条件掩码扩散语言模型的架构。上半部分是训练流程: 输入文本经 embedding encoder 编码后,通过 MLP 投影注入 Transformer。下半部分是去噪过程: 从全掩码序列出发,逐步还原。

这个设计一举解决了 Vec2Text 的两个问题。第一,推理时完全不需要接触原始模型,向量是唯一的输入。第二,所有位置并行预测,避免了自回归从左到右的误差累积。而且 AdaLN 的条件注入方式天然不挑编码器:不管目标向量来自什么模型、什么维度,过一遍投影 MLP 就能注入同一个 Transformer。

底座模型我们选用了 22 层、3.8 亿参数的多语言 BERT。在冻结预训练权重后,我们只训练投影层、AdaLN 模块和输出层,实际训练参数量约 1.9 亿。训练数据是 mC4 的 200 万条多语言样本,统一截断到 32 个 token。

# 训练核心伪代码
for text, embedding in dataloader:
    t = uniform(01)              # 随机采样时间步
    masked = random_mask(text, t)   # 按比例随机掩码
    cond = mlp_project(embedding)   # 投影 embedding
    logits = model(masked, t, cond) # 条件预测
    loss = cross_entropy(logits[masked_pos], text[masked_pos])

训练流程: 随机掩码 + 条件去噪。噪声调度用 log-linear schedule,集中在后期掩码,前期保留结构。

81% 的 Token 级还原准确率

我们分别在三个主流模型上进行了实测,还原率都很惊人。

编码器
Token 还原率
向量维度
Qwen3-Embedding-0.6B
81.3%
1024
EmbeddingGemma-300m
78.8%
768
jina-embeddings-v3
76.0%
1024

三个编码器上的 token 还原准确率,使用顺序贪心解码(Sequential Greedy Decoding),序列长度 32 token。每个编码器单独训练。

训练曲线

四个编码器配置的训练准确率曲线。所有模型在 50K 步后趋于收敛。

为了看清这个数字的含金量,我们设定了一个基准对照组:让一个普通的语言模型在完全不看向量的情况下盲猜文本。它能写出非常流畅的句子(BLEU 分数很高),但 Token 准确率只有 2.1%。随机 token 更惨,0.02%。

"能说人话"和"说对的话"是两回事。 模型必须从向量中真正提取语义信息,才能在最低的编码器上也做到 76% 的还原。

在解码策略上,我们测试了五种方案。表现最好的是欧拉 + 重掩码(Euler + Remasking):模型每一步去噪后,都会自我检视一遍,把置信度最低的 5% 重新掩码,交给下一步去修正。相当于把 Vec2Text 的外部修正循环内化到了扩散过程里。

实验证明 5% 是一个最优平衡点,比例太多丢掉正确的预测,太低则修正力度不够。

解码策略
jina-v3
Qwen3
Gemma
顺序贪心(Sequential Greedy)
0.715
0.585
0.621

欧拉采样(Euler Sampling)

0.667
0.556
0.604

欧拉 + 重掩码(Euler + Remasking)

0.665
0.584
0.595

两阶段(Two-Stage)

0.667
0.591
0.605

不同解码策略在 10 种语言上的平均余弦相似度。需要注意,这里衡量的是还原文本与原始文本的向量相似度,而非 Token 级准确率。两个指标下的最优策略不完全一致。综合来看,Sequential Greedy 在大多数编码器上表现得最为稳健,是目前最可靠的还原主力。

一个 1024 维的 float32 向量只有 4KB。但这 4KB 足以让一个扩散模型还原出 32 个 token 中超过 80% 的内容。

向量并非不可逆

在很多人的认知中,向量是一道天然的脱敏屏障:文本转化为高维坐标后,原始信息便不可回溯。很多系统也都宣称:“我们只存向量,不存原文,所以用户隐私是绝对安全的。”

这两项研究动摇的正是这个假设。向量不是不可逆的哈希,而是一个有损但信息密度极高的压缩表示。模型的身份、原始文本的内容,都编码在里面,提取的门槛也在不断降低。

指纹研究(Fingerprint)证明了每个模型编码语义的数值风格各不相同,区分度高到一个 80 万参数的小模型就能认出 68 个来源。逆向研究(Inversion)则证明了这些数字里编码的原始信息,足够扩散模型还原出 80% 以上的内容。两个工作串联起来,先用指纹分类器锁定编码器,再用对应的逆向模型还原文本,就构成了一条完整的攻击链路。

对模型开发者来说,这些发现迫使我们直面一个此前被忽视的问题:向量模型的安全边界到底在哪里?过去我们把精力都投在提升语义检索性能上,但从来没认真想过这些向量在安全性上到底暴露了多少。

我们是否该在训练中引入某种信息瓶颈?在保留检索能力的同时,降低向量的可逆性,或者至少让模型的数值指纹不再那么容易被识破?

当然,硬币有另一面。在 API 提供商可以悄悄换模型的世界里,能从数值本身验证模型来源,本身就是一种有价值的审计能力。

两个项目的代码和在线 demo 均已开源:

🔬 在线 Demo: embedding-inversion-demo.jina.ai

💻 代码仓库: github.com/jina-ai/embedding-fingerprints

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询