FDE W2D3 学习手册 · 数据库 Tool 与规则 Tool
W2 Week2 Day3 · A 级(必须掌握,安全核心)· 5h · 学完能讲透"让 Agent 安全查库、可靠算规则"的设计与风控
本日定位:W2D1 工具调用 + W2D2 OCR 之后,今天落地两类"高敏感"工具:数据库 Tool(读业务数据)和规则 Tool(算金额/风险)。它们是理赔自动化的"数据源"和"决策脑",但也是安全和合规的重灾区。
学完能回答:① 数据库 Tool 的安全设计(只读/白名单/参数化/超时/审计);② 规则引擎(Drools)在理赔风控怎么用、相比 LLM 直接算金额的优势。
使用方法:通读原理 → 重点看「面试话术」「易错点」→ 做自测清单 → 配合《FDE-W2D3-评测题.md》。选中不熟的词可标注(左下★重要 / 右下📌待查)。
一、数据库 Tool 的定位与安全基调
数据库 Tool 让 Agent 能查保单、理赔记录、药品目录等。但它和 OCR 不同——直接接触核心业务数据,一旦设计不当,轻则查错、重则SQL 注入 / 越权读隐私 / 拖垮生产库。
安全基调:数据库 Tool 默认只读、最小化、受控。它只回答"查",绝不接受"写/删";敏感字段脱敏;每次查询可追溯。
数据库 Tool 是 Agent 的"只读数据窗口"。它和 OCR 不同,直接碰核心数据,所以安全是第一位:只读、白名单、参数化、超时、审计,缺一不可。
在医疗保险场景,数据库 Tool 查的是保单、就诊、理赔等 PII 密集数据,受《个人信息保护法》和保险监管约束。安全设计不是"可选项",是"上线前提"。
二、参数化 SQL 与防注入
2.1 什么是 SQL 注入
若把模型给的参数直接拼进 SQL 字符串,攻击/幻觉可能注入恶意语句:
# 错误示范:字符串拼接
sql = "SELECT * FROM policy WHERE policy_no = '" + args['policy_no'] + "'"
# 若 policy_no = "x'; DROP TABLE policy; --" → 灾难
2.2 参数化查询(Prepared Statement)
# 正确:占位符 + 参数绑定,数据库区分"代码"和"数据"
cur.execute(
"SELECT policy_no, holder, special_drug_limit FROM policy WHERE policy_no = %s",
(args['policy_no'],) # 参数由驱动安全转义
)
防注入用参数化查询(占位符+参数绑定):数据库把参数当"数据"不是"代码",即使参数里含 ' DROP TABLE 也不会执行。绝不能用字符串拼接模型给的参数。
参数化是数据库 Tool 的铁律。即使参数是模型生成的,也必须走占位符绑定,由 JDBC/psycopg 等驱动做转义。这是防注入的最有效手段。
① ORM(如 MyBatis/Hibernate)的 ${} 是拼接、#{} 才是参数化,别用错。② 即使参数化,仍要白名单限制表/字段(见 s4),防止查到不该查的表。③ LIKE 模糊查询也要参数化,别手拼 %。
三、只读账号与最小权限
3.1 专用只读账号
数据库 Tool 用的连接账号,必须是独立的、只读(SELECT only)的专用账号,绝不复用业务写库账号或 DBA 账号。
| 账号类型 | 权限 | 能否用于 Tool |
| 只读查询账号 | SELECT 指定库表 | ✅ 应该 |
| 读写业务账号 | 增删改查 | ❌ 禁止 |
| DBA 管理员 | 全部权限 | ❌ 绝对禁止 |
3.2 最小权限原则
- 只授予 Tool 实际需要的库/表/列读权限。
- PII 列(身份证、手机号)要么不授予,要么授权脱敏视图。
- 网络层限制 Tool 账号只能从应用服务器 IP 连。
数据库 Tool 必须用独立只读账号,绝不用业务写账号或 DBA 账号。遵循最小权限:只给需要的表/列,PII 列走脱敏视图。
即使参数化防住了注入,若用写账号,模型或被诱导执行 UPDATE/DELETE 就完了。只读账号是"即使被攻破,损失也封顶"的纵深防御。
四、表和字段白名单
4.1 为什么需要白名单
参数化解决了"注入",但没解决"查到不该查的表/字段"。白名单在应用层再锁一层:只允许访问预定义的表和字段。
ALLOWED_TABLES = {"policy", "claim_record", "drug_catalog"}
ALLOWED_COLUMNS = {
"policy": {"policy_no","holder","special_drug_limit","valid_until"},
"claim_record": {"claim_id","status","amount","reason"},
"drug_catalog": {"drug_name","is_special","price"}
}
def build_query(table, columns, where):
if table not in ALLOWED_TABLES: raise PermissionError("表不在白名单")
bad = set(columns) - ALLOWED_COLUMNS[table]
if bad: raise PermissionError(f"字段不在白名单: {bad}")
# 只允许等值/IN 条件,列名也必须白名单校验
...
白名单在应用层限制"能查哪些表、哪些字段、哪些条件列",参数化只防注入不防越权。即使模型想查 salary 表,白名单直接拒绝。
白名单 + 参数化 + 只读账号,构成数据库 Tool 的"三道防线"。白名单还能防止模型生成离谱的跨表 JOIN 拖垮数据库。
① 白名单校验要在应用层做,别信任数据库端;且列名也要校验(防止查密码列)。② 别用"黑名单"(禁止 xxx),攻击者总能找到漏网之鱼,用白名单(只允许 xxx)才稳。③ 动态拼表名无法参数化,必须白名单枚举,绝不能把模型给的表名直接拼 SQL。
五、查询超时与返回数量限制
5.1 查询超时
给每个查询设语句超时(如 PostgreSQL 的 statement_timeout),防止慢查询/全表扫描拖垮数据库。
cur.execute("SET LOCAL statement_timeout = 3000") # 3 秒超时
cur.execute("SELECT ... FROM policy WHERE ...")
5.2 返回数量限制
- 强制
LIMIT(如最多 50 行),避免一次返回几万行撑爆上下文/内存。
- 分页或聚合优先;需要全量时走离线任务而非 Tool 实时返回。
- 返回前裁剪/脱敏敏感字段,只留下游需要的。
查询要设语句超时(如3s)和返回行数上限(如LIMIT 50),防止慢查询拖垮库、大结果撑爆上下文。返回前脱敏裁剪。
超时和限量是"保护生产库"的护栏。Agent 可能生成 SELECT * FROM claim_record 没有 WHERE,没有 LIMIT 直接打满库——白名单+LIMIT+超时缺一不可。
六、审计日志
6.1 记什么
- 谁(哪个用户/session)在何时查了什么(表/条件/参数)。
- 返回了什么摘要(脱敏后),命中多少行。
- 查询是否成功、耗时、是否触发白名单拒绝。
6.2 审计的价值
保险行业对 PII 访问有合规要求(可追溯、可审计)。审计日志用于:合规报备、异常检测(某账号频繁查陌生保单)、争议溯源。
数据库 Tool 必须留审计日志:谁、何时、查了什么表/条件、返回多少行、是否拒拦。保险 PII 访问受合规约束,审计是可追溯和异常检测的底座。
审计日志要防篡改(独立存储、只追加)。它既是合规要求,也是"出事能说清"的护身符——当被问"为什么这人的保单被查了",有日志可查。
① 审计日志本身别记明文 PII(记脱敏或哈希),否则审计库又成泄露点。② 日志要关联业务 session,而非只记 DB 连接账号——否则分不清是哪个客户触发的查询。
七、规则 Tool 的定位
规则 Tool 负责确定性的业务决策与计算:理赔金额怎么算、风险等级怎么定、是否拒赔。它和数据库 Tool 互补——一个取数,一个决策。
为什么不用 LLM 直接算?金额、风险等级必须精确、可复现、可审计,LLM 是概率模型,算金额可能算错、每次结果还不一致。确定性计算要用代码/规则引擎,LLM 只做"理解诉求、调工具、组话术"。
规则 Tool 做确定性决策(算金额、定风险、判拒赔),和数据库 Tool 一个取数一个决策。金额这类必须精确可复现,不能交给会"算错"的 LLM。
在理赔风控里,规则 Tool 是"算账先生":输入(保单额度、发票金额、特药目录命中),输出(应赔金额、风险等级、拒赔原因)。结果可解释、可审计,符合保险监管。
八、简单规则脚本 vs Drools 规则引擎
| 维度 | 简单脚本/函数 | Drools 规则引擎 |
| 适用规模 | 规则少(几条~几十条) | 规则多、常变(上百条) |
| 可维护性 | 改代码要发版 | 规则与代码分离,可热更新 |
| 冲突处理 | 自己写 if-else 顺序 | 引擎自动做冲突解析、规则链 |
| 可解释 | 需自己记命中了哪条 | 天然记录"命中规则+依据" |
| 学习成本 | 几乎无 | 需学 DRL 语法/概念 |
8.1 Drools 简介
Drools(drools.org)是成熟的 Java 规则引擎,用 DRL 描述规则:when(条件)→ then(动作)。规则与业务代码解耦,支持版本管理、规则流、复杂事件。
rule "特药目录内且额度充足-全额赔付"
when
$c : Claim( drugInCatalog == true, amount <= specialDrugLimit )
then
$c.setPayAmount($c.getAmount());
$c.setRiskLevel("low");
$c.setReason("特药在目录内且额度充足");
end
规则少用简单脚本,规则多且常变用 Drools 这类规则引擎。Drools 用 when→then 描述规则,规则与代码分离可热更新,还自动记录命中依据。
保险理赔规则成百上千条且频繁调整(政策变、药品目录变),用硬编码 if-else 会灾难。Drools 让业务人员也能维护规则,且每次决策自动留"命中了哪条规则"的依据——这正是审计要的。
九、规则版本管理
- 规则要版本化:每条规则有版本号、生效时间、作者、变更原因。
- 决策可回溯:一次理赔结论要能关联到"当时生效的哪版规则",避免政策变了却说不清旧案为何那么赔。
- 灰度/回滚:新规则先小流量,异常可快速回滚到上一版。
- 审批流:规则变更走审批,不能谁改了线上就变。
规则要版本化:每条有版本/生效时间/作者,决策能回溯到"当时哪版规则"。支持灰度发布和回滚,变更走审批。
规则版本管理是合规刚需。监管可能事后审计"这笔拒赔依据的是哪条规则、当时是否有效"。没有版本化,你答不上来。
十、命中依据、金额计算与风险等级
10.1 命中依据(为什么这么算)
规则引擎输出不只给结果,还要给依据链:命中了哪些规则、输入是什么、得出什么结论。这既是可解释性,也是争议处理依据。
{
"pay_amount": 1280.00,
"risk_level": "low",
"hit_rules": ["R-特药目录内", "R-额度充足"],
"reason": "药品奥希替尼在特药目录,金额1280≤额度30万",
"rule_version": "v2026.03"
}
10.2 金额计算与风险等级
| 输入 | 规则逻辑 | 输出 |
| 发票金额、保单额度、目录命中 | 目录内且≤额度→全额;超额度→按比例 | pay_amount |
| 既往史、理赔频次、异常特征 | 命中风控规则→升级 | risk_level: low/medium/high |
规则引擎输出要带"命中依据链"(哪条规则+输入+结论),这是可解释和审计的核心。金额按目录/额度算,风险等级按风控规则定。
"给结果更要给依据"是 FDE 的高分点。只返回 pay_amount=1280 不够,要能说清"为什么是 1280、依据哪条规则、当时哪版"——这正是规则引擎相对 LLM 的优势。
① 金额计算要处理边界(负数、超额度、重复理赔),别让 LLM 自由算。② 风险等级要可解释,不能只给个"high"没理由——监管和客诉都要求说明。③ 规则之间可能冲突(一条说赔一条说不赔),引擎要定义冲突优先级,不能靠巧合。
十一、资源与工具
- Drools 官网:drools.org —— 规则引擎、DRL 语法、决策表。
- PostgreSQL 文档:postgresql.org/docs/current —— statement_timeout、权限、脱敏(如 pgcrypto)。
- LangChain Tools:python.langchain.com/docs/how_to/tools —— 如何把 SQL/函数封装成 Agent 可调的 Tool。
- SQLAlchemy / JDBC:参数化查询的标准做法。
实战建议:小规则用 Python 函数 + 配置化(规则写配置不写死);规则上百条且多变再上 Drools。数据库 Tool 用 SQLAlchemy 参数化 + 只读账号 + 白名单中间件。
资源:Drools(规则引擎)、PostgreSQL 文档(超时/权限/脱敏)、LangChain Tools(把 SQL/函数包成 Tool)。规则少先配置化,多再上 Drools。
十二、面试达标线①:数据库 Tool 的安全设计
独立只读账号 → 参数化查询(防注入) → 表/字段白名单(防越权) → 语句超时 + LIMIT(防拖库) → 返回脱敏裁剪 → 全量审计日志(谁/何时/查什么)
- 只读账号:专用 SELECT-only 账号,绝不复用写/DBA 账号,纵深防御。
- 参数化:占位符绑定,数据库区分代码与数据,杜绝 SQL 注入。
- 白名单:应用层限制可查的表、字段、条件列(用白名单不用黑名单)。
- 超时 + 限量:statement_timeout + 强制 LIMIT,保护生产库。
- 审计:记谁/何时/查什么/返回多少,关联业务 session,日志防篡改。
数据库 Tool 安全五件套:只读账号、参数化防注入、表/字段白名单防越权、超时+LIMIT 防拖库、全量审计。核心是纵深防御——每层都挡一道。
十三、面试达标线②:规则引擎在理赔风控的应用与对比 LLM 算金额
| 维度 | Drools/规则引擎 | 让 LLM 直接算金额 |
| 准确性 | 确定性,结果可复现 | 概率性,可能算错、不一致 |
| 可审计 | 天然记录命中规则+依据+版本 | 难追溯"为什么算这个数" |
| 可维护 | 规则与代码分离,热更新 | 改逻辑要改 prompt,易漂移 |
| 合规 | 满足保险监管可追溯要求 | 不满足(黑盒) |
| 适用 | 金额/风险/拒赔等硬决策 | 理解诉求、组话术、调工具 |
- 怎么用:Agent 用 LLM 理解用户诉求→调用数据库 Tool 取数→调用规则 Tool(Drools)→规则引擎按版本化规则算出 pay_amount / risk_level,并附带命中依据链。
- 优势总结:精确、可复现、可审计、可热更新、合规友好——这是金额/风控这种"不能错"的场景必须上规则引擎的根本原因。
规则引擎(Drools)做金额/风险决策:确定性、可复现、自带命中依据和版本,满足保险合规;LLM 直接算会算错、不一致、不可审计。正确分工:LLM 理解+调度,规则引擎算账。
十四、W2D3 自测清单
- 能说清数据库 Tool 为什么是"高敏感"工具,安全基调是什么。
- 能写出参数化查询代码,并解释它如何防 SQL 注入(代码 vs 数据分离)。
- 知道为什么必须用独立只读账号,而不是业务/DBA 账号。
- 能解释表/字段白名单的作用,以及为什么用白名单而非黑名单。
- 能说出查询超时(statement_timeout)和返回 LIMIT 的必要性。
- 能列出数据库 Tool 审计日志要记哪些内容,以及为何要关联业务 session。
- 能区分规则脚本和 Drools 规则引擎的适用场景与优劣。
- 能写出一条 Drools 的 when→then 规则示例。
- 能解释规则版本管理的价值(决策可回溯、灰度、回滚、审批)。
- 能讲清规则引擎输出要带"命中依据链",以及金额/风险怎么算。
- 能讲清达标线①(数据库 Tool 安全五件套)。
- 能讲清达标线②(Drools 在理赔风控的应用 + 相比 LLM 算金额的优势)。
十五、高频面试题速记卡
Q:数据库 Tool 怎么防 SQL 注入?
用参数化查询(占位符+参数绑定),数据库把参数当数据不是代码。绝不字符串拼接模型给的参数。
Q:为什么数据库 Tool 要用只读账号?
纵深防御:即使被诱导,损失也封顶在"只读"。绝不用写账号/DBA账号,防 UPDATE/DELETE 被触发。
Q:参数化了还需要白名单吗?
需要。参数化只防注入,不防越权。白名单在应用层限制能查哪些表/字段/条件列,防查到 PII 或无关表。
Q:白名单和黑名单哪个好?
白名单(只允许 xxx)好。黑名单(禁止 xxx)总有漏网之鱼,攻击能找到没禁的入口。
Q:数据库 Tool 为什么要超时和 LIMIT?
防慢查询/全表扫描拖垮生产库,防大结果撑爆上下文和内存。超时+LIMIT 是保护库的护栏。
Q:审计日志记什么?为什么关联业务 session?
记谁/何时/查什么表条件/返回多少/是否拒拦。关联业务 session 才能分清是哪个客户触发的,而非只看 DB 账号。
Q:Drools 和简单规则脚本怎么选?
规则少且稳用脚本;规则多、常变、要热更新和命中依据用 Drools。保险理赔上百条规则适合 Drools。
Q:为什么不让 LLM 直接算理赔金额?
LLM 概率性会算错、每次不一致、不可审计。金额必须精确可复现,用规则引擎;LLM 只做理解和调度。
Q:规则引擎输出为什么要带"命中依据"?
可解释+可审计。监管和客诉都要"为什么赔/拒、依据哪条规则、哪版",这是 LLM 给不出而规则引擎天然有的。
Q:规则版本管理有什么用?
让决策可回溯到"当时哪版规则",支持灰度发布和回滚,变更走审批——保险合规刚需。
FDE W2D3 学习手册 · 数据库 Tool 与规则 Tool(面试级)· 配合《FDE-W2D3-评测题.md》自测
📌 待查★ 重要