IntentGuard是一个专为LLM(大语言模型)安全设计的垂直领域意图分类系统,旨在解决特定行业(如金融、医疗、法律)中LLM可能回答超出其专业范围的问题。这个开源项目基于DeBERTa-v3-xsmall模型构建,经过ONNX INT8量化后,在普通硬件上运行时延低于20ms(p99)。
核心功能是在用户查询到达下游LLM之前,将其分类为:
传统的二元分类器("在范围内"或"超出范围")在处理边界查询时表现不佳。考虑以下发送给金融服务聊天机器人的查询示例:
| 查询 | 二元分类结果 | 理想决策 |
|---|---|---|
| "当前抵押贷款利率是多少?" | 在范围内 ✓ | ALLOW ✓ |
| "巧克力蛋糕的最佳配方" | 超出范围 ✓ | DENY ✓ |
| "HIPAA如何影响医疗账单纠纷?" | ??? | 取决于上下文 |
| "2025年HSA缴款限额是多少?" | ??? | ALLOW(财务规划) |
| 在HSA讨论后出现的"药物相互作用的症状" | ??? | DENY(医疗,非财务) |
IntentGuard引入ABSTAIN类别来处理这些边界情况:
这种设计自然地映射到用户体验模式中,系统不会简单地"封闭失败"(阻止所有不确定的查询)或"开放失败"(通过所有不确定的查询),而是会询问更多信息。
IntentGuard使用微软的DeBERTa-v3-xsmall(2200万参数)作为基础模型,这是一个经过深思熟虑的工程选择:
| 模型 | 参数数量 | ONNX INT8大小 | p99延迟(CPU) | 准确率 |
|---|---|---|---|---|
| DeBERTa-v3-xsmall | 22M | ~10MB | <20ms | 95-98% |
| DeBERTa-v3-base | 86M | ~45MB | >100ms | 96-99% |
| Prompted LLM (GPT-4) | ~1.7T | N/A | 500-2000ms | 98-99% |
大多数护栏部署以sidecar配置运行——分类器在LLM看到每个请求之前运行。在高吞吐量下,增加100ms+的延迟是不可接受的,而增加500ms+的LLM分类器延迟则违背了初衷。
模型使用DeBERTa的句子对输入格式:
示例上下文字符串:
code复制VERTICAL=finance; CONTEXT_VERSION=ctv1;
CORE_TOPICS=[banking,lending,credit,payments,investing,insurance,tax,personal finance,retirement,mortgages,financial planning,budgeting];
CONDITIONAL_ALLOW=[healthcare: only when related to financial planning, insurance, HSA/FSA, medical debt; legal: only when related to financial regulation, contracts, or compliance];
HARD_EXCLUSIONS=[sports,entertainment,cooking,gaming,celebrity gossip,fashion,travel_leisure]
这种设计意味着模型不会将其范围"烘焙"到权重中——它在推理时读取垂直的范围定义作为条件上下文。
微调使用HuggingFace的Trainer,并精心调整超参数:
yaml复制# training/train_config.yaml
base_model: microsoft/deberta-v3-xsmall
learning_rate: 2.0e-05
num_train_epochs: 3
per_device_train_batch_size: 8
max_seq_length: 128
warmup_ratio: 0.1
label_smoothing_factor: 0.05
weight_decay: 0.01
freeze_embeddings: true # 防止在小数据集上过拟合
class_weights: inverse # 对类别不平衡进行逆频率加权
两个值得注意的细节:
标准分类器采用argmax——具有最高logit的类别获胜。这忽略了决策的置信度有多高。如果模型产生allow=0.52,deny=0.48,argmax是ALLOW,但边界只有0.04——这更像是一个抛硬币的决定,而不是一个自信的预测。
IntentGuard使用基于边界的阈值。决策需要两个条件:
决策逻辑代码示例:
python复制def _apply_thresholds(self, probs, tricks_detected=False):
"""ALLOW if: p_allow >= tau_allow AND (p_allow - max(p_deny, p_abstain)) >= margin_allow
DENY if: p_deny >= tau_deny AND (p_deny - max(p_allow, p_abstain)) >= margin_deny
Otherwise: ABSTAIN"""
t = self.policy.thresholds
# 编码技巧检测 → 总是弃权
if tricks_detected:
return Decision.ABSTAIN, p_abstain
# 首先检查ALLOW(偏向允许合法查询)
if p_allow >= t.tau_allow and (p_allow - max(p_deny, p_abstain)) >= t.margin_allow:
return Decision.ALLOW, p_allow
# 检查DENY
if p_deny >= t.tau_deny and (p_deny - max(p_allow, p_abstain)) >= t.margin_deny:
return Decision.DENY, p_deny
# 默认ABSTAIN
return Decision.ABSTAIN, max(p_abstain, 1.0 - p_allow - p_deny)
阈值默认是非对称的:
json复制{
"decision": {
"tau_allow": 0.80,
"tau_deny": 0.90,
"margin_allow": 0.10,
"margin_deny": 0.10
}
}
DENY阈值(0.90)高于ALLOW阈值(0.80),这是有意为之——阻止用户比让他们通过更难。错误阻止会挫败合法用户;错误允许可以被下游的其他安全层捕获。
在文本到达模型之前,它会通过一个规范化流程,旨在减少对抗性攻击面:
python复制def normalize(text: str, max_chars: int = 2000) -> str:
# 1. Unicode NFKC规范化
text = unicodedata.normalize("NFKC", text)
# 2. 去除零宽度和不可见字符
text = _ZERO_WIDTH.sub("", text)
# 3. 压缩空白
text = _WHITESPACE.sub(" ", text).strip()
# 4. 截断
if len(text) > max_chars:
text = text[:max_chars]
return text
除了规范化外,系统还检测可能表明基于编码的规避的模式:
python复制def has_encoding_tricks(text: str) -> bool:
# Base64块:20+连续base64字母字符
if _BASE64_BLOB.search(text):
return True
# 短文本中的高非ASCII比率(混淆,非CJK散文)
non_ascii = sum(1 for c in text if ord(c) > 127)
ratio = non_ascii / len(text) if text else 0
if ratio > 0.6 and len(text) < 200:
return True
return False
当检测到编码技巧时,分类流程会立即路由到ABSTAIN,而不管模型输出如何。
现代神经网络(包括DeBERTa)倾向于产生过度自信的预测。一个模型可能在一个它实际上只有70%可能正确分类的查询上输出allow=0.95。
温度缩放是一种事后校准技术,它拟合单个参数T来调整logit分布:
code复制scaled_logits = logits / T
probabilities = softmax(scaled_logits)
如果T > 1,分布会变软(减少过度自信);如果T < 1,分布会变尖锐。最佳T是通过在保留的校准集上使用L-BFGS优化最小化负对数似然来找到的。
我们使用预期校准误差(ECE)来衡量校准质量:
code复制ECE = Σ (|B_b|/N) * |acc(B_b) - conf(B_b)|
发货门要求ECE < 0.03——意味着预测置信度和实际准确度之间的平均差距小于3个百分点。
IntentGuard中的每个部署决策都由策略JSON文件驱动,而不是硬编码逻辑。完整策略定义了范围、阈值、响应、隐私设置和下游工具权限:
json复制{
"vertical": "finance",
"version": "1.0",
"display_name": "Financial Services",
"scope": {
"core_topics": ["banking", "lending", "credit", "payments", "investing", "insurance", "tax", "personal finance", "retirement", "mortgages", "financial planning", "budgeting"],
"conditional_allow": [{
"topic": "healthcare",
"condition": "only when related to HSA/FSA, medical debt, insurance",
"examples_allow": ["What are HSA contribution limits?"],
"examples_deny": ["Explain my MRI results"],
"disambiguation_questions": ["Is your question about healthcare costs, insurance, or financial planning?"]
}],
"hard_exclusions": ["sports", "entertainment", "cooking", "gaming", "celebrity gossip", "fashion", "travel_leisure"]
},
"decision": {
"tau_allow": 0.80,
"tau_deny": 0.90,
"margin_allow": 0.10,
"margin_deny": 0.10
},
"privacy": {
"log_query_text_default": false,
"pii_redaction_default": true,
"log_sampling_rate": 0.1
}
}
conditional_allow部分处理那些会破坏二元分类器的细微情况。发送给金融聊天机器人的医疗问题在与HSA/FSA账户或医疗债务相关时应该被允许,但在请求临床建议时应该被拒绝。
每个决策都带有一个策略包——告诉下游系统应用哪些工具和护栏的元数据:
json复制{
"policy_packs": {
"allow": {
"allowed_tools": ["calculator", "market_data", "account_lookup"],
"guardrails": ["no_trade_execution", "no_pii_disclosure", "disclaimer_required"],
"metadata": {"risk_level": "standard"}
},
"deny": {
"allowed_tools": [],
"guardrails": ["block_response", "log_attempt"],
"metadata": {"risk_level": "blocked"}
},
"abstain": {
"allowed_tools": ["document_search"],
"guardrails": ["require_clarification", "no_pii_disclosure"],
"metadata": {"risk_level": "elevated"}
}
}
}
对于部署多个领域特定聊天机器人的组织,IntentGuard支持两阶段路由架构:
完整的多垂直设置在一个JSON配置中定义:
json复制{
"router_model": "models/router/model.onnx",
"router_tokenizer": "models/router/tokenizer",
"verticals": {
"finance": {
"model": "dist/finance/model.onnx",
"tokenizer": "dist/finance/tokenizer",
"policy": "policies/finance.json",
"calibration": "dist/finance/calibration_params.json"
},
"healthcare": {
"...": "..."
},
"legal": {
"...": "..."
}
}
}
IntentGuard定义了明确的、自动化的发货门——在模型可以部署之前必须通过的定量标准:
| 垂直领域 | 准确率 | LBR | OPR | AOC | 发货? |
|---|---|---|---|---|---|
| 金融 | 98.3% | 0.37% | 0.00% | 4.2% | SHIP |
| 医疗 | 97.7% | 0.00% | 0.00% | 6.1% | SHIP |
| 法律 | 95.3% | 0.41% | 0.50% | 8.3% | SHIP |
IntentGuard支持三种部署模式:
用户应用 → POST /v1/classify → IntentGuard → 决策
用户应用 → POST /v1/chat/completions → IntentGuard → LLM(如果ALLOW)→ 拒绝(如果DENY/ABSTAIN)
用户应用 → POST /v1/classify?mode=shadow → IntentGuard → 总是返回ALLOW → 真实决策在头信息中
| 配置 | p50 | p95 | p99 |
|---|---|---|---|
| ONNX INT8, 4核CPU | 8ms | 15ms | 19ms |
| PyTorch FP32, 4核CPU | 22ms | 38ms | 47ms |
| ONNX INT8, 2核CPU | 12ms | 21ms | 28ms |
| 格式 | 大小 |
|---|---|
| PyTorch FP32 | ~88MB |
| ONNX FP32 | ~45MB |
| ONNX INT8 (量化) | ~10MB |
| Docker镜像(完整) | <500MB |
所有三个模型都在Apache 2.0下发布:
bash复制docker run -p 8080:8080 \
-e POLICY_PATH=policies/finance.json \
-e DEBUG=true \
ghcr.io/perfecxion/intentguard:finance-latest
bash复制curl -X POST http://localhost:8080/v1/classify \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "What are current mortgage rates?"}]}'
响应示例:
json复制{
"decision": "allow",
"confidence": 0.94,
"vertical": "finance",
"message": "",
"probabilities": {
"allow": 0.94,
"deny": 0.03,
"abstain": 0.03
}
}
完整的训练管道、评估套件、对抗性测试集、门限报告和Docker配置都在GitHub存储库中。