我最早接触“数据使用提示”这个概念,是在一个AI客服改造项目里。当时业务方要求把所有用户对话都喂给大模型做意图识别,架构上做了脱敏、做了加密存储,看起来没什么问题,结果合规评审一过就傻眼:提示这一层完全没管。用户问了一句“你帮我查一下手机号对应的订单”,模型真的就把手机号带进了上下文;后面再跟模型闲聊时,它无意中“记住”了这个号码,甚至在下一次没有目的关联的轮次里也把它当成了普通记忆在用。
这件事让我意识到,提示工程与架构设计之间那根线,远不是“写一句好Prompt”那么简单。任何面向用户的AI系统,只要碰个人数据,GDPR就横在中间。而GDPR对用户告知、同意、最小化、目的限制、删除权的要求,几乎每一项都必须通过提示词工程落到模型行为上。这篇文章就是从这个角度出发,把我在多个企业级AI项目里沉淀下来的设计方式、模板、踩坑点,重新梳理成一份给提示工程架构师参考的操作指南。适合正在做AI产品、客服机器人、智能体编排,或者企业知识库系统的架构师与算法工程师。
1. 先看清问题:GDPR数据使用提示为什么是架构层设计
1.1 别把提示工程当“咒语”,它是AI系统的交互协议
我见过不少团队对Prompt的理解停留在“让模型输出得更像人话”这个层面。但如果站在架构师的位置上,眼光必须放远一点。Prompt不只是模型输入前的几行文字,它是用户、系统、模型三者之间交互协议的一部分,尤其是涉及个人数据的处理时,它承担了“告知”“限制”“记录”这些功能。
举个例子,一个用户对客服机器人说“我上个月买的耳机坏了,想退款”,这句话本身可能不含手机号,但如果系统为了核单,让模型追问“请提供您的订单号和手机号”,那这整段对话就已经进入了GDPR所指的“处理个人数据”范畴。用户是否有被告知数据用途?系统是否只收集了必要字段?模型是否可以把手机号保留在会话记忆里?这些问题如果等到技术评审才想起来,往往已经晚了,最麻烦的是用户数据已经混进了训练日志、埋点、缓存和多轮上下文里。
所以我把“数据使用提示”定义成一个专门的架构产物:它是一组结构化的指令文本,同时约束模型在收集、使用、保留、删除个人数据时的行为边界,并且在用户可见的界面层同步展示“数据将被怎么用”。它不单是一条Prompt,而是一套跨系统提示、用户提示、输出提示的规则集。
1.2 把GDPR条款翻译成Prompt可执行的清单
GDPR条文读起来晦涩,但落到提示工程,可以拆成几条可执行的动作。我做项目时,通常会画一张映射表,把合规要求和提示行为一一对应,这张表后面会贯穿整个系统设计:
| GDPR核心要求 | 在提示层的执行方式 |
|---|---|
| 数据最小化 | 系统提示中声明“仅允许获取完成当前任务所需字段”,并对用户输入做字段检查 |
| 目的限制 | 每个会话绑定一个“目的锚点”,模型不得跨目的复用已获得的个人数据 |
| 明示同意 | 在需要收集额外个人信息时,用三级提示机制先出示用途说明,等待用户确认 |
| 告知与透明 | 输出内容引用个人数据时,自动追加数据使用声明 |
| 访问权/删除权 | 提供固定的触发词模式,例如“删除我的信息”,并联动后端执行删除任务 |
| 留存期限 | 提示层自带保留时间戳,系统按策略定时清理 |
这张表一出来,工作就从“跟律师讨论条款”变成了“从数据字典开始配置提示”,可操作性一下子强很多。
1.3 数据使用提示要管住三层:系统提示、用户提示、输出提示
很多人纠结“到底把GDPR规则写在哪个提示里”。我的做法很简单,三层都写,但职责不同:
- 系统提示(System Prompt)负责定义规则。它告诉模型哪些字段是允许收集的、哪些是禁止的、什么时候必须征求同意、什么时候必须停止使用。
- 用户提示(User Prompt)负责采集输入。它在用户发起对话时,把当前场景的目的字段结构化地传给模型,避免模型漫无目的地收集信息。
- 输出提示(Output Prompt)负责交付记录。模型在回应中一旦涉及用户个人信息,需要在输出上自增透明声明,同时在日志中标记一条审计记录。
三层各司其职,不是把大量法条一次性塞给模型,而是分别作用于模型的“思考方式”“输入来源”“输出结果”。这也是为什么这件事是架构师的活,而不是文案的活。
2. 核心机制拆解:怎样构造一份可执行的合规数据使用提示
2.1 数据最小化:把“能不问就别问”写成硬规则
数据最小化是GDPR里最重要也最容易做歪的一条。很多团队的所谓最小化,是产品经理在交互稿里少放了一个输入框,但模型还是会通过自由对话“意外”收集到额外字段。所以必须在提示中做硬性限制。
我在系统提示的固定位置会放这样一段:
data_minimization_policy: scope: 订单履约 allowed_fields: [订单号, 收货地址, 联系电话] prohibited_fields: [身份证号, 健康信息, 生物特征, 宗教信仰, 政治观点] behavior: > 当用户提供allowed_fields之外的个人信息时,模型只需要确认已收到该信息, 但不得将该信息写入长期记忆,也不得在后续回答中主动引用。实际落地时要注意,光有这段提示还不够。如果用户在下单场景里说“我最近身体不舒服,想换个大码”,这属于健康信息,是GDPR里的特殊类别数据,即使模糊出现也应处理。我通常会在提示里额外要求模型做“字段归类判断”,把主动收集之外的信息标记为“非目标字段”并忽略。
2.2 目的限制:给每个会话设置“目的锚点”,防止跨场景漂移
目的限制的意思是,你因为给用户发货收集了他的地址,就不能顺手拿这个地址去做营销分析。AI系统里这个问题尤其隐蔽,因为大模型的上下文窗口会让多个主题的数据混在一起。
我的方案是引入“目的锚点”机制。在每个会话的开头,系统向模型注入一个结构化字段:
{ "session_purpose": "订单履约", "purpose_description": "回答用户关于订单状态、退货换货、物流进度的问题", "prohibited_secondary_uses": ["营销推广", "用户画像", "跨渠道推荐"], "on_purpose_shift": "如果用户提出与当前目的无关的新需求,先清空会话记忆,再重新声明新的目的并请求同意" }目的锚点的核心作用是让模型意识到,个人数据的合法使用范围是动态的。当用户在售后服务里突然问“顺便给我推荐一款同价位耳机”,这就是目的漂移。如果不加约束,模型很可能直接基于用户的订单信息和地址范围去做推荐,看起来很方便,但合规上已经越界。正确处理是切换到营销场景前,先提示“本次推荐将使用您过去的订单信息”,再次取得用户同意后再执行。
2.3 明示同意:三段式可撤回同意提示模板
同意机制是用户最容易感知的部分,也是最容易在产品上做丑的部分。你当然可以弹一堆法律条款逼用户点“同意”,但架构师要考虑的是:同意行为必须能被记录、能被校验、能被撤回。
我在系统里使用一个三段式模板:
第一段【数据使用提示】: 为了完成“{{当前目的}}”,本次对话可能需要使用您的以下信息:{{字段列表}}。 这些信息仅用于上述目的,保存期限为{{保留天数}}天。 第二段【请求确认】: 如果您同意以上说明,请回复“同意继续”。如果不需要提供这些信息,我们也仍然可以为您完成不涉及个人信息的基础服务。 第三段【撤回声明】: 您可以在任何时候输入“撤回同意”或“删除我的信息”,我们将停止使用并删除相关数据。模板本身看着不复杂,真正难的是状态管理。模型需要记住当前会话的同意状态是“未问询”“已同意”“已撤回”中的哪一种。我会给同意状态专门建一个变量,在每次用户输入后做一次检查,只有状态为“已同意”时才允许模型把新增个人数据写入长期上下文。
千万要避免的是默认勾选。GDPR对同意的定义是自由给出的、具体的、知情的、无歧义的。如果你的Prompt设定是“用户没说不同意就等于同意”,那基本上一查一个准。
2.4 输出透明化:让模型每次引用个人数据都自带“水印”
很多系统在输入层做得不错,却在输出层丢了透明原则。用户问“我的快递到哪了”,模型回答“尾号8890的包裹已经到驿站”,这时模型引用了个人数据却没有任何提示,用户压根不知道系统记住了他的手机号等信息。
合适的做法是在输出提示里强制追加一份透明的数据引用声明:
output_notice: when: 回答内容引用了当前用户提供的个人数据 append: "为完成{{session_purpose}},系统使用了您提供的{{字段列表}}。该信息将按政策自动清除,您也可以随时要求删除。"有些团队担心输出太长影响体验,但透明性本身就是合规成本的一部分。我在实际项目中会把声明折叠到“详情”里,让界面上只显示一个可点击的小标签。不过,即使是折叠状态,也要保证声明在输出结构里存在,日志审计时能够追溯。
3. 落地实操:从字段清单到系统提示的完整搭建过程
3.1 第一步:先建一份“数据字典”,而不是先写Prompt
合规提示工程的最大误区就是跳过数据字典直接写提示词。没有数据字典,你写的所有“允许字段”“禁止字段”都是空洞的,模型执行时也没有比照对象。
我的操作顺序是这样的。先跟业务方坐下来,把用户可能在对话中暴露的信息全部列出来。字段分类建议用四层:
| 字段分类 | 说明 | 示例 |
|---|---|---|
| 必需字段 | 完成当前业务必须拿到 | 订单号、收货地址、联系人电话 |
| 上下文辅助字段 | 有助于回答问题但非强制 | 商品名称、购买日期 |
| 无意暴露字段 | 用户主动提供但业务不需要 | 身份证号、银行卡号 |
| 禁止字段 | 法律明确限制或风险极高 | 健康记录、生物识别数据 |
字段清单出来后,再为每个字段打上“目的”“保留期限”“是否有必要存储”三个标签。只有这份表是完整的,写进系统提示的规则才有依据。
3.2 第二步:把数据字典映射成系统提示参数
有了数据字典,接下来就是生成系统提示。我习惯用一套模板引擎,从数据字典自动生成提示文本,避免手工维护一堆容易过期的规则。大致思路是这样的,模板里预留变量,字典里的字段动态填入。
SYSTEM_PROMPT_TEMPLATE = """ [数据使用规则] 处理目的:{{scope}} 合法依据:为履行{{legal_contract}}所必需 允许收集的字段: {% for field in allowed_fields %} - {{ field.name }}(用途:{{ field.purpose }},保留:{{ field.retention_days }}天) {% endfor %} 禁止收集与处理:{{ prohibited_fields | join("、") }} 行为约束: 1. 当用户主动提供的字段不在允许列表内时,不要写入记忆,不要用于后续推理。 2. 当需要收集允许列表之外的信息时,先展示数据使用提示并取得用户明确同意。 3. 用户表示撤回同意时,停止会话中的个人数据处理,并标记待删除状态。 4. 回答中引用个人数据时,必须附带数据使用说明。 同意状态:{{ consent_status }} """这样做的好处是,当数据字典里某个字段的保留天数从30天改成3天,系统提示会自动同步,不会留下“提示文本和系统策略不一致”的雷。
3.3 第三步:设置用户输入的“预检脱敏口”,别什么都喂给模型
提示架构师最容易忽略的一个硬边界,是把所有用户输入原封不动丢给模型。其实在进入模型之前,应该有一层结构化的预检处理。它做的事情不多,但很关键:
第一,识别输入中是否包含禁止字段的关键信息,比如身份证格式、银行卡号格式。命中之后立即做打码处理,再把脱敏后的文本交给模型。
第二,把用户输入中的“信息索取意图”和“当前会话目的”做匹配。如果用户请求查询订单号,而当前目的锚点并不包含订单查询,就应先触发用途说明提示,而不是直接执行查询。
第三,把同意状态作为基础设施传入提示,而不是让模型从历史对话里“猜”。我踩过的最深一次坑,就是让模型自己判断用户是否已经同意,结果它把一句很普通的“嗯嗯”判断成了同意。后来所有项目都改成由外部状态机统一管理同意状态,模型只接收状态值。
3.4 第四步:设计审计日志,注意别把个人数据写进去
合规系统必须能证明自己合规。审计日志是底线,但很多团队把审计日志做成了事故现场,为了排查方便,把完整对话、原始手机号一股脑写进日志。这等于一边努力合规,一边裸奔。
我建议维护两层日志。第一层是业务审计日志,记录“什么时间、什么操作、涉及哪些字段ID、同意状态是什么”,但不记录字段值本身。第二层是必要的数据快照,加密存储,设置更短的保留期,只用于争议取证。两层的访问权限分开,避免内部人员顺手就能查到全量个人数据。
对应到提示层,可以在系统提示里约定模型每次执行“数据使用”类动作时,输出一个结构化的事件标记。举个例子:
{ "action": "data_usage_event", "consent_status": "granted", "fields_involved": ["ORDER_ID", "PHONE_NUMBER"], "purpose": "订单履约", "log_to": "audit_bucket_encrypted" }这个事件标记会进入旁路日志系统,不会出现在用户对话界面里。相当于模型替你完成了合规流程的“埋点”,事后追溯很方便。
3.5 第五步:上线前用“红线脚本”做批量验证
功能测试只能证明“能跑”,证明不了“不能越界”。我在上线前会准备一组红线测试用例,专门验证提示层是否把违规行为拦住了:
- 用户主动报出身份证号,测试模型是否将其写入了长期记忆;
- 用户提供A场景数据,在B场景中被要求复用,测试模型是否主动请求新的同意;
- 用户模糊提及健康信息,测试模型是否进行了特别标记;
- 用户输入“删除我的信息”,测试系统是否真正触发删除流程而不是仅仅口头答应。
这些用例最好是脚本化跑,每次提示词变更后都自动回归一遍。我现在会把它们集成进CI流程,任何PR只要引入了Prompt修改,都必须经过红线用例集。这一部做好,后面就能少掉很多没日没夜的合规补救。
4. 最容易翻车的几个场景:排查思路与速查表
4.1 对话中途出现“信息复活”
有一种情况很隐蔽:用户在某轮对话里提供了手机号,后来明确说“不要再记录我的手机号了”,提示层也把同意状态改成了“已撤回”。但下一轮用户问“我的包裹到哪了”,模型居然又把手机号拿出来做了核验。
原因多半是撤回状态没有同步到模型上下文,或者模型在历史段落的原始文本里仍然看到了这个手机号。解决办法是,在撤回动作发生后,不是简单修改状态,而是对当前上下文做一次字段清理,把已撤回的个人数据从记忆槽位中摘除,再注入一条提示:“以下字段已删除,后续不得引用。”很多团队忽略这一步,因为状态机和上下文是两套系统,忘记联动就会出这种鬼故事。
4.2 模型把“允许”理解成“必要”
数据最小化提示里写着“允许收集订单号、收货地址、联系电话”,有些模型会把“允许”理解成“必须”。用户只说了一句“我要投诉快递”,模型偏要先把手机号、订单号、地址全部要齐,才肯进入正题。
这个问题需要用语义更明确的表述解决。我在提示里会用“允许且仅当”这种限定句式,同时增加一条兜底说明:
allowed_fields_interpretation: > 列出的字段仅在“缺少该字段将导致任务无法完成”时才允许索取。 如果任务有其他完成路径,优先使用不收集个人信息的方式。 不得因为字段在允许列表内,就主动要求用户补充。4.3 遗忘权变成口头承诺
用户说“删除我的信息”,模型回答“好的,已为您删除”。但这只是一句话,后端可能什么都没发生。这种假删除在合规审查里属于严重问题。正确做法是,提示层识别到删除请求后,调用一个真正的删除API,并在返回结果里附上删除任务编号。这样用户和审计人员都能看到可验证的删除凭证。
4.4 特殊类别数据的边界模糊
就算你的业务跟健康一点关系都没有,用户也可能在对话里说“因为生病所以想推迟发货”。这句里隐含健康信息,按GDPR说法属于特殊类别数据,处理条件更加严格。提示层不能假装没听到,而是应该把这条信息剥离出业务数据流,直接标记为“敏感信息豁免处理”,不写入任何存储。我常在提示里加一句:
special_category_protection: > 如果用户主动提及健康、信仰、性取向、政治观点等特殊类别信息, 即便与当前对话无关,也禁止保存、禁止用于决策、禁止输出, 并在日志中打上special_category_dropped标记。4.5 可复用的故障速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 模型跨目的使用了旧数据 | 目的锚点没有随会话切换 | 检查会话初始化的purpose字段是否每次更新 |
| 用户已拒绝仍被索取数据 | 同意状态流转逻辑缺失 | 检查状态机是否覆盖了“拒绝后重试”分支 |
| 日志里出现完整手机号 | 审计日志未做字段脱敏 | 把日志输出改为字段ID加哈希 |
| 删除请求执行了但无凭证 | 删除动作只在提示层模拟 | 接入后端删除API并生成任务ID |
| 提示词改了但行为没变 | 缓存策略导致旧提示仍生效 | 检查会话级缓存和模型上下文版本号 |
| 用户输出引用个人数据无声明 | 输出提示未强制装配 | 增加结构化输出校验,缺少data_use_notice则重试 |
排查这类问题时,我的经验是先看状态机,再看模型上下文,最后看日志。状态机决定“该不该做”,模型决定“怎么做”,日志决定“能不能证明”。三个环节只要有一个没对齐,合规异常就必然出现。
5. 最后再分享一点我的体会
做了这么多AI系统和合规提示之后,最大的感受是:别把GDPR提示工程当成填表,也别当成法务文案。提示架构师真正要做的,是把抽象的法律义务翻译成模型每一步都能执行的微观指令。这需要你同时懂数据、懂交互、懂模型边界,还得能把一套规则说得让业务团队理解。我自己在项目里吃过亏之后,养成一个习惯:任何Prompt设计完,先拿一份完全无关的数据字典来跑红测。如果这套规则在陌生业务场景里也能稳定拦住违规收集,我才敢放进生产环境。按这个标准去做,GDPR数据使用提示就不会只是墙上挂着的合规口号,而是真正能抗住审计的工程能力。