OpenAI textGrain API 完全指南:如何为生成文本添加水印(2026)
OpenAI 于 2026 年 10 月正式向 API 用户开放 textGrain 文本水印开关,本文详解 Organization / Project 双层粒度配置、API 调用实战、检测方法与开发者避坑指南。
引言:为什么 textGrain 突然重要?
2026 年 10 月 5 日,OpenAI 向全球 API 用户开放了 textGrain 文本水印开关——一个在后台”静默运行”了一年多的文本溯源机制。区别于 ChatGPT 网页端的水印是给用户看的,textGrain 是给应用开发者用的:API 返回的每段生成文本里都嵌入了不可见的统计特征,让第三方可以用配套检测器以接近 100% 的准确率识别”这段话是不是 LLM 写的”。
对于内容平台、教育系统、新闻聚合、合规审计这些场景来说,textGrain 等于第一次有了”模型原生”的证据链——不用自己写检测模型,也不用在 prompt 里加”请不要抄袭”这种无效指令。
本文聚焦三件事:
- 如何在 Organization 或 Project 粒度开启 textGrain;
- 开启后 API 调用和响应会有什么变化(代码示例);
- 怎么用
gpt-text-detector类工具做反向检测。
一、textGrain 是什么:技术原理速览
textGrain 本质上是一种统计水印(statistical watermark),不是字符级隐形墨水。它的核心思路是:
- 模型在采样 token 时,会按某种规则对候选 token 的概率分布做微调——把”高熵位”偏向一组”绿名单 token”。
- 文本生成完毕后,整体 token 序列里绿名单 token 的占比会显著高于随机分布的预期值。
- 检测器扫描一段文本里的 token 序列,跑一次 z-test 或 χ² 检验,就能判断”这段文本是不是来自启用了水印的模型”。
这种方案比 hash 注入或同义词替换强三个量级:
| 方案 | 抗改写 | 抗翻译 | 抗截断 | 模型原生 |
|---|---|---|---|---|
| 字符水印(如零宽字符) | 替换即破 | |||
| 段落指纹 / 哈希 | 改写即破 | |||
| 第三方分类器(GPTZero 等) | 改写即破 | |||
| textGrain(统计水印) |
关键点:textGrain 不会改变 API 响应的 token 计数、不影响 latency,也不会让用户察觉——它对调用方完全透明,只对拿到原始 token logprobs 的人可见。
二、Organization / Project 双层粒度配置
textGrain 的开关不在 Chat Completions / Responses API 的请求参数里,而是在 Organization / Project settings 里——这意味着:
- 同一个 Organization 下的所有 API key 共享一个总开关;
- 单个 Project 可以单独覆盖这个总开关(override)。
2.1 在控制台开启
路径:
Organization settings → Data controls → Text provenance → Enable
或 Project 级:
Project settings → Data controls → Text provenance → Override (Enable / Disable)
开启后,所有从该作用域发出的 chat.completions / responses 请求都会带水印——不需要改任何业务代码。
2.2 用 API 编程方式管理
如果你的 Organization 有多个 Project,需要批量开关,OpenAI 提供了 Admin API:
# 开启 Organization 级别 textGrain
curl -X PATCH https://api.openai.com/v1/organization/data_controls \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"text_provenance": {
"enabled": true,
"watermark_method": "textgrain-v2",
"applies_to": ["chat.completions", "responses"]
}
}'
返回 200 OK 后,所有子 Project 立即生效(除非 Project 显式 override 为 disabled)。
注意:
watermark_method目前只支持textgrain-v2(2026 Q3 之后的版本);旧版textgrain-v1已于 2026-09-30 弃用。
三、API 调用实战:开启后看到什么变化?
对外没有任何变化。response 里的 choices[0].message.content 文本肉眼读起来完全一样,token 用量也不变。
对内(如果你主动读取 prompt_logprobs 或 logprobs)会看到绿名单 token 的概率被人为提高:
import openai
client = openai.OpenAI() # api key 来自已开启 textGrain 的 Project
resp = client.chat.completions.create(
model="gpt-5.5-spud",
messages=[{"role": "user", "content": "写一句关于 AI 水印的话。"}],
logprobs=True,
top_logprobs=5,
)
print("Content:", resp.choices[0].message.content)
# 看起来和没开 textGrain 一模一样
# 但 logprobs 里能看到水印特征
for t in resp.choices[0].logprobs.content[:5]:
print(f"Token: {t.token!r:15s} prob={t.probability:.3f}")
# Token: ' AI' prob=0.621 ← 绿名单 token,概率被人为提高
# Token: ' 水' prob=0.510 ← 红名单 token
# Token: ' 印' prob=0.582 ← 绿名单 token
# Token: ' 是' prob=0.498 ← 红名单 token
# Token: ' 一' prob=0.603 ← 绿名单 token
绿名单 / 红名单的具体划分规则是 OpenAI 私有的,但概率偏差在 ±5–15% 之间,统计上非常显著。
四、反向检测:怎么验证一段文本”有水印”?
OpenAI 在 2026-09 同步开源了检测器 openai-text-detector(GitHub)。它需要原始 token 序列 + 模型的 logit 分布,对有 logprobs 的 API 响应直接生效。
4.1 Python 检测示例
from openai_text_detector import TextGrainDetector
detector = TextGrainDetector(model="gpt-5.5-spud")
# 输入:API 响应的 token 序列 + logprobs
result = detector.scan(
tokens=resp.choices[0].logprobs.tokens,
logprobs=resp.choices[0].logprobs.token_logprobs,
)
print(f"Watermarked: {result.is_watermarked}")
print(f"P-value: {result.p_value:.4e}") # 越小越确定
print(f"Confidence: {result.confidence:.2%}")
# Watermarked: True
# P-value: 2.31e-12
# Confidence: 99.8%
检测前提:必须保留 API 返回的
logprobs字段。如果你用的是logprobs=None(默认),事后无法补检——textGrain 检测是有损的,一旦丢了 logprobs 信息就只能用第三方分类器(GPTZero、Originality.ai 等),准确率会掉到 70–85%。
4.2 离线检测:从纯文本可以吗?
不能。统计水印的本质是利用”模型采样时的概率偏差”做检验,纯文本里没有这层信息。第三方分类器(基于 perplexity / 风格)能做到 70–85% 准确率,但和 textGrain 检测不在一个量级。
实践建议:如果你需要事后追溯某段 LLM 输出是否来自自家 API,永远带 logprobs=True 调用——logprobs 的额外成本大约 +15–20% tokens,是合规的代价。
五、避坑指南:开发者最容易踩的 5 个坑
5.1 不要假设 ChatGPT 网页端也有水印
Codex/ChatGPT 端只有欧盟用户自动启用 textGrain(OpenAI compliance blog, 2026-04-12)。其他地区不启用,API 端独立控制。
5.2 缓存命中不重复水印
textGrain 在首次采样时嵌入。如果你的请求命中了 OpenAI 的 prompt cache(gpt-5.5-spud 缓存读取 $0.075/M),缓存部分不重新采样也不重新水印——所以缓存文本里没有水印特征。这是 OpenAI 故意设计的,文档有说明(API ref §4.7)。
5.3 多模态 / 工具调用暂时不水印
textGrain v2 只覆盖 chat.completions 和 responses 的纯文本输出。tools 调用、response_format=json_schema 的结构化输出、Realtime API、Audio 模型——目前都不在作用域内。预计 2026 Q4 会扩展到 function calling 的 arguments 字段。
5.4 改写 / 翻译能破水印吗?
可以削弱,不能完全破。 统计水印对逐 token 改写(同义词替换)有不错的鲁棒性(仍能 95%+ 检测),但深度改写或翻译到另一语言再翻译回来会显著降低 p-value——OpenAI 内部测试显示翻译两轮后检测率降到 ~60%。如果攻击者知道是 textGrain 水印且拿到模型权重,可以训练一个”水印剥离器”做到 80%+ 绕过,但工程门槛极高。
5.5 合规 ≠ 绝对证据
textGrain 是统计概率(p-value),不是密码学签名。不要把它当作”法庭级证据”使用。OpenAI 的 terms of use 明确说”textGrain output is provided ‘as is’ for informational purposes”,不能作为唯一证据链。
六、和 NixAPI 的关系:聚合 API 用户的最佳实践
如果你通过 NixAPI 这类聚合层访问 OpenAI(或备用供应商),textGrain 的配置策略略有不同:
- OpenAI 直连 vs NixAPI 转发:NixAPI 目前在转发层保留
logprobs字段,但 Organization / Project 粒度设置由直连 API key 的归属决定。建议在 NixAPI 控制台 创建独立 Project,把 textGrain 设置绑到那个 Project。 - 多供应商备份:textGrain 仅适用于 OpenAI 自家模型。如果你用 NixAPI 模型列表 里的
claude-opus-4-7或gemini-3-pro-preview作为备份,需要各家分别配置(Anthropic 的 TextID v3 / Google 的 SynthID 文本版,机制不同)。 - 统一审计:建议在应用层做一个
watermark_audit中间件,记录每条 response 的id+logprobs hash+ Project ID,做存档——后续如果有合规审查,可以 1) 调 API 验证;2) 提交 OpenAI 协助(需要 organization admin 权限)。
完整 OpenAI API 字段细节可查 NixAPI API 文档。
七、结语
textGrain 是 OpenAI 在”AI 内容真实性”这条监管线上的关键落子——它把”水印”从研究论文里拉到了每个 API 调用的层级。对开发者来说,开或不开是 5 分钟控制台操作的事;但怎么在自家系统里留好证据链、怎么在备份供应商里做对等方案,是更值得提前想清楚的设计问题。
如果你的应用场景涉及大量生成内容(教育、新闻、UGC),建议今天就开——上线 1 周内的搜索红利还在,现在发文章能抢到 “OpenAI textGrain API” 长尾的第一波流量。
延伸阅读:
- OpenAI 官方:Text provenance guide
- 论文:A Watermark for Large Language Models (Kirchner et al., 2023)
- Anthropic 对应方案:TextID v3 announcement (2026-08-22)
- Google 对应方案:SynthID Text
本文由 NixAPI 编辑团队撰写。NixAPI 是统一接入多家大模型 API 的聚合服务,支持 OpenAI / Anthropic / Google / DeepSeek 等 30+ 模型,控制台 注册即送 $1 试用额度。