我给 AI 装了一个"大脑":从会聊天,到会干活
银行合规助手项目——Agent
2026-06-22我给 AI 装了一个”大脑”:从会聊天,到会干活
上篇我们搭了一个 RAG 系统,让 AI 能从银行合规文档里找答案。 但很快我就发现,它只会回答问题——不会查客户信息,也不会提交申请。 这篇文章,我给它加上了真正的”行动能力”。
一、RAG 做不到什么
上次的系统上线后,我测试了几个问题:
“信用卡逾期30天会有什么后果?”
✅ 完美,从合规文档里检索出了答案,还标注了条款来源。
“帮我查一下 C002 客户的账户情况”
❌ AI 开始胡说了。它根本不知道 C002 是谁,只能靠”猜”。
“C002 逾期了,帮我提交一个减免申请”
❌ 更离谱,它编了一个假的申请单号,说”已提交”——但什么都没发生。
RAG 解决的是”知道什么”的问题,解决不了”能做什么”的问题。
这就是 RAG 和 Agent 的本质区别:
- RAG:图书馆管理员,能帮你找资料
- Agent:有手有脚的助理,能找资料、查系统、替你提申请
二、Agent 比 RAG 多了什么
多了两件事:意图判断 和 工具调用。
打个比方——
你走进银行,跟大堂经理说了一句话:
“C002 客户逾期了,帮我提交一个减免申请”
大堂经理需要先判断你想干什么(意图判断),然后去做对应的事(工具调用):
- 如果你在问规定 → 去查合规手册(RAG)
- 如果你在查客户 → 去查客户系统
- 如果你要提申请 → 去填审批表单
这个”判断 → 执行”的过程,就是 Agent 的核心逻辑。
三、意图路由:给 AI 装一个交通枢纽
在代码里,我把用户的问题分成三类:
用户的问题进来,先经过一个”路由器”——判断是哪种意图,再分发给对应的处理模块:
用户输入
│
▼ 路由器(意图判断)
├── 知识型 ──→ RAG 检索 ──→ 带引用的合规回答
├── 查询型 ──→ 客户工具 ──→ 客户账户信息
└── 操作型 ──→ 申请工具 ──→ 待审批申请单关键问题是:路由器怎么判断意图?
我实现了两种方式,结论很有意思。
四、方式A:让模型自己决定调哪个工具
这是 OpenAI 推广的 Function Calling(工具调用) 方式。
原理:我给模型发一份”工具说明书”,告诉它有三个工具可用:
工具1:rag_search —— "搜索合规知识库,回答规定类问题"
工具2:query_customer —— "查询特定客户的账户信息"
工具3:submit_operation —— "提交需要人工审批的操作申请"然后把用户的问题一起发过去,让模型自己判断:“我要调用哪个工具,传什么参数?”
模型返回的不是一句话,而是一个结构化的指令:
{
"tool": "query_customer",
"arguments": {"customer_id": "C002"}
}Python 读取这个指令,去查询 C002 的数据,再把结果返回给用户。
优点:参数提取准确,模型直接输出结构化数据。 缺点:依赖模型有没有被专门训练过这种格式——小模型经常”不配合”。
五、方式B:让模型输出 JSON,Python 手动解析
这是更稳妥的降级方案。
我不要求模型调用工具,只要求它输出一个 JSON,告诉我它的判断:
Prompt:根据用户输入判断意图,只输出JSON,格式如下:
{"intent": "知识型/查询型/操作型", "reason": "判断依据", "params": {...}}用 Ollama 的 format: "json" 模式,强制模型输出合法 JSON(不加这个,小模型会输出花式乱码)。
模型输出:
{
"intent": "操作型",
"reason": "用户请求为特定客户提交逾期罚息减免申请",
"params": {
"operation_type": "逾期减免",
"customer_id": "C002",
"detail": "逾期罚息减免申请"
}
}Python 拿到这个 JSON,直接读 intent 字段,决定走哪个分支。
优点:几乎所有模型都能跟着 JSON 指令走,稳定性强。 缺点:多了一层解析代码,遇到模型输出奇怪内容还要兜底处理。
六、11 道测试题,两种方式正面 PK
我准备了 11 道测试题——4 道知识型、3 道查询型、2 道操作型,还故意加了 2 道模糊题:
Q10 [模糊] C002 客户最近有没有逾期?如果逾期了按规定要怎么处理?
Q11 [模糊] 账户 C003 上个月还款正常,但他想申请一个利率优惠,帮我走一下流程两种方式全部跑一遍,结果如下:
两种方式最终正确率相同,但过程差异明显:
tool_calling 有 4 道题”掉链子”了——模型没有调用工具,直接用自然语言回答了(比如 Q04「银行多少天回复投诉」、Q06「客户逾期了几天」)。
不过代码里做了降级兜底:检测到没有工具调用时,自动切换到 json_parse 重新判断,所以结果还是正确的。代价是这 4 道题多跑了一次模型,耗时多了约 800ms。
模糊题的处理方式不同:
Q10「逾期情况 + 怎么处理」—— - json_parse:模型输出”查询型和知识型”(不合法),触发降级,兜底为知识型(走 RAG) - tool_calling:模型选择了查询型(先查客户,再说规定)
Q11「申请利率优惠」——两种方式都判断为操作型,一致。
七、为什么操作型不直接执行
你可能注意到一个细节:当用户说”帮我提交减免申请”时,系统只是生成了一张申请单,而不是直接修改客户数据。
已生成申请单 [REQ-67517237],等待人工审批这是故意设计的。
在金融场景里,任何涉及账户状态或资金流向的操作,都必须有人工复核这道关卡。原因很简单:
- AI 的意图判断有概率出错
- 出错了之后,数据改了就很难回滚
- 监管要求每笔操作都要留下可追溯的审批记录
所以正确的设计是:
AI 负责 → 识别意图 + 整理信息 + 生成申请单
人工负责 → 审核 + 最终决策这有个专业名词叫 Human-in-the-loop(人在环路中),是目前 AI 落地高风险业务的主流方案。
八、整体结构一眼看懂
用户输入
│
▼ router.py(意图路由)
│ 方式A:tool_calling(发工具定义,模型自选)
│ 方式B:json_parse(要求输出JSON,Python解析)
│
├── 知识型 ──→ RAG(chunking + embedding + vectorstore + LLM)
│ → 带条款引用的合规回答
│
├── 查询型 ──→ tools.py: query_customer_info("C002")
│ → 客户姓名/额度/逾期状态/信用评分
│
└── 操作型 ──→ tools.py: submit_operation_request(...)
→ 生成申请单,等待人工审批整套系统: - 路由模型:本地 Ollama qwen2.5:7b(完全免费) - RAG 问答:同上,或切换 Anthropic Claude - Embedding:sentence-transformers(本地,免费) - 向量库:Chroma(本地文件,免费)
全程不需要 OpenAI,不需要任何云端 API Key,跑在自己电脑上。
九、学到了什么
Agent = 意图判断 + 工具调用。说起来简单,但每个环节都有细节要处理。
json_parse 在小模型上比 tool_calling 更稳。不是说 tool_calling 不好,而是小模型的工具调用训练不充分,遇到措辞平实的问题容易”跑偏”。
降级兜底比单点完美更重要。与其追求路由 100% 原生成功,不如把兜底链路做扎实——4 道触发降级的题,用户感知不到任何差异。
模糊问题是真正的分水岭。明确的问题,两种方式都能判对;模糊问题暴露了模型对”多意图”的处理策略差异。这部分没有标准答案,取决于你的业务希望在模糊时”偏向哪个意图”。
从 RAG 到 Agent,代码加了不到 300 行——tools.py、router.py、agent_main.py 三个文件。复杂度没有想象中高,核心是把每一步的职责想清楚。