11.5 内容安全
前几节我们讨论了如何防止攻击者"进来"(Prompt 注入)、如何防止模型"叛变"(越狱)、如何保护"数据"(数据安全)、如何守住"操作"(工具调用安全)。本节关注最后一个维度——当 LLM 的输出即将展示给用户时,如何确保内容本身是安全的。
打个比方:前面的安全措施是在"后厨"防投毒、防偷工减料、防操作失误,而内容安全是在"上菜前"的最后一道质检——检查这道菜有没有变质、有没有异物、有没有放错调料。
11.5.1 内容安全威胁分类
AI 内容安全的威胁不止"有害内容"一种。一个完整的威胁分类包括四大类:
AI 内容安全威胁
├── 有害内容生成
│ ├── 暴力/仇恨言论 ← 模型可能生成煽动暴力的内容
│ ├── 色情内容 ← 不当内容可能对未成年人造成伤害
│ ├── 违法信息 ← 诈骗方法、犯罪指导等
│ └── 自残/自杀诱导 ← 对脆弱用户极具危险性
├── 幻觉 (Hallucination)
│ ├── 事实错误 ← "爱因斯坦发明了电话"
│ ├── 虚构引用 ← 编造不存在的论文、URL
│ └── 逻辑矛盾 ← 前后回答不一致
├── 偏见与歧视
│ ├── 性别偏见
│ ├── 种族偏见
│ └── 地域偏见
└── 隐私泄露
├── PII 泄露 ← 模型输出中包含真实个人信息
├── 训练数据记忆 ← 模型复述了训练数据中的内容
└── 上下文泄露 ← 把其他用户的对话内容泄露出来11.5.2 有害内容检测
有害内容检测有三种主要方法,就像安检的三种手段——X 光机(API 检测)、警犬(LLM 审查)、人工检查(关键词过滤),各有优劣:
from openai import OpenAI
import re
import json
client = OpenAI()
# 方法 1:使用 Moderation API——专业的"有害内容检测器"
def check_content_moderation(text: str) -> dict:
"""使用 OpenAI Moderation API 检测有害内容"""
# 调用 Moderation API,它会返回各维度的有害内容评分
response = client.moderations.create(input=text)
result = response.results[0]
return {
"flagged": result.flagged, # 是否被标记为有害
"categories": { # 各维度的评分 (0.0-1.0)
"sexual": result.category_scores.sexual, # 色情
"hate": result.category_scores.hate, # 仇恨
"violence": result.category_scores.violence, # 暴力
"self_harm": result.category_scores.self_harm, # 自残
"harassment": result.category_scores.harassment # 骚扰
}
}
# 方法 2:使用 LLM 作为内容审核器——"用 AI 管 AI"
def llm_content_guard(text: str) -> dict:
"""使用 LLM 进行内容安全审核"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": """你是内容安全审核员。按以下规则判断:
1. 如果内容包含暴力、色情、仇恨、违法信息,标记为 unsafe
2. 如果内容安全,标记为 safe
3. 只返回 JSON: {"verdict": "safe|unsafe", "reason": "原因"}"""
}, {
"role": "user",
"content": text # 待审核的内容
}],
response_format={"type": "json_object"} # 强制 JSON 输出
)
return json.loads(response.choices[0].message.content)
# 方法 3:关键词 + 正则过滤——最基础的"安检门"
def keyword_filter(text: str, blocked_words: set) -> bool:
"""基于关键词的内容过滤"""
text_lower = text.lower() # 统一转小写匹配
for word in blocked_words:
if word in text_lower:
return False # 命中关键词,拦截
return True # 通过11.5.3 幻觉检测与缓解
幻觉(Hallucination)是 LLM 的"阿喀琉斯之踵"——模型会自信满满地编造不存在的事实。就像一个"不懂装懂"的同事,说起来头头是道,但仔细一查全是编的。
幻觉的三种类型:
- 事实幻觉:编造不存在的事实(如"爱因斯坦发明了电话")
- 引用幻觉:虚构论文、书籍、URL——这在学术场景中尤其危险
- 逻辑幻觉:前后矛盾,同一问题给出不同答案
def detect_hallucination_self_check(claim: str, source: str = None) -> dict:
"""让 LLM 自我检查是否存在幻觉——"让说错话的人自己复查" """
prompt = f"""检查以下陈述是否准确:
陈述:{claim}
{f'参考来源:{source}' if source else ''}
请判断:
1. 陈述是否基于事实?
2. 是否存在虚构的信息?
3. 返回 JSON: {{"has_hallucination": true/false, "confidence": 0-1, "explanation": "说明"}}"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"} # 强制结构化输出
)
return json.loads(response.choices[0].message.content)
def check_factual_consistency(generated: str, source: str) -> float:
"""
基于 NLI(自然语言推理)的幻觉检测
检查生成内容与源文本的一致性——"对照原文查错"
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": "判断生成文本是否与源文本一致。返回 0-1 的分数,1 表示完全一致。只返回数字。"
}, {
"role": "user",
"content": f"源文本:{source}\n\n生成文本:{generated}"
}]
)
return float(response.choices[0].message.content) # 一致性分数11.5.4 RAG 幻觉检测器
在 RAG(检索增强生成)场景中,幻觉检测尤为关键——因为 RAG 的核心承诺是"基于检索到的事实回答"。如果 RAG 系统的输出与检索文档不一致,就是严重的幻觉。以下是一个 RAG 专用幻觉检测器:
def rag_hallucination_detector(query: str, answer: str, retrieved_docs: list) -> dict:
"""
检测 RAG 回答中的幻觉
流程:提取声明 -> 逐条验证 -> 计算幻觉率
"""
# 第一步:从回答中提取所有事实性声明
extraction_prompt = f"""从以下回答中提取所有事实性声明:
回答:{answer}
只返回 JSON 数组,每个元素是一条声明:["声明1", "声明2"]"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": extraction_prompt}],
response_format={"type": "json_object"}
)
claims = json.loads(response.choices[0].message.content).get("claims", [])
# 第二步:逐条验证每个声明是否被检索文档支持
docs_text = "\n".join(retrieved_docs) # 合并所有检索文档
results = []
for claim in claims:
verify_prompt = f"""基于以下文档验证声明:
文档:{docs_text}
声明:{claim}
是否被文档支持?返回 JSON: {{"supported": true/false, "evidence": "证据"}}"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": verify_prompt}],
response_format={"type": "json_object"}
)
verification = json.loads(response.choices[0].message.content)
results.append({"claim": claim, **verification})
# 第三步:统计幻觉率
supported = [r for r in results if r["supported"]] # 被支持的声明
unsupported = [r for r in results if not r["supported"]] # 未被支持的声明(幻觉)
return {
"total_claims": len(claims),
"supported": len(supported),
"unsupported": len(unsupported),
"hallucination_rate": len(unsupported) / max(len(claims), 1), # 幻觉率
"details": results
}11.5.5 输出安全审核流水线
将有害内容检测、幻觉检测、PII 检测整合为一个完整的审核流水线。就像工厂的质检流水线——产品依次通过多个检查站,任何一个站发现问题就拦截:
class OutputSafetyPipeline:
"""输出内容安全审核流水线——多检查站串联"""
def __init__(self):
# 审核检查列表:按顺序执行
self.checks = [
self.check_moderation, # 有害内容检测
self.check_hallucination, # 幻觉检测
self.check_pii_leak, # PII 泄露检测
self.check_length # 长度限制
]
def check_moderation(self, text: str) -> dict:
"""检查站 1:有害内容检测"""
result = check_content_moderation(text) # 调用 Moderation API
return {"check": "moderation", "passed": not result["flagged"], "detail": result}
def check_hallucination(self, text: str) -> dict:
"""检查站 2:幻觉检测——检查虚构的 URL"""
url_pattern = r'https?://[^\s]+' # URL 正则
urls = re.findall(url_pattern, text)
return {"check": "hallucination_urls", "passed": len(urls) < 5, "urls_found": urls}
def check_pii_leak(self, text: str) -> dict:
"""检查站 3:PII 泄露检测"""
pii_patterns = {
"phone": r'\b1[3-9]\d{9}\b', # 手机号
"email": r'\b[\w.-]+@[\w.-]+\.\w+\b', # 邮箱
"id_card": r'\b\d{17}[\dXx]\b', # 身份证号
"credit_card": r'\b\d{16}\b' # 银行卡号
}
found = {}
for name, pattern in pii_patterns.items():
matches = re.findall(pattern, text) # 搜索 PII
if matches:
found[name] = matches
return {"check": "pii", "passed": len(found) == 0, "found": found}
def check_length(self, text: str) -> dict:
"""检查站 4:长度限制"""
return {"check": "length", "passed": len(text) < 10000, "length": len(text)}
def audit(self, text: str) -> dict:
"""执行完整审核——所有检查站串联"""
results = []
for check_fn in self.checks:
results.append(check_fn(text)) # 逐站检查
# 所有检查站都通过才算通过
passed = all(r["passed"] for r in results)
return {
"passed": passed,
"checks": results,
"action": "allow" if passed else "block_or_flag" # 通过放行,否则拦截或标记
}
# 使用示例
pipeline = OutputSafetyPipeline()
result = pipeline.audit("用户手机号 13812345678,请帮我...")
print(json.dumps(result, indent=2, ensure_ascii=False))
# 输出中 check_pii_leak 会显示 found: {"phone": ["13812345678"]},passed: false11.5.6 常见误区
误区一:"模型越大越不会幻觉"
大模型的幻觉问题确实比小模型轻,但并没有根本解决。GPT-4 仍然会编造论文引用和 URL。幻觉是 LLM 生成机制的本质特征——概率生成决定了它无法保证事实正确性。
误区二:"Moderation API 拦截了就够了"
Moderation API 主要检测暴力和色情等有害内容,但无法检测幻觉、偏见和 PII 泄露。内容安全需要多种检测方法的组合。
误区三:"关键词过滤太简单,不值得做"
关键词过滤虽然简单,但在处理已知风险词时非常高效。它作为第一道快速过滤层,可以大幅减少后续复杂检测的负载。多层防护不排斥简单方法。
误区四:"RAG 不会幻觉,因为基于检索"
RAG 减少了幻觉但不能消除。模型可能误解检索到的内容,或者在检索结果不足时"脑补"信息。必须对 RAG 输出进行独立的幻觉检测。
11.5.7 本节小结
内容安全是 LLM 应用面向用户的最后一道防线。我们从四大威胁类型出发——有害内容、幻觉、偏见、隐私泄露——介绍了三种有害内容检测方法(Moderation API、LLM 审查、关键词过滤)、两种幻觉检测策略(自我检查、NLI 一致性),以及一个完整的输出审核流水线。
记住一个类比:内容安全审核就像机场的安检流水线——行李先过 X 光机(Moderation API),再过爆炸物探测(幻觉检测),最后人工抽检(PII 检测)。任何一个环节发现问题,行李就不能上飞机。
下一节将讨论合规与治理——当技术层面的安全措施到位后,制度层面的法规、审计和治理框架同样不可或缺。
延伸阅读
- OpenAI Moderation API — https://platform.openai.com/docs/guides/moderation
- Anthropic Safety & Security — https://www.anthropic.com/research#safety
- OWASP Top 10 for LLM Applications — https://owasp.org/www-project-top-10-for-large-language-model-applications/