plugin-sensitive-filter-xr 0.0.2 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -54
- package/dist/lib/sensitive-filter.module.d.ts.map +1 -1
- package/dist/lib/sensitive-filter.module.js +2 -1
- package/dist/lib/sensitiveFilter.d.ts +6 -3
- package/dist/lib/sensitiveFilter.d.ts.map +1 -1
- package/dist/lib/sensitiveFilter.js +782 -83
- package/dist/lib/types.d.ts +143 -29
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +37 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,63 +1,165 @@
|
|
|
1
1
|
# Xpert Plugin: Sensitive Filter Middleware
|
|
2
2
|
|
|
3
|
-
`@xpert-ai/plugin-sensitive-filter`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
type
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
3
|
+
`@xpert-ai/plugin-sensitive-filter` 提供输入/输出敏感内容过滤,支持两种互斥模式:
|
|
4
|
+
|
|
5
|
+
- `rule`:规则匹配过滤(关键词/正则)
|
|
6
|
+
- `llm`:自然语言规则过滤(固定改写策略)
|
|
7
|
+
|
|
8
|
+
## 快速上手
|
|
9
|
+
|
|
10
|
+
1. 在工作流中添加“敏感内容过滤中间件”。
|
|
11
|
+
2. 选择 `mode`:`rule` 或 `llm`(二选一)。
|
|
12
|
+
3. `rule` 模式填写规则表;`llm` 模式只需填写模型、范围、审核规则说明。
|
|
13
|
+
4. 运行工作流验证输入与输出阶段效果。
|
|
14
|
+
5. 查看日志中的审计记录。
|
|
15
|
+
|
|
16
|
+
## 执行流程
|
|
17
|
+
|
|
18
|
+
- `beforeAgent`:处理输入
|
|
19
|
+
- `wrapModelCall`:处理输出
|
|
20
|
+
- `afterAgent`:记录审计
|
|
21
|
+
|
|
22
|
+
## 顶层参数
|
|
23
|
+
|
|
24
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
25
|
+
|---|---|---|---|---|
|
|
26
|
+
| `mode` | `'rule' \| 'llm'` | 是 | `rule` | 过滤模式(互斥)。 |
|
|
27
|
+
| `rules` | `Array<Rule>` | `rule` 模式建议配置 | `[]` | 业务规则,仅 `rule` 模式生效。 |
|
|
28
|
+
| `generalPack` | `object` | 否 | 见子项 | 通用规则包(本地词库兜底),仅 `rule` 模式生效。 |
|
|
29
|
+
| `caseSensitive` | `boolean` | 否 | `false` | 是否区分大小写,仅 `rule` 模式生效。 |
|
|
30
|
+
| `normalize` | `boolean` | 否 | `true` | 是否标准化文本,仅 `rule` 模式生效。 |
|
|
31
|
+
| `llm` | `object` | `llm` 模式执行期必填 | - | LLM 过滤配置,仅 `llm` 模式生效。 |
|
|
32
|
+
|
|
33
|
+
## rule 模式参数
|
|
34
|
+
|
|
35
|
+
### rules[]
|
|
36
|
+
|
|
37
|
+
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
|
38
|
+
|---|---|---|---|---|
|
|
39
|
+
| `id` | `string` | 否 | 自动生成 `rule-{index+1}` | 规则标识。 |
|
|
40
|
+
| `pattern` | `string` | 是 | - | 匹配内容。 |
|
|
41
|
+
| `type` | `'keyword' \| 'regex'` | 是 | - | 匹配方式。 |
|
|
42
|
+
| `scope` | `'input' \| 'output' \| 'both'` | 是 | - | 生效阶段。 |
|
|
43
|
+
| `severity` | `'high' \| 'medium'` | 是 | - | 冲突优先级(`high > medium`)。 |
|
|
44
|
+
| `action` | `'block' \| 'rewrite'` | 是 | - | 命中动作。 |
|
|
45
|
+
| `replacementText` | `string` | 否 | `[已过滤]`(rewrite 时) | 自定义拦截/改写文本。 |
|
|
46
|
+
|
|
47
|
+
### generalPack
|
|
48
|
+
|
|
49
|
+
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
|
50
|
+
|---|---|---|---|---|
|
|
51
|
+
| `enabled` | `boolean` | 否 | `false` | 是否启用通用规则包。 |
|
|
52
|
+
| `profile` | `'strict' \| 'balanced'` | 否 | `balanced` | `strict` 更严格,`balanced` 更保守。 |
|
|
53
|
+
|
|
54
|
+
## llm 模式参数(简化版)
|
|
55
|
+
|
|
56
|
+
### llm
|
|
57
|
+
|
|
58
|
+
| 字段 | 类型 | 必填(执行期) | 默认值 | 说明 |
|
|
59
|
+
|---|---|---|---|---|
|
|
60
|
+
| `model` | `ICopilotModel` | 是 | - | 用于判定的过滤模型。 |
|
|
61
|
+
| `scope` | `'input' \| 'output' \| 'both'` | 是 | - | 生效范围。 |
|
|
62
|
+
| `rulePrompt` | `string` | 是 | - | 审核规则说明(自然语言,不需要 JSON)。 |
|
|
63
|
+
| `outputMethod` | `'functionCalling' \| 'jsonMode' \| 'jsonSchema'` | 否 | `jsonMode` | 结构化输出首选方式(不支持时自动降级)。 |
|
|
64
|
+
| `rewriteFallbackText` | `string` | 否 | `[已过滤]` | 命中但未返回改写文本时兜底文案。 |
|
|
65
|
+
| `timeoutMs` | `number` | 否 | 不限 | 判定超时(毫秒,上限 `120000`)。 |
|
|
66
|
+
|
|
67
|
+
### llm 模式行为说明
|
|
68
|
+
|
|
69
|
+
- 用户只需填写自然语言规则,不需要书写 JSON 协议。
|
|
70
|
+
- 命中后统一执行 `rewrite`。
|
|
71
|
+
- LLM 调用异常时也统一执行 `rewrite`。
|
|
72
|
+
- 若配置了 `timeoutMs` 且判定超时,会直接使用 `rewriteFallbackText` 作为改写结果。
|
|
73
|
+
- 若模型不支持当前 `outputMethod` 的 `response_format`,会自动尝试其它结构化方式并最终降级到纯文本 JSON 解析。
|
|
74
|
+
- 若历史配置仍携带 `onLlmError/systemPrompt/errorRewriteText`,会按兼容逻辑处理并给出弃用告警。
|
|
75
|
+
|
|
76
|
+
## 界面怎么填(最简)
|
|
77
|
+
|
|
78
|
+
`mode=llm` 时,最少只需要填这 3 项:
|
|
79
|
+
|
|
80
|
+
1. `llm.model`:选择过滤用模型(建议稳定、低延迟模型)。
|
|
81
|
+
2. `llm.scope`:建议先用 `both`。
|
|
82
|
+
3. `llm.rulePrompt`:写自然语言审核规则,不需要 JSON。
|
|
83
|
+
|
|
84
|
+
示例(个人信息场景):
|
|
85
|
+
|
|
86
|
+
- `llm.rulePrompt`:如果文本包含手机号、身份证号、银行卡号、家庭住址等个人敏感信息,请判定为命中并给出脱敏改写内容。
|
|
87
|
+
- `llm.rewriteFallbackText`:`[已过滤]`
|
|
88
|
+
|
|
89
|
+
说明:
|
|
90
|
+
|
|
91
|
+
- `llm` 模式是“只改写不拦截”。如果你要“直接拦截”,请改用 `mode=rule` 并配置 `action=block`。
|
|
92
|
+
|
|
93
|
+
## 超时与速度说明
|
|
94
|
+
|
|
95
|
+
- `timeoutMs` 是“单次 LLM 判定调用的最长等待时间(毫秒)”,不是整条工作流总超时。
|
|
96
|
+
- 设置过小(例如 `3000`)时,慢模型更容易超时,超时后会直接走 `rewriteFallbackText`。
|
|
97
|
+
- 不设置 `timeoutMs` 时,判定会一直等待模型返回,稳定性更高,但最坏延迟会变大。
|
|
98
|
+
- 命中输出过滤时,通常会感觉更慢:因为需要先拿到可判定内容,再统一改写返回。
|
|
99
|
+
- 你看到多个 `success` 卡片是正常的:输入判定、输出判定、收尾审计是不同执行步骤。
|
|
100
|
+
|
|
101
|
+
## 配置示例
|
|
102
|
+
|
|
103
|
+
### 示例 1:rule 模式
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mode": "rule",
|
|
108
|
+
"rules": [
|
|
109
|
+
{
|
|
110
|
+
"pattern": "炸弹",
|
|
111
|
+
"type": "keyword",
|
|
112
|
+
"scope": "both",
|
|
113
|
+
"severity": "high",
|
|
114
|
+
"action": "block"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"pattern": "(身份证|手机号)",
|
|
118
|
+
"type": "regex",
|
|
119
|
+
"scope": "output",
|
|
120
|
+
"severity": "medium",
|
|
121
|
+
"action": "rewrite",
|
|
122
|
+
"replacementText": "该回答包含敏感信息,已处理。"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"normalize": true,
|
|
126
|
+
"caseSensitive": false
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 示例 2:llm 模式(推荐)
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"mode": "llm",
|
|
135
|
+
"llm": {
|
|
136
|
+
"model": { "provider": "openai", "model": "gpt-4o-mini" },
|
|
137
|
+
"scope": "both",
|
|
138
|
+
"rulePrompt": "若内容包含违法、暴力或隐私泄露,请改写为安全且中性的表达。",
|
|
139
|
+
"rewriteFallbackText": "[已过滤]",
|
|
140
|
+
"timeoutMs": 3000
|
|
141
|
+
}
|
|
142
|
+
}
|
|
47
143
|
```
|
|
48
144
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
145
|
+
## 常见问题
|
|
146
|
+
|
|
147
|
+
### 1) 为什么没生效?
|
|
148
|
+
|
|
149
|
+
按顺序检查:
|
|
150
|
+
|
|
151
|
+
1. `mode` 是否正确。
|
|
152
|
+
2. `rule` 模式是否至少有 1 条有效规则(`pattern/type/action/scope/severity`)。
|
|
153
|
+
3. `llm` 模式是否填写了 `model/scope/rulePrompt`。
|
|
154
|
+
4. `scope` 是否覆盖当前阶段(输入或输出)。
|
|
155
|
+
|
|
156
|
+
### 2) 为什么提示中文校验错误?
|
|
53
157
|
|
|
54
|
-
|
|
158
|
+
中间件采用“编辑期容错、执行期校验”。编辑阶段允许先保存草稿,执行时再提示缺项。
|
|
55
159
|
|
|
56
|
-
|
|
57
|
-
- `enabled=true, profile=balanced`:词库较小,命中后整句替换
|
|
58
|
-
- `enabled=true, profile=strict`:词库更广,命中后直接拦截
|
|
160
|
+
### 3) 旧配置里的 systemPrompt 还能用吗?
|
|
59
161
|
|
|
60
|
-
|
|
162
|
+
可以。若未填写 `rulePrompt`,会兼容读取 `systemPrompt`。建议迁移到 `rulePrompt`。
|
|
61
163
|
|
|
62
164
|
## 开发验证
|
|
63
165
|
|
|
@@ -65,5 +167,5 @@ type SensitiveFilterConfig = {
|
|
|
65
167
|
pnpm -C xpertai exec nx build @xpert-ai/plugin-sensitive-filter
|
|
66
168
|
pnpm -C xpertai exec nx test @xpert-ai/plugin-sensitive-filter
|
|
67
169
|
pnpm -C plugin-dev-harness build
|
|
68
|
-
node plugin-dev-harness/dist/index.js --workspace ./xpertai --plugin
|
|
170
|
+
node plugin-dev-harness/dist/index.js --workspace ./xpertai --plugin ./middlewares/sensitive-filter
|
|
69
171
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensitive-filter.module.d.ts","sourceRoot":"","sources":["../../src/lib/sensitive-filter.module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sensitive-filter.module.d.ts","sourceRoot":"","sources":["../../src/lib/sensitive-filter.module.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAI9F,qBAIa,qBAAsB,YAAW,kBAAkB,EAAE,gBAAgB;IAChF,OAAO,CAAC,UAAU,CAAO;IAEzB,iBAAiB,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,eAAe,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAKxC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
var SensitiveFilterPlugin_1;
|
|
2
2
|
import { __decorate } from "tslib";
|
|
3
|
+
import { CqrsModule } from '@nestjs/cqrs';
|
|
3
4
|
import { XpertServerPlugin } from '@xpert-ai/plugin-sdk';
|
|
4
5
|
import chalk from 'chalk';
|
|
5
6
|
import { SensitiveFilterMiddleware } from './sensitiveFilter.js';
|
|
@@ -20,7 +21,7 @@ let SensitiveFilterPlugin = SensitiveFilterPlugin_1 = class SensitiveFilterPlugi
|
|
|
20
21
|
};
|
|
21
22
|
SensitiveFilterPlugin = SensitiveFilterPlugin_1 = __decorate([
|
|
22
23
|
XpertServerPlugin({
|
|
23
|
-
imports: [],
|
|
24
|
+
imports: [CqrsModule],
|
|
24
25
|
providers: [SensitiveFilterMiddleware]
|
|
25
26
|
})
|
|
26
27
|
], SensitiveFilterPlugin);
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { TAgentMiddlewareMeta } from '@metad/contracts';
|
|
2
|
-
import { AgentMiddleware, IAgentMiddlewareContext, IAgentMiddlewareStrategy
|
|
1
|
+
import type { TAgentMiddlewareMeta } from '@metad/contracts';
|
|
2
|
+
import { AgentMiddleware, IAgentMiddlewareContext, IAgentMiddlewareStrategy } from '@xpert-ai/plugin-sdk';
|
|
3
3
|
import { SensitiveFilterConfig } from './types.js';
|
|
4
4
|
export declare class SensitiveFilterMiddleware implements IAgentMiddlewareStrategy<SensitiveFilterConfig> {
|
|
5
|
+
private readonly commandBus;
|
|
5
6
|
readonly meta: TAgentMiddlewareMeta;
|
|
6
|
-
createMiddleware(options: SensitiveFilterConfig,
|
|
7
|
+
createMiddleware(options: SensitiveFilterConfig, context: IAgentMiddlewareContext): Promise<AgentMiddleware>;
|
|
8
|
+
private createRuleModeMiddleware;
|
|
9
|
+
private createLlmModeMiddleware;
|
|
7
10
|
}
|
|
8
11
|
export type { SensitiveFilterConfig };
|
|
9
12
|
//# sourceMappingURL=sensitiveFilter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensitiveFilter.d.ts","sourceRoot":"","sources":["../../src/lib/sensitiveFilter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sensitiveFilter.d.ts","sourceRoot":"","sources":["../../src/lib/sensitiveFilter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,oBAAoB,EAA8B,MAAM,kBAAkB,CAAA;AAGnG,OAAO,EACL,eAAe,EAGf,uBAAuB,EACvB,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAOL,qBAAqB,EAMtB,MAAM,YAAY,CAAA;AAienB,qBAEa,yBAA0B,YAAW,wBAAwB,CAAC,qBAAqB,CAAC;IAE/F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAqRlC;IAEK,gBAAgB,CACpB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,eAAe,CAAC;IAa3B,OAAO,CAAC,wBAAwB;IAqOhC,OAAO,CAAC,uBAAuB;CA8YhC;AAED,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
|