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, 大语言模型, 无后门, 网络安全, 逆向工具, 隐私保护