导出聊天或复用提示词前,扫描是否缺少「虚构/非建议」免责声明,以及诊断、保证收益等红线话术。
先看清成品
- safe → ok;risky(处方/保证收益/冒充本人)→ 失败。
- 3 项 pytest 通过。
合规提醒:Character.AI 角色均为虚构内容,不代表真实人物,不能当作医疗/法律/金融等专业建议。平台有年龄限制与未成年人安全措施,请遵守官方规定。长时间聊天注意休息。官方 Help Center 表明目前没有面向开发者的公开 API;勿使用非官方逆向客户端(可能违反条款且不稳定)。本文不编造价格与会员权益。
运行说明:无 Character.AI API(官方亦无公开开发者 API)。三篇均为本地助手:角色定义校验、会话时长账本、导出/提示词虚构免责扫描。未登录 character.ai。2026-10-23(Asia/Shanghai)pytest 通过。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
fiction_guard.py |
免责扫描 |
| 样例 txt | safe/risky |
test_106c.py |
测试 |
需要准备哪些环境?
| 项目 | 说明 |
|---|---|
| Python | 3.10+ |
关键事实
| 事实 | 来源 |
|---|---|
| 角色输出不能当专业建议 | 产品定位 |
| 启发式无法覆盖所有有害表述 | 重要 |
| 对外分享导出内容时自行加免责声明 | 实践 |
文件结构
106-character-ai-C-src/
├── fiction_guard.py
├── sample_safe.txt
├── sample_risky.txt
└── test_106c.py
第 1 步:扫描脚本
#!/usr/bin/env python3
"""Scan chat export / prompt text for missing fiction disclaimers and advice red flags."""
from __future__ import annotations
import argparse
import json
import re
from pathlib import Path
ADVICE = re.compile(r"(?i)(诊断|处方|保证治愈|一定能赢|内幕消息|保证收益|legal advice|medical advice|guaranteed returns)")
REAL_PERSON = re.compile(r"(?i)(我就是本人|这是真人|official statement from)")
DISCLAIMER = re.compile(r"(?i)(虚构|AI 角色|artificial|fictional|not (a )?real (person|advice)|不构成.*建议)")
def scan(text: str) -> dict:
hits = []
for name, pat in (("advice", ADVICE), ("claims_real", REAL_PERSON)):
for m in pat.finditer(text):
hits.append({"rule": name, "snippet": text[m.start(): m.start() + 40]})
has_disc = bool(DISCLAIMER.search(text))
ok = not hits or has_disc
# If advice/real hits and no disclaimer → fail; advice hits always fail soft
hard = [h for h in hits if h["rule"] == "advice"]
return {
"ok": len(hard) == 0 and (not any(h["rule"] == "claims_real" for h in hits) or has_disc),
"has_disclaimer": has_disc,
"hits": hits,
"note": "角色输出是虚构内容,不能当专业建议;导出前自行加免责声明。",
}
def main(argv=None) -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("file")
args = ap.parse_args(argv)
result = scan(Path(args.file).read_text(encoding="utf-8"))
print(json.dumps(result, ensure_ascii=False, indent=2))
return 0 if result["ok"] else 1
if __name__ == "__main__":
raise SystemExit(main())
第 2 步:测试
from pathlib import Path
import subprocess, sys
from fiction_guard import scan
HERE = Path(__file__).resolve().parent
def test_safe():
assert scan((HERE/"sample_safe.txt").read_text())["ok"]
def test_risky():
assert not scan((HERE/"sample_risky.txt").read_text())["ok"]
def test_cli():
r = subprocess.run([sys.executable, str(HERE/"fiction_guard.py"), str(HERE/"sample_safe.txt")], capture_output=True, text=True)
assert r.returncode == 0
第 3 步:运行
$ fiction_guard
{
"ok": true,
"has_disclaimer": true,
"hits": [],
"note": "角色输出是虚构内容,不能当专业建议;导出前自行加免责声明。"
}
{
"ok": false,
"has_disclaimer": false,
"hits": [
{
"rule": "advice",
"snippet": "处方你一定能治愈,保证收益。\n"
},
{
"rule": "advice",
"snippet": "保证收益。\n"
},
{
"rule": "claims_real",
"snippet": "我就是本人官方声明。按这个处方你一定能治愈,保证收益。\n"
}
],
"note": "角色输出是虚构内容,不能当专业建议;导出前自行加免责声明。"
}
$ pytest -q
... [100%]
3 passed in 0.03s
怎么检查结果?
- safe 退出码 0。
- risky hits 含 advice。
调试示例
角色说了「我建议你停药」。 即使有免责声明,也建议删改后再分享;本脚本对 advice 命中一律判失败。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 误报 | 改正则 | 保留人工复审 |
| 多语言 | 已含部分中英 | 可扩展 |
| 群聊导出 | 同样扫描 | 注意他人隐私 |
模板规则
- 分享前加虚构免责。
- 不传播「专业建议」幻觉。
- 尊重他人隐私。
项目资源
| 用途 | 地址 |
|---|---|
| About(官方) | https://character.ai/about |
| Blog(官方) | https://blog.character.ai/ |
娱乐归娱乐,免责声明不是装饰品。