资讯动态

大模型+工具调用+策略编排:保险业务智能办理系统实战

发布时间:2026/10/21 2:07:09 来源:尧图企业网站定制
保险和金融这个行业咨询场景一直是需求量大但翻车率也高的地方。之前做过好几个智能问答类的项目真正落到保险理赔、贷款咨询这种业务里最大的问题不是模型不会说话而是它说了不算——回答得再流畅没法查用户保单、没法算费率、没法走审批流程就只是个聊天机器人。我这次做的项目核心思路就是把大模型当成一个调度中枢通过工具调用把业务系统的能力接进来再用策略编排把业务流程固化下来最终形成一套能真正办理业务的智能系统。这篇博文会把完整方案、设计思路和核心源代码都拆开讲清楚。项目适合谁看如果你正在做金融保险领域的AI应用或者想把大模型接入现有业务系统但又不知道从哪下手这篇文章可以给你一套能直接落地的参考。你不需要是算法专家但最好懂一点Python和基本的API开发。1. 整体方案设计为什么是工具调用策略编排而不是端到端大模型先说说我为什么选这个架构。刚开始做保险咨询智能办理的时候有过两个失败的方向写出来帮你避坑。1.1 第一个失败方向纯RAG问答第一版做的是纯检索增强生成把保险条款、产品说明书都切片存进向量库用户提问就去检索相关段落喂给模型。效果怎么样回答什么是等待期免赔额怎么算这类概念性问题挺流畅的但一遇到我这个保单能不能赔我该买哪个产品就露馅了。原因很简单模型即使检索到了条款它也不具备用户的实时信息——用户的保单状态、历史理赔记录、当前年龄健康状况这些都在业务系统里。纯RAG本质上是查资料写作文不是办事。保险咨询的大部分问题最终都要落到数据查询和业务规则判断上这一层不打通前面回答得再好也是空中楼阁。1.2 第二个失败方向写死对话流程第二版走了另一个极端用传统对话流程把常见问题全部画成决策树比如用户说我要理赔就走理赔节点逐项询问保单号、出险时间、事故描述。这确实能办成事但维护成本高到离谱。金融保险的业务规则更新频繁产品停售、费率调整、理赔口径变化每一次改动都要重新画流程图、改代码、出测试用例。而且用户根本不会按你画的流程说话他可能一上来就甩给你一段一百字的事故描述中间夹杂着情绪化表达决策树里根本没有这个分支对话直接就死了。1.3 第三版架构各司其职的三层设计最后定下来的架构分三层第一层是大模型对话中枢负责理解用户意图、维护多轮对话上下文、从自然语言中抽取结构化参数。第二层是工具调用层把业务系统的能力封装成语义明确的工具函数包括保单查询、理赔试算、产品推荐、进度查询、人工转接等。模型通过函数调用机制按需触发这些工具。第三层是策略编排层这一层是整个系统的灵魂。它定义了一套业务规则引擎决定工具调用结果的后续流程——是直接返回给用户还是需要进入审批环节还是需要二次确认。业务人员写策略配置系统执行策略。为什么这么拆因为大模型擅长的是理解和表达不擅长的是精确计算和流程控制。策略编排就是把模型说了不算的部分用确定性的规则接住。模型负责把用户的话翻译成结构化意图和参数业务规则负责决定接下来怎么走两相结合既灵活又可控。提示这个架构里最容易被忽视的是策略编排层。很多人做工具调用就止步于模型调了个函数拿到结果但真正业务落地时你会发现同样的工具调用结果在不同的业务场景下后续动作完全不同。没有编排层所有的分支逻辑会全部堆在模型提示词里最后变得完全不可维护。2. 核心源码拆解工具定义与调用循环的工程实现这一节直接上代码。我用的模型接口兼容OpenAI格式的函数调用协议这套协议现在基本是行业标准换成别家的模型改动成本也很低。2.1 工具目录的结构化定义首先看工具怎么定义。每个工具包含名称、描述、参数结构三部分。描述字段是写给人看的但更重要的是它其实是在写给模型看——模型要根据这段描述判断什么时候该调用这个工具、参数该怎么填。# tools.py import json from typing import Any, Callable, Dict # 工具注册表名字 - (函数实现, 参数Schema, 工具描述) TOOL_REGISTRY: Dict[str, Dict[str, Any]] {} def register_tool(name: str, description: str, parameters: Dict[str, Any]): def decorator(func: Callable): TOOL_REGISTRY[name] { function: func, description: description, parameters: parameters, } return func return decorator # 保费试算工具 register_tool( namecalculate_premium, description计算指定保险产品的保费。当用户询问保费、价格、每年交多少钱时必须调用此工具。需要用户年龄、产品名称和保额。, parameters{ type: object, properties: { product_name: {type: string, description: 保险产品名称}, age: {type: integer, description: 用户年龄}, coverage_amount: {type: number, description: 保额单位为万元}, gender: {type: string, enum: [male, female], description: 性别} }, required: [product_name, age, coverage_amount] } ) def calculate_premium(product_name: str, age: int, coverage_amount: float, gender: str male) - str: # 实际项目中这里会调用精算服务这里模拟计算 base_rate {健康保: 0.023, 安心保: 0.018, 全家福: 0.031} rate base_rate.get(product_name, 0.025) premium coverage_amount * 10000 * rate * (1.1 if age 45 else 1.0) return json.dumps({product_name: product_name, premium: round(premium, 2), currency: CNY}) # 保单查询工具 register_tool( namequery_policy, description查询用户的保单信息包括保额、保障期限、缴费状态。当用户询问保单情况、保障内容、保单是否有效时必须调用。, parameters{ type: object, properties: { policy_id: {type: string, description: 保单号}, }, required: [policy_id] } ) def query_policy(policy_id: str) - str: # 模拟保单数据实际项目中会从核心系统同步 mock_db { P20240001: {holder: 张明, product: 健康保, sum_amount: 500000, status: active, valid_till: 2034-05-20}, P20240002: {holder: 李丽, product: 安心保, sum_amount: 300000, status: lapsed, valid_till: 2023-12-31} } policy mock_db.get(policy_id, {}) return json.dumps(policy, ensure_asciiFalse)这里有个关键细节工具描述里的触发条件要写清楚。我见过很多团队把工具描述写得含糊模型根本不知道什么时候该调用结果就是乱调或者不调。描述是给模型的使用说明书越精确越好。比如保费试算工具描述里明确写了当用户询问保费时必须调用模型看到这个保险多少钱就会触发。2.2 模型调用循环从自然语言到工具执行有了工具定义接下来是核心的调用循环。整个流程是这样的把用户消息和历史对话发给模型同时附上工具列表模型返回结果有两种可能一种是普通文本回答说明不需要调用工具另一种是函数调用请求包含工具名和参数如果是函数调用系统执行对应工具拿到结果把结果作为一条新消息返回给模型模型根据工具结果生成最终回答或者继续调用下一个工具。# agent.py import json from typing import List, Dict class ToolCallingAgent: def __init__(self, llm_client, tools: List[Dict]): self.llm llm_client self.tools tools def run(self, user_input: str, history: List[Dict]) - str: # 构建完整对话上下文 messages history [{role: user, content: user_input}] # 最多允许5次工具调用防止死循环 for _ in range(5): response self.llm.chat_completion( messagesmessages, toolsself.tools ) msg response[message] # 情况一模型直接给出文本回答不需要调工具 if not msg.get(tool_calls): return msg[content] # 情况二模型请求调用工具 messages.append(msg) for tool_call in msg[tool_calls]: tool_name tool_call[function][name] arguments json.loads(tool_call[function][arguments]) # 从注册表取出工具并执行 if tool_name in TOOL_REGISTRY: result TOOL_REGISTRY[tool_name][function](**arguments) else: result json.dumps({error: f未找到工具: {tool_name}}) # 工具执行结果以tool消息形式返回给模型 messages.append({ role: tool, tool_call_id: tool_call[id], content: result }) # 超过最大调用次数兜底返回 return 抱歉这个问题比较复杂我需要转接人工客服处理。这段代码看着不长但有几个工程细节值得展开说说。细节一工具调用次数的上限。理论上模型可以在一次回复里请求多个工具调用也可以连续多轮调用。但一定要设上限否则模型可能在复杂任务中陷入循环调用或者无限追问。实战中5次足够覆盖大多数场景超过这个数基本说明意图理解出了问题直接转人工反而更负责。细节二工具结果的转发格式。工具执行完的结果要用role: tool消息回传给模型并且tool_call_id必须和模型发起的调用对应上。不同模型平台这个字段的细节略有差异比如有的平台要求的是name字段回传接入的时候要看清楚文档。这个字段对不上模型会认为工具调用流程异常直接报错。细节三异常兜底。工具内部抛异常不能被模型看到原始堆栈需要捕获后转成友好错误信息返回给模型。模型很聪明它拿到该用户暂无有效保单这样的信息后会把回答转向询问用户是否确认保单号正确而不是傻乎乎地直接报错。2.3 多工具协同调用一个复杂场景示例单工具调用好做难的是多工具配合。举个例子用户问我今年50岁女想买份重疾险保额30万帮我算下保费另外看看我之前买的P20240001那份保单还有多久到期。这个请求同时涉及保费试算和保单查询两个工具而且两个请求之间没有依赖关系可以并行调用。我封装的循环会自动处理这种情况——模型会在一次回复中返回两个tool_calls代码里的循环会依次执行两个工具把结果一并回传给模型汇总回答。更复杂的情况是串行调用。比如用户问我之前买的那份保单现在退保能拿回多少钱这就必须先查保单拿到保单里的产品名称、保额、投保日期后再调用退保试算工具。模型在第一次工具结果返回后会根据结果内容判断是否要继续调用下一个工具。这种依赖关系全部靠模型推理完成不需要硬编码。实操心得并行调用看起来效率高但要慎用。有些工具之间有隐性依赖比如先查用户身份信息才能查保单列表如果把这俩并行执行身份还没查到就查保单结果必然是空的。我的做法是在工具描述里明确注释该工具依赖get_user_profile先执行模型通常能理解这种约束。3. 策略编排引擎业务规则和模型解耦的关键设计工具调用解决了模型能做事的问题但保险业务还有一个更棘手的需求相同的操作在不同条件下要走不同的流程。比如同样是理赔申请金额小于5000元自动审批5000到5万需要人工复核超过5万要上报风控。模型解决不了这种确定性的规则判断这是策略编排的活。3.1 为什么必须单独做编排层你看如果把业务规则写进提示词让模型自己判断会怎样。表面上看可行模型确实能理解如果金额超过5万要上报风控这种指令但实际跑起来问题很大第一规则不透明。模型怎么理解的、理解得对不对没有人能保证业务审计时你说模型自己判断的合规部门不答应。第二规则变更成本高。每周业务口径都在变这周改了免赔额规则下周调整了理赔审批权限每次都要改提示词、重新调试时间全耗在这种事情上。第三模型可能灵活处理。比如政策规定糖尿病患者的医疗险理赔必须人工审核模型可能在用户没说自己是糖尿病患者时就直接跳过了这条规则。这不是模型不聪明而是规则是硬性约束不适合交给概率模型去执行。策略编排层就是把这些硬规则从模型里剥离出来用代码实现用配置管理全流程可审计。3.2 策略编排核心结构流程模板 节点执行器我实现的策略引擎思路很直白每个业务流程定义成一个模板模板里挂载一串节点节点类型有工具调用、条件判断、人工审核、消息回复。引擎按顺序执行节点根据条件判断结果决定走哪条分支。# strategy_engine.py import json from typing import List, Dict, Any class StrategyNode: 策略流程中的节点 def __init__(self, node_id: str, node_type: str, config: Dict[str, Any]): self.node_id node_id self.node_type node_type # tool / condition / approval / reply / finish self.config config class StrategyEngine: 策略编排引擎 def __init__(self, strategies: Dict[str, List[StrategyNode]]): self.strategies strategies self.context: Dict[str, Any] {} def execute(self, strategy_name: str, initial_context: Dict[str, Any]) - Dict[str, Any]: 执行指定策略流程 self.context initial_context nodes self.strategies.get(strategy_name, []) current_index 0 max_steps len(nodes) * 3 # 防止意外死循环 while current_index len(nodes) and max_steps 0: node nodes[current_index] max_steps - 1 if node.node_type tool: # 执行工具调用从config中读取工具名和参数映射 tool_name node.config[tool_name] param_map node.config.get(param_map, {}) # param_map把context中的字段映射到工具参数 tool_args {k: self.context.get(v) for k, v in param_map.items()} result TOOL_REGISTRY[tool_name][function](**tool_args) result_obj json.loads(result) # 工具结果写入上下文供后续节点使用 for key, val in result_obj.items(): self.context[node.config.get(result_key, key)] val current_index 1 elif node.node_type condition: # 条件判断按expr表达式返回true/false决定跳转 expr node.config[expr] target_if_true node.config[target_if_true] target_if_false node.config[target_if_false] # 支持简单的表达式语言实际项目中可扩展为规则引擎 if self._eval_expr(expr): current_index target_if_true else: current_index target_if_false elif node.node_type approval: # 人工审核节点调用审批系统API创建任务 approval_system_url node.config.get(approval_url, ) # 实际项目中这里会POST一个审批请求到OA系统 self.context[approval_required] True self.context[approval_node] node.node_id break # 触达人工节点后流程暂停 elif node.node_type reply: # 生成回复内容支持模板渲染 reply_template node.config[template] # 简单模板替换把context中的值填进模板 reply_text reply_template for key, val in self.context.items(): reply_text reply_text.replace(f{{{{{key}}}}}, str(val)) self.context[final_reply] reply_text current_index 1 elif node.node_type finish: break return self.context def _eval_expr(self, expr: str) - bool: 求值条件表达式比如 claim_amount 50000 # 实际项目中可以用更安全的AST方案这里简化处理 left, op, right expr.split() left_val self.context.get(left, 0) right_val float(right) if op : return float(left_val) right_val if op : return float(left_val) right_val if op : return float(left_val) right_val if op : return float(left_val) right_val if op : return float(left_val) right_val return False3.3 策略配置化业务人员也能维护流程光有引擎还不够关键是策略配置得可视化、可维护。我的做法是用JSON描述流程模板这样业务人员通过管理后台就能调整流程不用动代码。{ strategy_name: claim_approval, description: 理赔申请审批流程, nodes: [ { node_id: 1, node_type: tool, config: { tool_name: query_policy, param_map: {policy_id: policy_id}, result_key: policy_info } }, { node_id: 2, node_type: tool, config: { tool_name: calculate_claim, param_map: {policy_id: policy_id, claim_amount: claim_amount}, result_key: claim_result } }, { node_id: 3, node_type: condition, config: { expr: claim_amount 50000, target_if_true: 5, target_if_false: 4 } }, { node_id: 4, node_type: reply, config: { template: 您好您的理赔申请预估可赔付金额为{{claim_amount}}元已为您自动提交预计3个工作日内完成审核。 } }, { node_id: 5, node_type: approval, config: { approval_url: http://approval-system.internal/create_task } } ] }这个配置表达的意思很清晰先查保单再算理赔金额如果金额超过5万就走人工审批流程暂停否则自动通过并回复用户。整个过程有明确的状态流转记录什么时候调的什么工具、结果是什么、命中了什么条件、卡在哪个节点全部可追溯。这在金融业务里是硬性要求——事后审计说不清楚当时为什么这么处理是要出问题的。策略编排层的价值说白了就是把模型能做和业务允许做这两件事分开。模型可以自由组织语言、理解意图但涉及钱、涉及合规、涉及风控的判断必须走确定性流程。4. 端到端流程串联一个完整的车险理赔咨询案例前面把各部分都拆开讲了这节完整走一遍流程让你看到从用户说话到最终办完事的全链路长什么样。4.1 会话入口识别意图并推送保单选单用户在小程序里输入我上周开车追尾了对方保险杠坏了要修我有商业险这个能赔吗对话服务收到消息后先做意图识别和实体抽取。这里不单独训练意图模型直接依赖大模型的函数调用能力完成。系统在工具列表里放了三个候选工具query_policy查保单、submit_claim提交理赔、query_claim_progress查理赔进度。模型读取用户消息后判断出这是在问能不能赔属于理赔咨询场景。模型返回工具调用请求query_policy(policy_idP20240001)——注意保单号是从用户档案中带出并拼进上下文的用户不需要自己输入。工具执行后返回保单状态模型发现保单有效给出的答复是根据您的保单P20240001您投保了机动车商业险包含第三者责任险和车损险此事故属于保险责任范围可以申请理赔。是否现在为您提交理赔申请到这里第一轮对话完成用户知道能赔也拿到了下一步动作的引导。4.2 理赔提交工具调用策略编排的完整协作用户回复是的提交理赔申请。这时系统先触发一次calculate_claim工具根据用户填写的损失金额、事故责任比例等信息做一个预计算输出预估赔付金额15000元。预计算完成后工具结果被写入策略引擎的上下文。策略引擎读取claim_approval流程模板按模板顺序执行节点1查保单确认保单有效节点2算理赔金额得到15000元节点3条件判断claim_amount 50000结果是15000小于50000走target_if_false到节点4节点4生成回复模板返回预估赔付金额15000元已自动提交预计3个工作日内完成审核。这些节点的执行状态全部落库审计时可完整还原。4.3 人工介入场景金额超限后的审批挂起再对比一个场景同样的流程但用户输入的理赔金额是80000元。策略引擎走完节点1和节点2后到了节点3条件判断80000 50000为真跳转到节点5即approval节点。引擎调用审批系统API创建一个审批任务推送给理赔复核团队。流程状态变为挂起待人工处理。这时模型该怎么回应用户这不是策略引擎管的事而是模型层根据策略引擎返回的状态信息组织话术。模型说您的理赔申请金额超过5万元按公司风控规定需人工复核已为您提交至审核团队预计1个工作日内有审核人员与您联系。用户端看到的是顺畅的对话背后是流程的暂停和人工介入。这就是策略编排层存在的意义——模型可能答非所问但流程永远不会走错。5. 实际落地中的踩坑记录与调优经验这节是我最想写的部分。方案设计得再好落地时全是细节坑。我按真实性排序分享几个印象最深的。5.1 工具参数幻觉模型生成的参数不靠谱第一个坑是模型编造工具参数。有次测试用户说我买的那个什么健康险帮我查一下模型竟然直接调用了query_policy还自动填了一个policy_id当然这个ID在系统里根本不存在。排查下来发现模型的工具参数是生成式输出的不是选择式输出的天然存在幻觉风险。不能假设模型填的参数一定对在工具调用入口必须做一层参数校验和补全逻辑枚举类参数性别、险种名称必须严格匹配不能有模糊值数值类参数要做范围和类型校验比如年龄不能是负数保额不能超过产品上限关键业务参数要从用户画像或会话上下文中去取而不是完全依赖模型生成。保单号这种系统能从绑定的用户档案里读出来就不要让模型自己填。这个校验层我放在工具执行之前参数过不了校验就直接返回错误信息给模型并附上正确的取值让模型重新组织追问。5.2 上下文污染一个工具的结果影响了另一个工具的判断遇到的第二个坑比较隐蔽。有一次用户连续问了两个问题先问车险理赔又问那你们那个重疾险能保什么病模型在处理第二个问题时把车险理赔查到的保单信息混进了上下文回答里出现了根据您的车险保单重疾险保障覆盖...这种低级错误。问题的根源在于工具调用结果会随着对话历史持续保留模型在相关性和优先级判断上出了错。解决思路有几个我用了组合拳系统级提示词里加入每个新问题都是独立的请基于当前问题和当前查询结果回答会话管理中标记每轮工具结果的时间戳和归属话题构建结构化历史而不是纯文本拼接在工具调用前增加相关性判断环节模型先判断当前问题是否需要工具如果需要再判断是复用前面的结果还是重新调用。效果不能说100%解决问题但明显减少了串味的情况。工具调用型Agent的上下文管理比普通对话机器人要复杂得多。5.3 审校机制大模型不能直接面向用户输出金融行业有一条铁律面向用户的输出必须经过审校不能让模型裸奔。我实现了一个双通道审校机制第一层是合规词表扫描。系统内置一个敏感词和违规表述词表模型输出的文本先过一遍这个过滤器命中就拦截并改写。第二层是事实核验。针对工具结果中带出的数值类信息在最终回答渲染前做一次严格匹配。模型生成的文本里提到的金额、日期、保单状态必须和工具结果一致不一致就重新生成或者直接报错。这个机制上线当天就拦下来一次事故模型在回答理赔金额时把赔付15000元写成了赔付150000元多了一个零。要不是审校拦住了这种回复发到用户手机上公司那边得炸锅。注意审校机制要有兜底提示不能无限重试。我设的规则是审校失败两次后放弃生成改用预设话术系统正忙已为您转接人工服务。宁可少一次自动回复也不发一条错误信息。5.4 性能与延迟工具调用链路比想象中耗时工具调用模式的延迟比纯问答高一大截。纯问答一次模型请求就够了工具调用通常要两到三次请求第一次模型返回工具调用指令第二次执行工具第三次模型根据结果生成回答。每次模型调用500到1500毫秒不等整条链路下来用户等上三秒很常见。金融咨询场景三秒能接受但再往上用户就流失了。我做了三个优化模型参数上把温度调到0.1降低输出长度上限让模型调用工具的决策更快工具执行采用并行策略无依赖关系的工具同时跑之前提过的那个例子从三次串行调用降为两次对一些高频固定场景比如查保单直接跳过模型生成工具指令的过程用规则匹配提前锁定工具调用把第一次模型请求省掉。实测下来优化后平均响应时间从3.8秒降到了2.1秒体感上流畅了不少。6. 常见问题排查与避坑速查表有段时间天天在群里解答类似问题干脆整理成速查表遇到问题照着排查就行。问题现象可能原因排查与解决办法模型完全不调用工具直接生成回答工具描述中触发条件不明确或模型版本不支持函数调用检查工具描述是否包含明确触发词确认模型接口参数里传了tools字段模型调用了错误的工具工具间描述存在语义重叠细化每个工具的使用场景和禁用场景对高频易混工具加上互斥注释工具参数频繁报错模型生成的参数格式和schema不一致在工具执行前增加参数校验层对数值参数做类型强转对缺失必填参数要求模型补充工具执行成功但模型回答错误上下文拼接顺序问题工具结果被淹没在历史消息中调整消息结构把最近一次工具结果放在最靠近最后一条消息的位置或使用摘要机制连续工具调用死循环工具返回结果触发了模型再次调用同一工具设置最大调用次数上限在工具返回信息中增加已尝试次数让模型知道要改变策略用户等待时间过长多轮工具调用串行执行分析工具依赖关系独立工具改为并行调用对高频场景做规则前置跳过第一次模型决策模型输出含违规或错误数据缺乏审校机制上线合规词表过滤和数值核验模块设置审校失败自动转人工策略流程卡在审批节点不动审批状态未同步回对话系统增加审批状态轮询回调机制审批通过后自动唤醒会话继续流程7. 这个项目的进一步扩展方向主流程跑通后后续扩展我打算重点做两件事。一件事是策略配置的可视化。目前JSON配置虽然不用改代码但业务人员上手还是有门槛。后面计划做成拖拽式流程编排界面节点即模块连线即流转让业务同学自己就能调整策略不需要研发介入。另一件事是引入多轮策略动态路由。现在策略模板在会话过程中是固定的但实际业务里用户可能中途改变了需求——从查理赔进度变成投诉流程应该能动态切换到投诉处理策略。这个需要策略引擎支持会话级的状态感知和策略重定位是一个有价值但工程量不小的改造。保险金融的智能化目前还没到全自动那一步但把大模型的对话能力、工具调用的执行能力、策略编排的控制能力结合起来已经能做出一套既智能又合规的业务办理系统。未来模型能力会更强工具生态会更丰富但分层架构的思路不会变——让该灵活的灵活让该可控的可控。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑