kinetic-100/chatbot-guardrails

GitHub: kinetic-100/chatbot-guardrails

面向 LLM 聊天机器人的零依赖纯 Python 内容安全护栏库,提供双向的 PII 隐去、攻击性语言过滤和 prompt 注入检测。

Stars: 0 | Forks: 0

# chatbot-guardrails 用于 LLM 聊天机器人的内容安全护栏,采用纯 Python 编写,**零依赖**。 它可以隐去 PII 和攻击性语言,中和 prompt 注入企图,验证输入,对调用者进行速率限制,并确保 API 密钥不会出现在错误文本中。自带终端聊天客户端,适用于 [Qwen Flash](https://www.alibabacloud.com/help/en/model-studio/) 或任何 OpenAI 兼容的 endpoint。 ``` from guardrails import Guardrails g = Guardrails() g.sanitize_outbound("call me on +44 20 7946 0958 or mail bob@example.com").text # '拨打 [REDACTED_PHONE] 或发送邮件至 [REDACTED_EMAIL]' g.sanitize_inbound("That was a stupid idea").text # '那真是一个 [redacted] 的主意' ``` ## 安装说明 要求 Python 3.10+。无需安装——只需将 `guardrails.py` 复制到您的项目中, 或克隆本 repo。 ``` git clone https://github.com/USERNAME/chatbot-guardrails.git cd chatbot-guardrails python3 -m unittest -v # 47 tests python3 guardrails.py # self-test + demo ``` ## 终端客户端 ``` export DASHSCOPE_API_KEY="your-key" python3 chat.py ``` 密钥仅从环境变量中读取——绝不写入磁盘、记录日志或回显。 如果您的主账户位于中国大陆地区,请使用 `dashscope.aliyuncs.com`(不带 `-intl`)。 | Flag | 默认值 | 用途 | | --- | --- | --- | | `--model` | `qwen-flash` | 模型名称 | | `--base-url` | DashScope 国际版兼容模式 | 任何 OpenAI 兼容的 endpoint | | `--system` | — | 额外的 system prompt,附加在安全导言之后 | | `--rate-limit` / `--rate-window` | `20` / `300` | 每个时间窗口(秒)的允许消息数 | | `--extra-words` | — | 逗号分隔的额外违禁词 | | `--extra-locations` | — | 逗号分隔的额外需要隐去的地名 | | `--selftest` | — | 验证过滤器,然后退出 | | `--no-guardrails` | off | 禁用所有过滤 | 会话内命令:`/quit`、`/clear`、`/notes`、`/selftest`。 ## 检查内容 **PII** — 电子邮件、电话(国际格式)、SSN、信用卡(Luhn 验证)、 IBAN、加密货币钱包、IP 地址、街道地址、出生日期、护照、驾驶 执照、银行账户、呈 API 密钥形态的字符串。 **地理位置** — 包含美国州名、国家和主要城市的地名录,以及上下文相关的 自我披露措辞(`"I live in ..."`、`"my house is in ..."`),会隐去 随后出现的任何地名,即使它不在列表中。可通过 `Config(extra_locations=...)` 进行扩展。 **攻击性语言** — 粗俗的脏话、侮辱性称呼和一般性辱骂,支持匹配 leetspeak(`$tupid`)、空格(`f u c k`)、字母重复(`fuuuck`)、词形屈折变化 (`stupidity`、`dumbest`)、Unicode 同形异义字(带有西里尔字母 `ѕ` 的 `ѕtupid`)、全角 形式(`stupid`)以及零宽字符分割。 **敌意语言** — 明确的威胁会被隐去,而不仅仅是标记。 **Prompt 注入** — 常见的指令覆盖措辞会在文本 到达模型之前被剔除。 **基础清理** — 长度限制、控制字符剔除、基于调用者的滑动窗口 速率限制,以及针对提供商返回的错误正文的凭证清洗。 ## 配置 ``` from guardrails import Config, Guardrails g = Guardrails(Config( redact_pii=True, redact_profanity=True, redact_locations=False, # keep city names for context-aware replies detect_injection=True, max_length=6000, rate_limit_max=20, rate_limit_window_s=300, extra_words=("bananapants",), extra_locations=("Cambridge",), )) ``` `sanitize_outbound` 和 `sanitize_inbound` 均返回一个 `Result`,其中包含 `.text` 和 `.notes` — 这是一份记录了修改内容的列表,可以安全地展示给用户。Notes 永远不会回显 违规内容。 ## 隐去操作不泄露任何信息 违禁词会被替换为固定的 `[redacted]` 标记,该标记**不**编码 任何关于它所替换内容的任何信息。 这是刻意为之的,也是这个库存在的理由。早期版本会将词汇掩码处理为“首字母 + 星号 + 尾字母”,因此 `Stupid.` 会变成 `S****d.` — 保留了首字母、尾字母、长度和大小写。 这对任何人类读者来说,读起来就像原词一样;当这样的文本被发送给 模型时,模型能将其完美解码回原始词汇。它甚至还能通过简单的 `"stupid" not in output` 测试,这也是它能通过代码审查的原因。 `test_guardrails.py` 断言排除了*身份识别信号*,而不仅仅是 子字符串,并且其中一个测试将标记 monkeypatch 回了之前有缺陷的形式,以证明 自检现在能够捕获到这个问题。 ## 限制 — 请务必阅读 - **模式匹配是后盾,而非控制手段。** 它增加了泄露 PII 或发出侮辱性言论的成本。一个执着的输入者会找到它漏掉的拼写方式。 - **system prompt 才是真正阻止内容生成的手段。** `SAFETY_PREAMBLE` 会被导出,并由 `chat.py` 在每次请求时发送;隐去只是在事后重写 文本。请两者并用。 - **设计上偏向激进。** 电话/ID 模式偶尔会捕获到一串并非 电话号码的长数字字符串。对于隐去过滤器来说,这是 正确的权衡;如果它不适合您,可以放宽限制。 - **地理位置隐去本质上是无法做到完美的。** 没有任何 regex 能识别任意的 地名。地名词典涵盖了常见的地名;针对您 特别关注的地方,请使用 `extra_locations`。 - **速率限制是进程局部的。** 在运行多个 worker 的情况下,请改用 Redis 或您的 框架自带的限制器。 - **这不是一个内容审查服务。** 对于任何大规模面向用户的应用,请在此 之前部署一个真正的审查 API。 ## 许可证 MIT — 详情请参阅 [LICENSE](LICENSE)。
标签:AI安全, Chat Copilot, DLL 劫持, Petitpotam, Python, 大语言模型, 无后门, 网络安全, 逆向工具, 隐私保护