欧盟 AI 法案倒计时:大模型厂商如何给生成内容加上机器可检测水印

2026-08-18 23 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

从 2026 年 8 月 2 日起,欧盟《人工智能法案》第 50 条要求相关 AI 系统以机器可检测的方式标记合成输出。主要前沿模型厂商因此开始采用统计水印:在不明显改变文本质量和推理性能的前提下,悄悄影响模型的选词分布,让检测器能够从足够长的文本中识别统计信号。这不只是模型算法问题,也会改变 API、内容平台和开源模型的合规边界。

统计水印不是在文本末尾加标签

传统元数据可以直接写入图片、音频或文件容器,但纯文本经常经过复制、粘贴、重新排版和格式转换。依赖文件元数据的标记很容易在这些操作中消失。

统计水印采用另一条路径:模型生成下一个 token 时,根据密钥和上下文把候选 token 划分为不同集合,再轻微提高其中某个集合的采样概率。单个词看不出异常,但在较长文本中,命中特定集合的 token 比例会持续偏高。持有检测参数的一方可以计算统计量,判断文本是否可能由相应模型生成。

这类方案的价值在于水印信号进入了生成过程,而不是附着在输出文件外层。厂商通常希望它满足三个条件:

  • 不明显降低文本质量、生成速度或模型基准表现。
  • 检测过程可以自动化,并能给出置信度而非简单字符串匹配。
  • 普通编辑不会立刻抹掉信号,至少在文本足够长时仍可检测。

不过,“机器可检测”不等于“永远可检测”。短文本、翻译、摘要、反复改写、token 替换以及多个模型接力处理,都可能削弱统计信号。误报和漏报也无法仅靠一句“已加水印”消除。

厂商接入后,平台需要处理完整证据链

模型提供商实现水印只是第一层。调用模型的产品还需要知道哪些输出被标记、用了哪个水印版本,以及后续处理是否破坏了信号。一个现实的 API 响应可以这样设计;以下是工程实践示例,并非来源中规定的标准格式:

{
  "id": "gen_01JXYZ",
  "model": "frontier-model-2026-07",
  "output": "Generated text goes here.",
  "provenance": {
    "synthetic": true,
    "marking_method": "statistical-watermark",
    "scheme_version": "sw-v3",
    "detector_id": "detector-eu-01"
  }
}

应用不应只保存 output。至少还应记录模型版本、生成时间、水印方案版本、检测器版本和所有会改写文本的后处理步骤。否则,几个月后即使检测结果发生变化,也很难判断是检测器升级、文本被编辑,还是原始输出根本没有水印。

面向用户的可见披露与机器水印也不是同一件事。前者帮助人理解内容来源,后者服务于自动检测和平台治理。工程上可以同时保留可见标签、结构化来源字段和模型层统计信号,不要把三者当作可以互相替代的单一控制措施。

用一个最小实验理解统计检测

下面的 Python 程序演示一种简化的“绿名单 token”检测思路。它使用密钥和前一个 token,确定当前 token 是否落入指定统计集合,再计算 z-score。代码可以直接运行,但它只是教学模型,不能用于证明合规,也不能可靠识别真实厂商的水印。

将代码保存为 watermark_demo.py,然后运行 python watermark_demo.py "要检测的一段较长文本"

#!/usr/bin/env python3
import hashlib
import math
import re
import sys

SECRET = b"replace-with-a-private-test-key"
GREEN_RATIO = 0.5


def tokenize(text: str) -> list[str]:
    return re.findall(r"\w+|[^\w\s]", text.lower(), re.UNICODE)


def is_green(previous: str, token: str) -> bool:
    payload = SECRET + b"\0" + previous.encode() + b"\0" + token.encode()
    value = int.from_bytes(hashlib.sha256(payload).digest()[:8], "big")
    return value / 2**64 < GREEN_RATIO


def detect(text: str) -> tuple[int, int, float]:
    tokens = tokenize(text)
    if len(tokens) < 2:
        return 0, 0, 0.0

    hits = sum(is_green(tokens[i - 1], tokens[i]) for i in range(1, len(tokens)))
    total = len(tokens) - 1
    expected = total * GREEN_RATIO
    variance = total * GREEN_RATIO * (1 - GREEN_RATIO)
    z_score = (hits - expected) / math.sqrt(variance)
    return hits, total, z_score


if __name__ == "__main__":
    sample = " ".join(sys.argv[1:]) or (
        "This is sample text for demonstrating a statistical watermark detector. "
        "Use a much longer passage when observing how token counts affect confidence."
    )
    hits, total, z_score = detect(sample)
    print(f"green tokens: {hits}/{total}")
    print(f"z-score: {z_score:.3f}")
    print("signal detected" if z_score >= 4.0 else "no strong signal")

真实系统不会只对最终文本做这种孤立计算。生成器必须在采样阶段有意识地偏向绿名单,检测器则需要处理分词器版本、语言差异、文本长度和阈值校准。阈值越低,越容易捕获被编辑过的内容,也越容易误报;阈值越高,证据更谨慎,但漏报会增加。

开源社区面对的是可验证性与规避风险

开放权重模型让研究者能够检查实现、复现实验并部署自己的检测器,这有助于审计水印是否真的不影响质量。然而,一旦生成算法、密钥派生方式或 token 划分规则完全暴露,攻击者也更容易针对信号进行移除或伪造。

完全封闭同样存在问题:外部平台无法独立检查误报率,不同厂商的检测结果也难以互操作。更可行的方向是把算法、密钥和验证服务分层管理,例如公开方案和评测方法,保护实际签名密钥,并通过版本化检测接口提供可审计结果。

开源项目还需要明确角色边界。模型维护者、推理服务运营者、下游应用和最终部署者可能承担不同责任。仅在仓库中加入一个可选的 watermark=true 参数,并不能保证生产请求真的启用了它,也不能证明代理服务器和后处理流水线保留了水印。

上线前应验证什么

团队不宜把统计水印当作独立的真实性判定器。采用前至少完成以下检查:

  • 对不同语言、文本长度、温度和采样参数分别测量误报率与漏报率。
  • 测试复制、格式化、人工编辑、翻译、摘要和模型改写后的检测强度。
  • 固定模型、tokenizer、水印方案和检测器版本,并保留升级记录。
  • 将检测结果表示为带阈值和版本的概率性证据,不直接等同于作者身份或违法结论。
  • 同时建设可见披露、结构化来源元数据、访问日志和申诉流程。
  • 让法律与合规团队依据最终法案文本、适用角色和产品场景确认义务。

统计水印提供了一种适合大规模自动检测的信号,但它不是密码学意义上的内容签名,也无法单独解决内容归属问题。更稳妥的落地方式,是把它放进完整的内容来源体系:生成时标记,传输时保留,平台侧记录,检测时量化不确定性,并允许结果被审计和复核。


相关推荐