很多业务系统接 AI第一步就错了。不是模型选错也不是 Prompt 写得不好而是把原始数据直接丢给模型。客户聊天记录直接丢。工单详情直接丢。合同内容直接丢。数据库日志直接丢。用户手机号、邮箱、订单号也顺手带进去。然后团队还会说一句“我们只是内部测试。”这句话最危险。因为 AI 接入业务后真正的风险往往不是它答错而是它看到了不该看的东西。Google I/O 2026 之后Google 把 AI 和 Agent 能力继续往搜索、开发工具和生产应用方向推进开发者更新里也强调从 prompt 到 production-ready application 的工具链正在变得更完整。AI 越接近生产流程输入层就越不能裸奔。尤其是企业场景。客服系统里有客户姓名、手机号、地址。CRM 里有销售记录、报价、合同状态。日志系统里可能有 token、cookie、内部接口。财务系统里有订单金额、发票、付款信息。代码仓库里有配置、密钥、内部域名。这些东西不应该原样进入模型。所以业务接 AI 前第一层应该不是 Prompt而是 Input Sanitizer也就是输入脱敏层。它要做三件事识别敏感信息。替换敏感信息。记录脱敏映射但不要暴露给模型。一个简单结构可以这样设计pythonfrom dataclasses import dataclassfrom enum import Enumfrom typing import Dict, Listimport reimport uuidclass SensitiveType(str, Enum):PHONE phoneEMAIL emailID_CARD id_cardTOKEN tokenORDER_ID order_idAPI_KEY api_keydataclassclass SensitiveMatch:sensitive_type: SensitiveTyperaw_value: strplaceholder: str然后定义一些基础规则pythonPATTERNS {SensitiveType.PHONE: r1[3-9]\d{9},SensitiveType.EMAIL: r[a-zA-Z0-9_.-][a-zA-Z0-9-]\.[a-zA-Z0-9-.],SensitiveType.API_KEY: r(sk|api|key)_[a-zA-Z0-9]{16,},SensitiveType.TOKEN: rBearer\s[a-zA-Z0-9._-],}扫描文本pythondef scan_sensitive(text: str) - List[SensitiveMatch]:matches []for sensitive_type, pattern in PATTERNS.items():for item in re.findall(pattern, text):placeholder f[{sensitive_type.value}_{uuid.uuid4().hex[:8]}]matches.append(SensitiveMatch(sensitive_typesensitive_type,raw_valueitem,placeholderplaceholder))return matches替换敏感信息pythondef sanitize_input(text: str) - Dict:matches scan_sensitive(text)sanitized textmapping {}for match in matches:sanitized sanitized.replace(match.raw_value, match.placeholder)mapping[match.placeholder] {type: match.sensitive_type.value,raw_value: match.raw_value}return {sanitized_text: sanitized,mapping: mapping}比如输入text客户手机号 13812345678邮箱 testexample.com反馈订单 ORDER_20260521001 无法支付。脱敏后应该变成text客户手机号 [phone_xxxxxxxx]邮箱 [email_xxxxxxxx]反馈订单 ORDER_20260521001 无法支付。这时模型仍然能理解问题这是一个客户反馈。涉及手机号和邮箱。问题是订单无法支付。但模型不需要看到真实手机号和邮箱。如果涉及订单号也可以继续做占位pythonORDER_PATTERN rORDER_\ddef sanitize_order_id(text: str):return re.sub(ORDER_PATTERN, [order_id], text)输入脱敏层还要配合风险等级。不是所有内容都只是替换一下就能送给模型。可以分三层低风险公开资料、普通文案、通用问题。中风险客户问题摘要、内部流程、非敏感业务数据。高风险身份证、银行卡、合同原文、密钥、生产日志、未脱敏客户数据。高风险内容应该直接拦截而不是脱敏后继续丢给模型。pythonBLOCKED_TYPES {SensitiveType.API_KEY,SensitiveType.TOKEN,SensitiveType.ID_CARD,}def should_block(matches: List[SensitiveMatch]) - bool:return any(match.sensitive_type in BLOCKED_TYPES for match in matches)完整处理pythondef prepare_ai_input(text: str) - Dict:matches scan_sensitive(text)if should_block(matches):return {ok: False,reason: blocked_sensitive_data,message: 输入包含高风险敏感信息已阻止发送给 AI。}result sanitize_input(text)return {ok: True,sanitized_text: result[sanitized_text],mapping_count: len(result[mapping])}注意mapping 不应该传给模型。mapping 只应该留在业务系统内部用于必要的结果回填。但这里还要补一句真实工程里不能只靠正则。正则适合识别手机号、邮箱、token、订单号这类格式稳定的字段但很多敏感信息没有固定格式。比如“客户住在台北信义区某某路附近”。“这位客户是我们重点续约对象”。“这段日志来自生产支付接口”。“这个合同条款还没有对外公开”。“这是内部报价不要外传”。这些内容不是简单正则能识别的。所以更成熟的做法是三层组合第一层规则识别。用于手机号、邮箱、token、API key、身份证号、订单号。第二层模型分类。让模型只判断“这段文本是否包含敏感业务信息”而不是直接处理全文任务。第三层人工标注。把误判和漏判样本沉淀成规则让脱敏层不断迭代。可以加一个分类结果pythondataclassclass RiskClassification:risk_level: strreason: strsuggested_action: str例如pythondef classify_risk_with_model(text: str) - RiskClassification:# 这里实际工程中应调用内部合规模型或受控分类服务# 返回 low / medium / highreturn RiskClassification(risk_levelmedium,reason文本包含客户投诉内容但未发现账号密码或密钥。,suggested_actionsanitize_then_process)这样系统就不是“只靠正则硬扫”而是规则、分类、人工反馈一起工作。这就是很多 Demo 和真实业务系统的区别。Demo 只关心模型能不能回答。业务系统要关心模型看到了什么。前期比较不同模型对脱敏文本的理解能力可以用 gpt57.com 跑同一批 sanitized input看哪个模型在信息缺失的情况下仍然能准确分类、总结、生成回复草稿。但上线时是否脱敏、是否拦截、是否记录审计必须由自己的系统控制。AI 接业务前先别急着调模型。先保证模型看不到不该看的东西。这比 Prompt 更基础。