资讯详情

从零搭建保险智能体:知识库构建与核保辅助实战

📅 2026/10/12 6:30:51 | 华诺云谱 👁 阅读
从零搭建保险智能体:知识库构建与核保辅助实战
1. 从零搭建一个保险智能体我踩过的坑和最终跑通的方案去年年底我接手了一个内部创新项目目标很明确做一个能真正帮上忙的保险智能体。不是那种只会念条款的问答机器人而是能理解用户模糊需求、能对比产品、能辅助核保、甚至能给出配置建议的“数字顾问”。说实话刚开始我觉得这事不难不就是把大模型接上保险知识库嘛。但真正动手之后才发现保险这个领域的复杂度远超我的预期——条款嵌套、责任免除、等待期、现金价值、核保规则每一个环节都是坑。我前后迭代了四个版本从最初的“人工智障”到后来能稳定处理八成以上的常见咨询中间积累了不少实战经验。这篇文章就把整个开发过程拆开揉碎讲清楚包括架构选型、知识库构建、意图识别、对话管理、核保辅助这些核心模块的实现思路和具体代码。如果你也在做垂直领域的智能体或者对保险科技感兴趣这篇记录应该能帮你省下不少试错时间。1.1 为什么保险场景对智能体这么不友好先说说保险这个领域的特殊性。普通电商客服机器人用户问“这个多少钱”“什么时候发货”意图非常明确槽位也好抽取。但保险咨询完全是另一回事。用户会说“我想给刚出生的孩子买个保险预算一年五千左右最好能保大病”这一句话里包含了被保人年龄、预算范围、保障需求、产品类型四个关键信息而且“大病”这个词在保险语境下可能指重疾险、医疗险、或者特定疾病险需要进一步澄清。更麻烦的是保险产品的条款是法律文本同一个词在不同产品里的定义可能完全不同。比如“意外伤害”有的产品要求“外来的、突发的、非本意的、非疾病的”有的还会把高风险运动除外。如果智能体直接拿通用大模型来回答很容易给出看似正确但实际有偏差的建议这在保险场景里是致命的。我一开始就犯了这个错误。第一版直接调了一个通用大模型接口把产品条款塞进提示词里让它回答。测试的时候问“等待期内生病能赔吗”它回答“等待期内生病通常不能理赔具体以合同为准”。这个回答本身没错但太笼统了。用户真正想知道的是我买的这个产品等待期是多久等待期内确诊但等待期后住院能不能赔这些问题需要精确到条款细节。通用模型在没有结构化知识支撑的情况下只能给出模糊的通用答案无法满足实际需求。所以第二版我开始构建专门的知识库。这里又遇到一个选择是用向量数据库做语义检索还是用图数据库做关系推理我最后选了混合方案。向量检索负责从海量条款中快速找到相关段落图数据库负责处理产品之间的对比关系和核保规则链。这个决策后面会详细展开。1.2 整体架构三层解耦的设计思路经过几轮迭代最终跑通的架构分成三层。最底层是知识层包含产品条款库、核保规则库、疾病定义库、理赔案例库四个子库。中间层是能力层包括意图识别、槽位填充、知识检索、推理引擎、对话管理五个模块。最上层是交互层负责多轮对话、澄清追问、结果呈现。三层之间通过标准接口通信每一层都可以独立替换和升级。为什么这么设计因为保险业务变化太快。今天出一个新产品明天调整一个核保规则如果架构是铁板一块每次改动都要动全身。解耦之后知识层更新不影响能力层的逻辑能力层升级也不影响交互层的体验。举个例子后来我们把核保规则从硬编码改成规则引擎配置只动了知识层和推理引擎的接口对话管理模块完全不用改。具体到技术选型知识层我用的是PostgreSQL加pgvector扩展存向量Neo4j存产品关系图。能力层用Python写核心逻辑意图识别用微调后的BERT模型槽位填充用规则加模型混合方案。交互层用FastAPI提供接口前端用React做对话界面。整个系统跑在一台16核64G的服务器上日均处理咨询量在两千左右响应时间控制在1.5秒以内。注意不要一上来就追求大而全的架构。我见过不少团队一开始就设计微服务、消息队列、分布式缓存结果开发两周还在调通链路。保险智能体的核心难点在知识处理和推理逻辑架构够用就行先把核心流程跑通再考虑扩展。2. 知识库构建从PDF条款到结构化知识的完整流程知识库是整个智能体的地基。地基不牢上面盖什么都是危房。我在这上面花了将近一半的开发时间现在回头看每一分钟都值得。2.1 条款解析为什么直接OCR不够用保险条款通常是PDF格式几十页到上百页不等。第一反应肯定是OCR提取文字但直接OCR出来的文本是一大坨没有层级结构。条款里有章、节、条、款、项还有各种表格和附件。如果只是把纯文本塞进向量库检索出来的片段可能缺上下文导致理解偏差。我的做法是先用PDF解析库提取带坐标的文本块然后根据字体大小、加粗、缩进这些排版特征重建层级结构。具体来说标题通常字号大且加粗条款正文有固定缩进表格有独立的边框识别。解析完之后每个条款变成一个JSON对象包含条款编号、标题、正文、所属章节、关联条款这些字段。# 条款解析核心逻辑示意 import pdfplumber from collections import defaultdict def parse_policy_pdf(pdf_path): clauses [] with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: # 提取文本块及其字体信息 words page.extract_words(extra_attrs[fontname, size]) # 按行分组 lines group_by_line(words) for line in lines: # 根据字体大小判断是否为标题 if is_heading(line): current_section line[text] # 根据缩进和编号识别条款 elif is_clause(line): clause extract_clause(line, current_section) clauses.append(clause) return build_hierarchy(clauses)这里有个关键点条款之间的引用关系必须保留。比如“本条款适用第3.2条约定”如果解析时丢了这个引用后续推理就会断链。我的处理方式是在解析阶段就抽取所有“第X条”“第X款”这样的引用标记存成图数据库的边。这样当用户问到某个条款时系统能自动把关联条款一起检索出来。2.2 向量化策略不是所有文本都值得嵌入条款解析完之后下一步是向量化。这里我踩过一个坑一开始把所有条款不分青红皂白全部嵌入结果检索效果很差。因为有些条款是通用说明比如“本合同未尽事宜按相关法律法规处理”这种条款跟用户问题相关性很低但向量相似度可能不低反而挤占了真正相关条款的位置。后来我做了分层处理。核心条款——也就是定义、保障责任、责任免除、等待期、理赔流程这些——做精细嵌入每个条款单独一个向量。辅助条款——比如通知义务、合同变更、争议处理——做摘要后嵌入降低权重。通用条款直接不入向量库只在需要时通过图关系检索。嵌入模型的选择也折腾了一阵。最开始用通用中文嵌入模型发现对保险术语的区分度不够。“重疾险”和“医疗险”在通用模型里向量距离很近但在保险场景里这是两个完全不同的品类。后来我用保险领域的问答对做了微调让模型学会区分这些专业概念。微调数据大概三千条都是人工标注的“问题-相关条款”对。微调之后检索准确率从百分之六十七提升到了百分之八十九。2.3 核保规则库把Excel变成可执行逻辑核保是保险智能体最有价值的场景之一。用户输入年龄、性别、健康状况系统判断能不能保、以什么条件保。传统做法是核保员查手册智能体要做的是把手册变成可执行的规则。原始资料是一堆Excel表格行是疾病列是核保结论。但直接读Excel不行因为规则之间有依赖关系。比如“高血压”的核保结论取决于血压值、是否服药、有无并发症这些子条件又各自有判断逻辑。我的做法是先把Excel转成决策表再人工梳理成决策树最后用规则引擎表达。# 核保规则示例高血压核保逻辑 def underwrite_hypertension(applicant): bp_systolic applicant[blood_pressure_systolic] bp_diastolic applicant[blood_pressure_diastolic] on_medication applicant[on_medication] complications applicant[complications] if bp_systolic 140 and bp_diastolic 90: return {result: standard, reason: 血压正常范围} elif bp_systolic 160 and bp_diastolic 100: if not on_medication and not complications: return {result: standard, reason: 轻度高血压无并发症} elif on_medication and not complications: return {result: substandard, reason: 服药控制中需加费} else: return {result: decline, reason: 高血压伴并发症} else: return {result: decline, reason: 血压超出可保范围}这套规则引擎跑起来之后常见疾病的核保判断准确率能达到百分之九十五以上。但要注意规则引擎只能处理明确的条件遇到模糊描述比如“医生建议进一步检查”就需要转人工。我在系统里设了置信度阈值低于阈值的自动转人工核保员避免误判。实操心得核保规则库一定要版本化。保险公司的核保政策可能每季度调整如果没有版本管理某天更新了规则但没记录出了问题根本查不到原因。我用Git管理规则文件每次变更都有commit记录线上出问题能快速回滚。3. 对话引擎让智能体听懂“人话”的核心逻辑知识库建好之后下一个难题是怎么让用户自然地提问系统准确地理解。保险咨询的特点是用户表达非常口语化而且经常省略关键信息。对话引擎要做的就是把这些模糊表达翻译成结构化查询。3.1 意图识别从“我想买保险”到具体需求用户说“我想买保险”这句话的意图是什么可能是想了解产品可能是想对比价格可能是想直接投保。如果系统直接推荐产品很可能不是用户想要的。我的做法是把意图分成三层第一层是动作意图比如咨询、对比、投保、理赔第二层是对象意图比如重疾险、医疗险、意外险第三层是约束意图比如预算、年龄、健康状况。意图识别模型用的是BERT微调。训练数据来自历史客服对话记录人工标注了五千条。这里有个技巧不要只标注最终意图要把中间澄清过程也标注进去。比如用户先说“我想买保险”客服追问“您想给谁买”用户回答“给孩子”这个追问-回答对也是训练数据。这样模型不仅学会识别意图还学会在信息不足时主动追问。# 意图识别输出示例 { action_intent: consult, object_intent: critical_illness, constraints: { insured_age: 0, budget: 5000, payment_period: 20年 }, confidence: 0.92, missing_slots: [health_condition] }当置信度低于阈值或者关键槽位缺失时对话引擎会触发澄清追问。追问的话术也经过设计不能太生硬。比如不会直接问“请提供健康状况”而是说“为了给您更准确的建议方便告诉我被保人有没有既往病史吗”。3.2 多轮对话管理状态追踪与上下文继承保险咨询很少是一问一答就结束的。用户可能先问重疾险再问医疗险然后对比两者最后回到重疾险问具体条款。对话引擎必须记住整个会话的上下文不能每轮都从零开始。我用的是基于状态机的对话管理。每个会话有一个状态对象记录当前讨论的产品、已收集的槽位、历史意图。当新消息进来时先做意图识别和槽位填充然后根据当前状态决定下一步动作。动作空间包括直接回答、澄清追问、推荐产品、对比展示、转人工。class DialogState: def __init__(self): self.current_product None self.collected_slots {} self.history [] self.turn_count 0 def update(self, user_input, nlu_result): self.history.append({ user: user_input, nlu: nlu_result, timestamp: time.time() }) # 继承上一轮的槽位 for slot, value in nlu_result.get(slots, {}).items(): if value is not None: self.collected_slots[slot] value # 更新当前讨论产品 if nlu_result.get(object_intent): self.current_product nlu_result[object_intent] self.turn_count 1这里有个细节槽位继承要有优先级。如果用户这轮明确说了“预算一万”那就覆盖上一轮的“预算五千”。但如果这轮没提预算就保留上一轮的值。我一开始没做优先级判断导致用户改了口径系统还在用旧值闹了不少笑话。3.3 回复生成模板加模型的双轨制回复生成这块我试过纯模型生成和纯模板两种方案最后选了混合。纯模型生成灵活但不可控保险场景里说错一句话可能引发合规问题。纯模板可控但生硬用户体验差。我的方案是核心信息用模板保证准确性过渡语句用模型生成保证自然度。比如推荐产品时产品名称、保障责任、保费这些关键信息从知识库直接填充模板而“根据您的情况我建议...”这样的引导语由模型生成。这样既保证了信息准确又让对话不那么机械。def generate_response(intent, slots, knowledge): # 核心信息模板 if intent recommend: products knowledge[products] template 根据您{constraints}的情况我筛选了{count}款产品\n for p in products: template f- {p[name]}{p[feature]}参考保费{p[premium]}元/年\n template 您想详细了解哪一款 return template.format(**slots) # 过渡语句由模型生成 elif intent clarify: prompt f用户问了一个保险问题需要澄清{slots[missing_slot]}请用友好的语气追问。 return model.generate(prompt)注意保险智能体的所有输出都必须经过合规过滤。我建了一个敏感词库包含“保证收益”“肯定赔”“最好”这类违规表述生成结果先过一遍过滤器再返回。这个步骤不能省否则可能给公司带来监管风险。4. 核保辅助与产品对比两个高频场景的落地细节对话引擎跑通之后我重点打磨了两个高频场景核保辅助和产品对比。这两个场景用户需求最强烈也最能体现智能体的价值。4.1 核保辅助从问卷到预核保结论核保辅助的流程是这样的用户输入基本信息系统逐步追问健康状况最后给出预核保结论。听起来简单但实现起来有几个难点。第一个难点是疾病描述的标准化。用户说“我血糖有点高”这可能是空腹血糖受损也可能是糖尿病。系统需要追问具体数值和诊断情况。我建了一个疾病同义词库把口语化描述映射到标准疾病名称然后再走核保规则。第二个难点是追问逻辑。不是所有疾病都需要追问所有细节。比如用户说“做过阑尾炎手术”系统只需要确认手术时间、是否痊愈、有无并发症不需要问家族史。我根据疾病类型预设了追问模板每种疾病对应一组必问问题。# 疾病追问模板示例 FOLLOW_UP_TEMPLATES { hypertension: [ {question: 最近一次测量的血压值是多少, slot: bp_value}, {question: 是否在服用降压药, slot: on_medication}, {question: 有没有出现心脑血管并发症, slot: complications} ], diabetes: [ {question: 确诊多久了, slot: diagnosis_duration}, {question: 最近一次空腹血糖是多少, slot: fasting_glucose}, {question: 是否使用胰岛素, slot: insulin_usage} ] }第三个难点是结论解释。核保结论不能只给一个“加费”或“拒保”要说明原因。比如“因高血压伴并发症本次投保需加费百分之三十”这样用户才能理解。我在规则引擎里加了原因字段每个判断节点都记录推理路径最后生成解释文本。实测下来常见疾病的预核保准确率在百分之九十以上用户满意度比纯人工核保高不少因为智能体可以二十四小时在线而且追问过程比人工更耐心。4.2 产品对比多维度打分与可视化呈现产品对比是另一个高频需求。用户通常会说“我想对比一下A产品和B产品”但直接列条款对比用户看不懂。我的做法是先提取对比维度然后按用户关注点加权打分最后用表格和图表呈现。对比维度包括保障范围、保费、等待期、免赔额、赔付比例、续保条件、增值服务。每个维度从知识库提取数据然后归一化打分。权重根据用户需求动态调整。比如用户说“我最看重保费”那保费维度权重就调高。def compare_products(product_a, product_b, user_weights): dimensions [coverage, premium, waiting_period, deductible, reimbursement_ratio, renewal] scores {} for dim in dimensions: score_a normalize(product_a[dim], dim) score_b normalize(product_b[dim], dim) weight user_weights.get(dim, 1.0) scores[dim] { product_a: score_a * weight, product_b: score_b * weight, winner: A if score_a score_b else B } return scores呈现方式上我用表格展示各维度对比用雷达图展示综合得分。用户一眼就能看出哪款产品更符合自己的需求。这里有个细节对比结果不能只说“A更好”要说明“在您关注的保费维度上A比B低百分之十五但等待期长三十天”。这样用户才能做权衡。实操心得产品对比功能上线后我发现用户最喜欢的是“一键对比”按钮。用户不需要手动输入产品名称系统根据之前的对话自动推荐对比对象。这个功能让对比功能的使用率提升了三倍。5. 常见问题与排查技巧实录开发过程中遇到的问题五花八门我挑几个典型的整理成速查表方便遇到类似情况时快速定位。5.1 知识检索不准确怎么办这是最常见的问题。用户问“等待期生病能赔吗”系统检索出来的却是“等待期定义”而不是“等待期出险处理”。排查思路如下问题现象可能原因排查方法解决方案检索结果不相关嵌入模型区分度不够人工评估Top10结果微调嵌入模型相关条款排在后位向量权重未分层检查条款权重配置核心条款提高权重检索结果缺上下文切片粒度太细检查切片大小按条款完整切片多义词导致偏差未做词义消歧分析查询词增加同义词映射我遇到最典型的一次是用户问“猝死能赔吗”系统检索出来的是“意外身故”条款。原因是“猝死”在医学上属于疾病范畴但用户可能认为它是意外。后来我在知识库里加了“猝死”的专门条目明确说明它通常不属于意外险保障范围但部分产品有特别约定。这个问题才解决。5.2 多轮对话中槽位丢失用户在第一轮说了“预算五千”第三轮系统却问“您的预算是多少”。这种问题通常是状态管理出了bug。排查步骤先看会话状态对象是否在每轮正确更新再看槽位继承逻辑是否有覆盖问题最后检查是否有并发请求导致状态错乱。我的解决方案是给会话状态加版本号每次更新递增。如果发现版本号跳跃说明有并发写入需要加锁。另外槽位继承我改成了“显式覆盖”模式只有用户明确说了新值才覆盖否则保留旧值。5.3 核保规则冲突不同疾病之间的核保规则可能冲突。比如用户既有高血压又有糖尿病单独看每个疾病都符合标准体但组合起来风险倍增应该加费。我一开始没处理组合规则导致核保结论偏松。后来我在规则引擎里加了组合规则层。先跑单病种规则如果都是标准体再跑组合规则。组合规则是一个矩阵行和列都是疾病交叉点是组合核保结论。这个矩阵由核保专家维护我负责把它变成可执行代码。5.4 回复内容合规风险保险智能体最怕的是说了不该说的话。比如用户问“这个产品收益怎么样”如果系统回答“收益很高”就涉嫌误导。我的做法是建三层过滤第一层是敏感词过滤第二层是语义合规检查第三层是人工抽检。敏感词过滤比较简单维护一个词库就行。语义合规检查用一个小模型判断回复是否包含承诺性表述。人工抽检每天随机抽一百条对话由合规同事审核。三层过滤下来合规风险基本可控。注意合规过滤不能只做一次。我见过有的系统只在生成时过滤但用户追问时又绕过了。正确的做法是在每个输出节点都加过滤确保任何返回给用户的内容都经过检查。6. 上线后的效果与后续优化方向系统上线三个月日均处理咨询两千三百条独立解决率百分之七十八用户满意度四点六分满分五分。核保辅助模块的预核保准确率百分之九十一产品对比功能使用率百分之六十三。这些数据比我预期的好但也有很多可以优化的地方。目前最大的瓶颈是复杂案例的处理。比如用户有多个既往症或者涉及多个产品的组合配置系统还是需要转人工。下一步我打算引入更强的推理能力把图数据库的查询能力用得更充分让系统能处理更复杂的规则链。另一个优化方向是个性化。现在的推荐逻辑还是基于规则和通用模型没有充分利用用户的历史行为数据。如果能把用户之前的咨询记录、浏览记录、投保记录都纳入进来推荐会更精准。但这涉及数据隐私和合规问题需要谨慎设计。最后分享一个小技巧智能体的对话日志是非常宝贵的资产。我每周会抽半天时间看用户和智能体的真实对话把失败的案例整理成测试集用来迭代模型和规则。这个习惯坚持了三个月系统的解决率从最初的百分之五十二提升到了百分之七十八。很多时候优化方向就藏在那些失败的对话里。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑