ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Prompt Privacy实战:提示词脱敏与匿名化方案全解析

Prompt Privacy实战:提示词脱敏与匿名化方案全解析 在业务系统接入大模型LLM时最大的隐形风险不是模型回答得不好而是我们发出去的 Prompt 本身。很多团队在调试智能客服、知识库问答或代码助手时习惯直接把客户姓名、手机号、邮箱、内部 API Key、数据库连接串粘贴到 Prompt 里然后把请求发送给云端模型接口。这样做功能跑得很快但 Prompt 里的明文数据也随着请求一起离开了可信环境。本文会从 Prompt Privacy 的定义讲起拆解提示词在调用链路中的泄露风险然后给出一套可落地的提示词脱敏与匿名化方案包含完整的 Python 组件、配置文件、调用示例和排查思路。无论你是后端开发、AI 应用开发还是正在做 LLM 合规治理的技术负责人这篇文章都值得收藏备用。1. 背景与核心概念1.1 什么是 Prompt PrivacyPrompt Privacy翻译过来就是“提示词隐私”指的是在把用户输入组装成提示词、发送给大模型执行时对其中不属于模型必须知道的敏感信息进行遮蔽、替换、隔离和审计使整个模型调用链路尽可能少地接触真实数据。这里的关键词是“尽可能少”因为 LLM 应用往往不是只有模型本身而是由客户端、网关、日志、模型服务、甚至人工标注系统组成的一条完整链路。真正的提示词隐私保护要求我们在输入侧做脱敏在链路侧做防护在结果侧做还原三层都做到位隐私才是基本可控的。为什么这个问题越来越受关注因为大模型判断能力越强我们越倾向于给它更多上下文结果就是 Prompt 中包含的数据密度越来越高。一段提示词里可能同时包含用户姓名、身份证号、住址、订单金额、内部备注信息这些数据一旦进入外部模型接口就不再完全受我们控制。即便模型服务商不会主动泄露数据访问日志、异常监控、数据训练、安全审核等环节都可能留下明文副本而在企业内部这些副本又会进入日志系统、BI 报表、搜索索引形成一条条看不见的数据泄露面。Prompt Privacy 的常见应用场景包括客服对话系统在调用大模型做摘要时需要遮蔽电话号码和地址企业代码助手在请求补全时不能把包含密钥的代码片段发到公有云知识库问答系统在命中内部文档后必须控制返回结果中敏感信息的可见范围金融、医疗等强监管行业在接入 LLM 时还要满足数据出境和分级分类要求。可以说只要业务里存在“把文本发出去换回答”的动作就绕不开 Prompt Privacy。1.2 一次普通 Prompt 请求经历了什么我们先来看一次普通的 Prompt 请求在网络上是怎么流动的用户输入 → 前端页面/客户端 → 浏览器插件或IDE插件 → 业务后端 → 脱敏/审计层 → API网关 → 云厂商接口 → LLM推理引擎 → 结果返回 → 日志数据库这里有几个很容易被忽略的事实第一个是浏览器插件、IDE 插件这类工具可能在你输入的时候就自动收集上下文比如自动补全插件会把当前打开的文件内容一起带进请求第二个是业务后端在调用模型之前通常会在日志里打印请求参数如果打印的是完整 Prompt那这就是一个明文副本第三个是 API 网关为了保证可观测性会记录请求头和请求体同样可能保留 Prompt 原文第四个是云服务商侧会话记录、异常日志、人工标注队列都可能留存数据。所以即使我们在最终请求前加了加密传输也只能防住链路窃听防不住服务端留存。想要真正缓解 Prompt 隐私风险就必须把明文 Prompt 控制在一个尽可能小的边界内同时在所有可能落盘的环节做脱敏或截断处理。1.3 容易混淆的三个概念在讨论提示词隐私时有几个概念经常被混用帮大家区分一下。数据脱敏Masking把敏感内容替换成伪造值或占位符常见于测试数据和日志处理。脱敏是可逆的只要能保管好映射关系就能还原。匿名化Anonymization让数据无法关联到具体个人通常不可逆比如把姓名改成“用户A”、把邮箱完全删除。匿名化更彻底但在大模型场景下完全匿名化可能影响功能效果。提示词加密Encryption对传输和存储的文本做加密。需要特别注意的是模型在推理时必须解密才能理解内容所以加密解决不了“模型已经看过明文”的问题只能解决链路窃听和静态存储泄露。很多人把“传输加密”当作 Prompt Privacy 的全部这是一个明显的误区。传输加密是基础但只是其中一环。真正的提示词隐私策略应该同时包含脱敏、审计、最小化和存储控制而不是只依赖某一种技术手段。2. 提示词隐私的主要风险路径2.1 上游采集风险第一个风险点集中在客户端和插件侧。开发者电脑上的 IDE 插件、浏览器扩展、剪贴板管理工具都可能成为 Prompt 数据泄露的源头。比如代码补全插件会把当前打开的文件内容作为上下文发送出去如果文件里恰好有数据库密码或云厂商凭证这些敏感信息就会跟着请求一起外发。更隐蔽的是很多工具在安装时会默认开启遥测和“改进建议”功能用户输入的数据会被回传到插件厂商的服务端。解决这类风险不能只靠提示词脱敏因为脱敏是发生在请求组装之后而插件可能在组装之前就已经把数据传走了。更合理的做法是在开发环境中使用最小权限插件关闭不必要的遥测开关在业务代码中把密钥和敏感配置放到环境变量或配置中心避免让它们在源码和文件内容里出现对必须使用外部 AI 工具的团队可以考虑沙箱环境或内部代理对出域请求做统一过滤。简单说DevOps 侧的安全基线往往比业务代码里的脱敏逻辑更重要。2.2 传输与存储风险Prompt 在请求链路中会以明文或半明文形式存在于多个系统。第一个是本地代理和抓包工具只要团队中有人开着 Charles 或 Fiddler并且没有做 SSL 解密限制HTTPS 请求也能被还原查看第二个是后端服务日志很多团队习惯在调用第三方接口前打印“请求参数”这个日志如果进入 Elasticsearch 或 Loki就会被长期保存第三个是消息队列和业务数据库一部分企业会把 Prompt 原文保存到数据库里用于后续分析却没有对这些数据做加密和权限隔离第四个是离线数仓当日志被清洗进数仓之后SQL 查询可以轻松拉出全量 Prompt 内容。针对这些风险最直接的措施是“日志只记录脱敏后的请求摘要”而不是完整 Prompt。如果确实需要保留原始数据供审计也应该单独建库、加密存储、严格控制访问权限。对于消息队列可以传递脱敏后的 Prompt原始数据不进入队列即便业务需要原始数据重放也应该在消费者端再做一次脱敏校验。2.3 服务端处理风险当 Prompt 请求发送到外部 LLM API 后我们就进入了数据控制权最薄弱的环节。不同的模型服务提供商对数据留存策略差异很大有的会把数据用于模型训练和模型改进有的会在人工评审、安全监测环节查看数据还有的会默认保留一定周期后才删除。在没有仔细阅读服务条款的情况下不能假设外部 API 收到 Prompt 后会立即丢弃。部分云厂商提供了“零数据保留”选项但这类功能通常需要显式开启也需要在合同中以书面形式确认。如果企业业务对数据主权要求非常高比如涉及核心客户隐私、员工个人信息或未公开的商业计划最稳妥的方案是私有化部署模型或者使用经过合规评估的内部模型服务。私有化部署虽然会增加 GPU 成本和运维成本但能让 Prompt 数据全部停留在自有基础设施内从根本上降低服务端留存风险。这个决策本质上是一种投入产出的权衡数据越敏感越应该把推理放在自己能控制的范围内。2.4 下游消费风险Prompt 数据泄露的另一个隐蔽渠道是下游消费系统。当日志进入 Elasticsearch 后DevOps 团队、数据分析师、算法工程师都可能看到日志索引当 Prompt 被写入 BI 报表系统之后只要报表访问权限设置不当全公司都能看到真实客户数据还有人工标注和模型评测流程外包标注团队可能接触到包含敏感信息的 Prompt 样本这也是合规审计中经常被点名的风险点。下游消费风险的处理思路和前面提到的“最小化原则”一致在数据进入下游系统之前先完成脱敏和脱密动作。如果下游只需要统计数据那么把真实值替换成占位符即可如果下游需要人工分析那么应该使用专门的匿名化平台对访问者做实名申请、审批和审计。Prompt 数据不应该作为一种“普通日志”被随意复制和流转。3. 环境准备与实验设计3.1 基础环境为了让后面的代码可以顺利运行我们先明确一套实验环境。本文的示例不依赖特定的云厂商重点演示“脱敏→调用→还原”这条链路如何落地因此你只需要准备以下内容操作系统macOS、Linux 或 Windows 均可Windows 建议使用 PowerShell 或 WSL。Python 3.9 及以上版本代码主要用到标准库re、json以及少量第三方库pyyaml、requests。一个可用的 LLM API 或本地模型推理服务。如果没有现成的 API也可以先跑通脱敏组件本身等有接口时再接入。一个用于实验的文本数据集建议准备一段包含手机号、邮箱、身份证号、API Key 的模拟文本。安装依赖的命令如下版本以你的实际环境为准pip install pyyaml requests需要说明的是示例代码中的模型名称、接口地址、响应字段结构都使用通用占位符。不同的模型服务提供商响应体结构可能完全不同你在接入时要根据实际 API 文档调整解析逻辑。3.2 实验流程设计我们做一个最小可行的实验构造一段包含敏感信息的内部文本交给PromptSanitizer做脱敏然后把脱敏后的文本发送给 LLM 做摘要或实体提取最后把 LLM 输出结果中的占位符还原成人可读文本。实验的关键点有两个第一真实数据不会出现在发送给模型的文本中第二模型看到的占位符不能过于影响语义理解。为了验证效果可以设计一组对比先用明文 Prompt 让模型总结再用脱敏 Prompt 让模型总结对比两个输出在信息完整性上的差异。通过这个对比你能直观感受到“脱敏会不会让模型变笨”这个问题。实际上只要占位符设计合理并在 Prompt 中增加一句“文本中的标记代表敏感数据请根据上下文理解含义”模型通常可以保持不错的理解能力。4. 核心方案提示词脱敏与匿名化实战4.1 脱敏组件的整体思路在动手写代码之前先明确一个完整的脱敏流程应该包含哪些步骤。第一步是识别Detect。我们可以用正则在文本中找到手机号、邮箱、身份证号、IP 地址、密钥模式也可以用命名实体识别模型识别更复杂的个人信息比如人名和公司名。第二步是替换Mask。把识别出的真实值替换成占位符例如把13800138000替换成__PHONE_0__把testexample.com替换成__EMAIL_0__。第三步是发送Send。将脱敏后的 Prompt 发送给 LLM并在 Prompt 中明确要求模型保留占位符格式。第四步是还原Restore。拿到模型的输出后用替换阶段的映射表把输出中的占位符还原成真实值。这里有几个设计要点。第一占位符必须容易识别建议使用__TYPE_INDEX__这种格式既能表示敏感类型又能支持同一个类型下的多个字段。第二同一个会话中同一个真实值应该映射到同一个占位符避免信息关联性丢失比如上下文里多次出现同一个手机号应该都用__PHONE_0__表示。第三映射表只能存在于内存中绝对不允许把映射表打印到日志或写入数据库。一旦映射表泄露脱敏就形同虚设。4.2 实现 PromptSanitizer下面我们来实现一个通用的脱敏组件。在项目目录下新建prompt_sanitizer.py完整代码如下# 文件路径prompt_sanitizer.py import re from typing import Dict, Pattern, Optional class PromptSanitizer: 提示词脱敏组件识别敏感信息替换为占位符并在模型输出中还原。 使用时请保持映射表只存在内存中不要落盘、不要进日志。 def __init__(self, patterns: Optional[Dict[str, Pattern]] None): self.patterns patterns or self._default_patterns() self.token_map: Dict[str, str] {} self._counter 0 staticmethod def _default_patterns() - Dict[str, Pattern]: return { EMAIL: re.compile(r[A-Za-z0-9._%-][A-Za-z0-9.-]\.[A-Za-z]{2,}), PHONE: re.compile(r(?!\d)(1[3-9]\d{9})(?!\d)), ID_CARD: re.compile(r(?!\d)\d{17}[\dXx](?!\d)), IP: re.compile(r(?!\d)((?:\d{1,3}\.){3}\d{1,3})(?!\d)), API_KEY: re.compile(r(?i)(sk-[A-Za-z0-9_-]{16,})), } def sanitize(self, text: str) - str: 识别文本中的敏感信息将其替换为 __TYPE_INDEX__ 格式的占位符。 每次调用会重置 token_map确保同一个 session 内使用独立的映射关系。 self.token_map {} self._counter 0 for sens_type, pattern in self.patterns.items(): def _replace(match, _typesens_type): return self._mask(match.group(0), _type) text pattern.sub(_replace, text) return text def restore(self, text: str) - str: 将模型输出中的占位符还原为真实值。 for token, real_value in self.token_map.items(): text text.replace(token, real_value) return text def _mask(self, real_value: str, sens_type: str) - str: # 同一个真实值在同一个 session 内映射到同一个 token for token, value in self.token_map.items(): if value real_value: return token token f__{sens_type}_{self._counter}__ self.token_map[token] real_value self._counter 1 return token这个类的核心逻辑并不复杂。_default_patterns定义了需要识别的敏感类型sanitize用正则把命中的文本替换成占位符restore再把占位符还原。值得说明的是_mask方法会先遍历已有映射如果同一个真实值已经出现过就直接复用之前的占位符这样能保持信息关联性避免同一个手机号被替换成两个不同占位符导致下游统计失真。在使用时需要注意正则的边界。比如手机号正则使用了(?!\d)和(?!\d)来避免匹配身份证号中的数字片段但真实世界的数据格式远比示例复杂比如带区号的座机010-88886666、带横杠的手机号138-0000-8000都不在当前规则里。实际落地的脱敏规则必须根据业务统计确认需要覆盖哪些格式并持续补充。4.3 添加规则文件正则模式如果硬编码在代码里后续维护起来会很不方便。实际工程中更推荐把规则放到独立配置文件中例如sensitive_rules.yaml# 文件路径sensitive_rules.yaml sensitive_rules: email: pattern: [A-Za-z0-9._%-][A-Za-z0-9.-]\\.[A-Za-z]{2,} phone: pattern: (?!\\d)(1[3-9]\\d{9})(?!\\d) id_card: pattern: (?!\\d)\\d{17}[\\dXx](?!\\d) ip: pattern: (?!\\d)((?:\\d{1,3}\\.){3}\\d{1,3})(?!\\d) api_key: pattern: (?i)(sk-[A-Za-z0-9_-]{16,})然后在 Python 中加载规则动态构造PromptSanitizer# 文件路径build_sanitizer.py import re import yaml from prompt_sanitizer import PromptSanitizer def build_sanitizer(config_path: str) - PromptSanitizer: with open(config_path, r, encodingutf-8) as f: config yaml.safe_load(f) patterns {} for name, rule in config[sensitive_rules].items(): patterns[name.upper()] re.compile(rule[pattern]) return PromptSanitizer(patterns)配置化的好处显而易见业务人员或安全人员可以独立维护规则不需要改动代码在灰度发布时也能通过配置中心动态开关某类规则的启停。但需要注意yaml文件中的正则表达式在编写时要小心转义YAML 解析和 Python 正则解析有两层语法建议在本地写单元测试来验证规则有没有写错。4.4 脱敏后调用 LLM 的完整示例现在我们把整个链路串起来。新建demo_llm_call.py代码如下# 文件路径demo_llm_call.py import requests from build_sanitizer import build_sanitizer from prompt_sanitizer import PromptSanitizer def call_llm(prompt: str, api_url: str, api_key: str) - str: 调用 LLM API 的通用示例。 注意不同模型服务商的请求体和响应体结构不同请根据实际 API 文档调整。 headers { Authorization: fBearer {api_key}, Content-Type: application/json, } payload { model: your-model-name, messages: [{role: user, content: prompt}], temperature: 0.3, } resp requests.post(api_url, jsonpayload, headersheaders, timeout60) resp.raise_for_status() return resp.json()[choices][0][message][content] def main(): # 1. 构造原始文本 raw_text ( 客户张三的手机号是13800138000邮箱是zhangsanexample.com 他所在的公司API Key是sk-abcdefghijklmnopqrstuvwxyz1234567890 请帮我总结这段信息中的客户联系方式和身份信息。 ) # 2. 初始化脱敏组件 sanitizer: PromptSanitizer build_sanitizer(sensitive_rules.yaml) # 3. 脱敏 safe_prompt sanitizer.sanitize(raw_text) print( 脱敏后的 Prompt ) print(safe_prompt) print() # 4. 调用 LLM # 如果没有现成 API可以改为 mocksafe_result 客户联系方式为 __PHONE_0__邮箱为 __EMAIL_0__API Key 为 __API_KEY_0__。 safe_result call_llm( promptsafe_prompt \n说明文本中的 __TYPE_INDEX__ 标记代表敏感字段请不要修改这些标记直接基于上下文回答问题。, api_urlhttps://your-llm-api.example.com/v1/chat/completions, api_keyyour-api-key, ) print( 模型输出含占位符 ) print(safe_result) print() # 5. 还原 restored_result sanitizer.restore(safe_result) print( 还原后的最终输出 ) print(restored_result) if __name__ __main__: main()这段代码把前面几个组件串成了完整链路。它的输出效果大致如下脱敏后的 Prompt 中不包含手机号、邮箱、API Key 明文模型返回的文本中带有__PHONE_0__、__EMAIL_0__、__API_KEY_0__等占位符最后的还原步骤把占位符替换回真实值得到原本可读的总结结果。这里有一个容易被忽略的细节还原步骤只能还原“模型输出中的占位符”但如果模型没有遵守“保留占位符”的要求而是把__PHONE_0__改写成“一个手机号”那么还原步骤就无法生效。所以在提示词里明确要求模型保留标记是非常必要的。如果模型仍然频繁改写可以尝试把占位符设计成更奇怪、更像专有名词的格式比如SENSITIVE_PHONE_0、MASKED_EMAIL_0降低模型改写它的概率。5. 进阶方案与工程化思路5.1 用本地小模型辅助发现敏感信息正则脱敏的问题是覆盖不全。像“客户名称”“公司内部项目代号”这类敏感字段并没有固定的格式正则无法识别。更进一步的方案是部署一个本地小模型用命名实体识别辅助识别敏感信息。因为模型在本地推理文本不需要外发所以仍然不会扩大数据暴露面。这个方案的整体思路是先用本地模型对输入文本做实体识别输出实体列表和实体类型然后把实体列表传给脱敏组件让脱敏组件不仅依赖正则也依赖模型输出。由于本地模型的精度不一定很高建议把模型输出作为“候选实体”由规则库判断是否真的需要脱敏。比如模型识别出一个“人名”实体但业务规则规定人名不需要脱敏那么就跳过如果识别出“证件号”则立即进入脱敏流程。这种“规则模型”双通道的方式比单纯依赖任何一种都更稳定。5.2 令牌化与映射表管理当业务中同一个真实值会在多个 Prompt 中反复出现时使用一次性内存映射表就不太合适了。比如售后场景中用户IDU12345会在多次对话里反复出现我们希望每一次调用都把它映射到同一个 token才能维持跨会话的关联性。这时可以引入令牌化服务真实值到 token 的映射表存放在数据库中每次调用前先查表或创建 tokenPrompt 中只使用 token结果返回后通过映射表把 token 还原为真实值。令牌化相比一次性脱敏的优势是可控性好可以统一管理、集中审计也可以在需要时批量轮换。缺点是需要维护映射表如果映射表本身被攻破所有未加密的真实值都会泄露。因此映射表至少要做到字段级加密存储、访问留痕、定期备份和权限隔离。5.3 日志链路脱敏很多情况下Prompt 明文不是业务代码泄露的而是日志系统泄露的。Python 的logging模块支持自定义 Filter我们可以统一在日志输出前对敏感字段做打码处理。下面这个示例实现了一个最简单的日志脱敏过滤器# 文件路径log_redact_filter.py import logging import re SENSITIVE_PATTERNS [ re.compile(r[A-Za-z0-9._%-][A-Za-z0-9.-]\.[A-Za-z]{2,}), re.compile(r(?!\d)(1[3-9]\d{9})(?!\d)), re.compile(r(?i)(sk-[A-Za-z0-9_-]{16,})), ] class RedactFilter(logging.Filter): def filter(self, record: logging.LogRecord) - bool: if isinstance(record.msg, str): for pattern in SENSITIVE_PATTERNS: record.msg pattern.sub([REDACTED], record.msg) return True把这个 Filter 挂载到 root logger 或业务 logger 上就可以在日志落盘之前把手机号、邮箱、密钥等模式替换成[REDACTED]。对于 FastAPI、Flask、Django 这类框架请求日志通常由中间件或装饰器打印可以在中间件中先调用PromptSanitizer.sanitize()再记录日志。这里需要特别强调的是日志脱敏过滤器只应该作为最后一道兜底不能作为唯一防线。更合理的做法是在业务入口处就直接脱敏日志打印只输出安全摘要。5.4 从规则到平台的演进当 LLM 调用规模变大之后散落在各业务代码里的本地脱敏组件会变得难以维护。比较成熟的做法是搭建一个统一的数据安全网关让所有 LLM 请求都经过这个网关网关负责统一接入脱敏规则、实体识别模型和令牌映射表网关对入站 Prompt 做敏感信息扫描对出站结果做还原网关记录脱敏覆盖率、敏感信息命中次数和风险告警网关对接审计平台提供完整的调用链追踪。这个思路和 API 网关、流量治理可以说是同构的。从工程落地角度一开始不需要做到平台化可以先从一个公共 Python 包开始供各业务线复用等规则和调用量积累到一定程度再演进为独立的网关服务。重点不是一步到位而是先让“脱敏”成为所有 LLM 调用的默认动作。6. 常见问题与排查思路6.1 常见问题排查表问题现象常见原因解决思路模型输出仍出现明文手机号正则规则漏配或占位符被模型改写检查正则覆盖范围在 Prompt 中增加“保留标记”约束脱敏后语义明显变差占位符让模型无法理解实体关系在 Prompt 中解释占位符含义保留部分非敏感上下文日志里出现 Prompt 明文日志组件在脱敏逻辑之前执行在入口层先做脱敏再打日志挂载日志 Filter 兜底模型没有保留占位符占位符太像普通文本模型自动改写使用MASKED_EMAIL_0这类高辨识度占位符外部 API 可能留存数据供应商数据条款不透明优先私有化部署签订数据处理协议控制敏感数据出域脱敏后同一个值被替换成不同占位符映射表没有在跨请求间保持使用令牌化服务或持久层做统一映射6.2 排查步骤与预防在集成脱敏组件后如果怀疑还有敏感信息外泄建议按下面的顺序排查。第一步确认业务入口是否真的调用了sanitize()方法而不是只在某个工具函数里实现第二步检查日志输出查看是否有脱敏前的原始请求被打印第三步在 API 网关或代理层抓包确认出域请求体里没有明文敏感字段第四步检查外部模型返回结果里是否有占位符被还原为明文如果有需要检查还原逻辑是否误用了其他映射表第五步审查数据库和数仓看是否有历史任务直接把未脱敏 Prompt 写入存储。预防措施方面比较有效的是在 CI 流水线中增加一个简单的“敏感字段扫描”步骤用同一套正则规则扫描测试代码里的静态字符串一旦发现疑似手机号、身份证号、密钥就阻止合并。这样可以在代码层面防止新的明文 Prompt 被写入业务。7. 最佳实践与工程建议7.1 最小必要原则在设计 LLM 调用时先问自己一个问题模型真的需要知道这段信息吗如果只需要判断用户意图就不需要把完整客户信息塞进 Prompt如果只需要对文档做摘要就应该先对文档做敏感信息过滤再送给模型。最小必要原则是 Prompt Privacy 的第一性原则。很多团队为了让模型回答更“聪明”习惯把上下文堆得越全越好但每增加一个非必要的敏感字段隐私风险就增加一分。所以Prompt 组装阶段就应该做字段级裁剪而不是等整段文本都拼好后再做正则脱敏。7.2 传输与存储安全Prompt 请求在传输过程中必须使用 HTTPS/mTLS避免明文 HTTP 出域。在存储环节如果业务确实需要保留 Prompt 用于风控或审计也要做加密存储并设置访问白名单。涉及敏感数据落库时应使用字段级加密而不是只对整库做静态加密。需要强调的是即便数据库启用了透明数据加密在查询结果返回给应用的时候仍然是通过解密后的明文传输的所以数据库账号权限、网络隔离和 SQL 审核仍然是必要的安全手段。7.3 日志治理日志治理是 Prompt Privacy 中最容易被忽略、也最容易被发现的短板。建议所有生产环境日志默认不记录 Prompt 请求体只记录请求 ID、模型名称、响应耗时、Token 消耗等元数据。只有通过 Trace ID 关联的独立审计日志中才允许保存脱敏后的 Prompt 摘要。审计日志必须有独立权限访问行为需要留痕这样既能满足问题排查需求又不会因为日志索引权限过大导致大范围泄露。7.4 权限与审计Prompt 数据的访问权限应该遵循“最小授权”原则。只有负责模型调用的核心开发人员和运维人员可以看到脱敏前的 Prompt安全审计人员可以查看日志但不能直接导出数据库表数据分析师只应该访问脱敏后的统计结果。同时每一次对 Prompt 数据的访问都应有审计记录包括访问者、时间、访问内容摘要和访问原因。在云环境下访问权限通常由 IAM 或云访问控制管理在本地则要依托内部账号和堡垒机体系。7.5 数据生命周期管理Prompt 数据也有生命周期应该明确保存周期和销毁策略。如果外部模型服务商提供零数据保留选项业务上应该优先开启如果模型服务商保留数据但承诺一定周期后删除需要确认删除机制是逻辑删除还是物理删除企业内部审计日志里的 Prompt 数据也应该设置基于时间或业务需求的自动清理策略。特别注意带敏感数据的备份文件也要在备份机制中单独标记避免一份备份泄露导致所有历史 Prompt 全部暴露。8. 收尾从一次小改造开始Prompt Privacy 不是一个需要一次性建设到位的平台级工程它更像是一连串可以逐步落地的小改造。如果你所在的团队刚刚开始接入 LLM我建议先从三件事下手第一把本文的PromptSanitizer接入现有调用入口要求所有发往模型服务的请求都先经过脱敏第二在日志 Filter 中增加统一脱敏让日志系统不再保存明文 Prompt第三梳理你正在使用的 LLM 服务商的数据处理条款明确它是否有数据留存、人工标注、数据训练等行为。这三步不需要购买任何额外服务也不需要重构系统跑两周之后再根据脱敏覆盖率和误杀率继续完善规则库。等到调用量变大、业务线变多再考虑搭建统一的数据安全网关。记住Prompt 隐私的核心不是追求百分之百的完美而是让敏感数据在每一环都被有意识地控制住。
返回列表