保险行业 AI 落地——理赔审核的工程挑战
保险行业 AI 落地——理赔审核的工程挑战
适读人群:做企业 AI 落地的工程师,对金融/保险行业感兴趣的开发者
阅读时长:约 23 分钟
文章价值:理赔 AI 的合规工程实践 + 多模态处理方案 + 完整代码实现
一次不愉快的演示
我职业生涯里最难熬的一次客户演示,发生在一家保险公司。
那天我们演示 AI 理赔审核系统,给客户方的产品经理、IT 负责人、还有一位法务人员看。前二十分钟进行得很顺利——准确率 89%,处理速度从平均 3 天压缩到 4 小时,客户频频点头。
然后法务开口了:「如果 AI 拒绝了一个客户的理赔,客户要求知道拒绝原因,你们的系统能给出可追溯的、有法律效力的解释吗?」
我卡了五秒钟。
技术层面我知道答案:我们的 LLM 给出了分析文本,理论上可以作为解释。但法律层面,「LLM 说的话」能不能作为拒赔依据?万一 LLM 的判断有偏见怎么办?这些问题我根本没想过。
演示没有失败,但合同签了三个月后。这三个月里,我重新设计了整个系统的合规框架。
这篇文章,就是这次教训的系统整理。
保险理赔 AI 的特殊性:比你想象的复杂
合规是一等公民,不是可选项
大多数行业,AI 准确率高就是好系统。保险行业不一样。保险受到严格的法律监管,理赔决策必须:
可解释:每一个理赔决定,必须能向客户解释「为什么」,这个解释必须基于具体的证据和条款,不能是「AI 认为」这种描述。
可审计:监管机构随时可能来检查,系统必须记录每一次决策的完整过程,包括使用了哪些数据、参考了哪些条款、人工在哪个环节介入。
无歧视:AI 不能因为客户的性别、地区、年龄等因素系统性地影响理赔判断(这是真实存在的 AI 偏见风险,不是假设)。
我见过一个保险公司的案例:他们的 AI 系统在某个地区的拒赔率比其他地区高出 30%,后来发现是因为训练数据里这个地区的欺诈案例比例偏高,导致模型对这个地区产生了系统性偏见。这种问题如果上线后才发现,后果很严重。
多模态数据是这个行业的常态
一个车险理赔案件,可能包含:
- 事故现场照片(多张,不同角度)
- 交警事故认定书(PDF 扫描件)
- 维修报价单(图片或 PDF)
- 行车记录仪视频(有时候)
- 客户书面陈述(Word 文档)
- 历史保单信息(结构化数据)
- 医疗证明(针对人身险,PDF 或图片)
这些数据格式各异,信息分散,需要 AI 系统综合理解,不能只看其中一部分。
欺诈识别是绕不开的核心需求
保险行业的 AI,欺诈检测是重要需求。据行业数据,保险欺诈占理赔金额的 10%-15%,每年损失以亿计。AI 的一个核心价值就是发现人工审核难以发现的欺诈模式。
但欺诈识别有一个棘手的问题:你不能因为 AI 怀疑就拒赔,这在法律上站不住脚。 AI 只能做「怀疑」的标注,把可疑案件推给人工做深入核查,不能直接做出拒赔决定。
这个业务约束,深刻影响了系统架构的设计。
系统架构:人机协作是核心设计原则
保险理赔 AI 的架构,不能是「AI 做决定,人看结果」,而必须是「AI 做分析,人做决定,全程留痕」。
这个架构有几个关键设计决策:
AI 只出「审核报告」,不出「理赔决定」
系统生成的是「AI 分析报告」,包含:材料符合度、可疑点列表、相关条款引用、欺诈风险评分、建议赔付金额(仅供参考)。最终的理赔决定,必须由有资质的审核员签字确认。
这不是技术能力的问题,而是合规的要求。AI 分析报告作为辅助材料,审核员的签字作为法律依据,两者共同构成可追溯的决策链。
分级处理降低人工成本
低风险案件(材料完整、没有可疑点、历史记录良好)走快速通道,审核员只需确认 AI 报告;高风险案件由资深人员处理。这样既保证了合规,又把人工资源集中在真正需要判断的地方。
多模态理解的工程实现
理赔材料的多模态处理是技术难点。我们的处理流程分三层:
第一层:文档解析和 OCR
保险单证很多是扫描件,质量参差不齐。有些交警认定书是手写的,有些维修单子是打印但被折叠过的,有些医疗证明分辨率很低。
我们用的是分层 OCR 策略:先用轻量级 OCR 处理,如果置信度低于阈值,再用质量更高但更慢的模型重处理,对特定类型文件(如手写内容)用专门的手写识别模型。
第二层:图像内容分析
车险的事故现场照片,需要 AI 判断:
- 损伤部位和损伤程度
- 损伤与事故描述是否吻合
- 是否存在明显的人为修改痕迹
- 照片元数据是否与事故时间地点一致
这里有一个细节:照片的 EXIF 数据(拍摄时间、GPS 坐标)是重要的核验线索,但有些欺诈案件会修改 EXIF,所以不能完全依赖 EXIF,要和内容分析结合。
第三层:信息融合和一致性核查
把不同来源的信息融合起来,检查一致性。比如:
- 事故认定书上的车辆损伤描述,和现场照片是否一致
- 维修报价的零件,和照片里的损伤部位是否匹配
- 客户陈述的事故时间,和行车记录仪时间是否一致
这一层的不一致,往往就是可疑点的来源。
代码实现:Spring AI 理赔文档分析
下面是核心的理赔文档分析服务,用 Spring AI 实现,包含多模态处理和结构化输出。
@Service
public class ClaimsDocumentAnalysisService {
private final ChatClient chatClient;
private final VectorStore policyVectorStore;
private final DocumentParser documentParser;
private final FraudRiskEvaluator fraudEvaluator;
public ClaimsDocumentAnalysisService(
ChatClient.Builder chatClientBuilder,
@Qualifier("policyVectorStore") VectorStore policyVectorStore,
DocumentParser documentParser,
FraudRiskEvaluator fraudEvaluator) {
this.chatClient = chatClientBuilder
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
this.policyVectorStore = policyVectorStore;
this.documentParser = documentParser;
this.fraudEvaluator = fraudEvaluator;
}
/**
* 理赔材料综合分析,生成审核报告
*/
public ClaimsAuditReport analyzeClaimsDocuments(ClaimsCase claimsCase) {
// 1. 解析所有文档
ParsedDocuments parsedDocs = documentParser.parseAll(claimsCase.getDocuments());
// 2. RAG:检索相关保险条款
List<Document> relevantClauses = retrieveRelevantClauses(claimsCase, parsedDocs);
// 3. 核心分析:用LLM做综合审核
String analysisResult = performCoreAnalysis(claimsCase, parsedDocs, relevantClauses);
// 4. 欺诈风险独立评估(不依赖LLM,用规则+ML模型)
FraudRiskScore fraudScore = fraudEvaluator.evaluate(claimsCase, parsedDocs);
// 5. 整合生成审核报告
return buildAuditReport(claimsCase, analysisResult, fraudScore, relevantClauses);
}
private List<Document> retrieveRelevantClauses(
ClaimsCase claimsCase, ParsedDocuments parsedDocs) {
// 构建条款查询:基于险种、事故类型、涉及项目
String clauseQuery = String.format(
"保险理赔条款 险种:%s 事故类型:%s 损失类型:%s",
claimsCase.getInsuranceType(),
claimsCase.getAccidentType(),
parsedDocs.getDamageCategories()
);
List<Document> clauses = policyVectorStore.similaritySearch(
SearchRequest.query(clauseQuery)
.withTopK(8)
.withSimilarityThreshold(0.78)
.withFilterExpression(
// 只查询该险种的有效条款
"insurance_type == '" + claimsCase.getInsuranceType() + "'" +
" AND status == 'ACTIVE'"
)
);
// 强制包含免责条款(重要)
List<Document> exclusionClauses = retrieveExclusionClauses(claimsCase.getInsuranceType());
clauses.addAll(exclusionClauses);
return clauses;
}
private String performCoreAnalysis(
ClaimsCase claimsCase,
ParsedDocuments parsedDocs,
List<Document> relevantClauses) {
// 构建多模态分析提示
UserMessage userMessage = buildMultimodalPrompt(claimsCase, parsedDocs, relevantClauses);
return chatClient.prompt()
.system(buildSystemPrompt())
.messages(userMessage)
.call()
.content();
}
private UserMessage buildMultimodalPrompt(
ClaimsCase claimsCase,
ParsedDocuments parsedDocs,
List<Document> relevantClauses) {
List<Media> mediaList = new ArrayList<>();
// 添加事故现场照片(如果有)
for (AccidentPhoto photo : claimsCase.getAccidentPhotos()) {
mediaList.add(new Media(MimeTypeUtils.IMAGE_JPEG, photo.getResource()));
}
// 构建文字提示
String textPrompt = buildTextAnalysisPrompt(claimsCase, parsedDocs, relevantClauses);
if (!mediaList.isEmpty()) {
return new UserMessage(textPrompt, mediaList);
} else {
return new UserMessage(textPrompt);
}
}
private String buildTextAnalysisPrompt(
ClaimsCase claimsCase,
ParsedDocuments parsedDocs,
List<Document> relevantClauses) {
StringBuilder sb = new StringBuilder();
sb.append("## 理赔案件信息\n");
sb.append(String.format("- 案件编号:%s\n", claimsCase.getCaseId()));
sb.append(String.format("- 险种:%s\n", claimsCase.getInsuranceType()));
sb.append(String.format("- 被保险人:%s\n", claimsCase.getInsuredName()));
sb.append(String.format("- 事故时间:%s\n", claimsCase.getAccidentTime()));
sb.append(String.format("- 申请赔付金额:%s 元\n", claimsCase.getClaimedAmount()));
sb.append("\n## 解析的文档内容\n");
sb.append("### 客户陈述\n");
sb.append(parsedDocs.getCustomerStatement()).append("\n");
if (parsedDocs.hasPoliceReport()) {
sb.append("### 交警事故认定书(OCR提取)\n");
sb.append(parsedDocs.getPoliceReport()).append("\n");
}
if (parsedDocs.hasRepairQuote()) {
sb.append("### 维修报价单(OCR提取)\n");
sb.append(parsedDocs.getRepairQuote()).append("\n");
}
if (!parsedDocs.getInconsistencies().isEmpty()) {
sb.append("### 系统发现的信息不一致点\n");
parsedDocs.getInconsistencies()
.forEach(item -> sb.append("- ").append(item).append("\n"));
}
sb.append("\n## 相关保险条款\n");
for (Document clause : relevantClauses) {
sb.append("### ").append(clause.getMetadata().get("clause_id")).append("\n");
sb.append(clause.getContent()).append("\n\n");
}
if (!claimsCase.getAccidentPhotos().isEmpty()) {
sb.append("\n## 图像分析说明\n");
sb.append("上方附有事故现场照片,请结合图像内容分析损伤情况与文字描述的一致性。\n");
}
sb.append("\n## 分析要求\n");
sb.append("请按照以下结构输出 JSON 格式分析报告:\n");
sb.append("""
{
"documentIntegrity": "材料完整性评估",
"documentConsistency": "各材料间一致性分析",
"damageAssessment": "损失评估",
"applicableClausesAnalysis": "适用条款分析(引用具体条款编号)",
"exclusionRiskAnalysis": "免责条款风险分析",
"recommendedPayableAmount": "建议赔付金额(仅供参考)",
"suspiciousPoints": ["可疑点列表"],
"auditConclusion": "整体审核结论",
"confidenceLevel": 85,
"keyEvidence": ["关键证据列表(条款编号+文件名)"]
}
""");
return sb.toString();
}
private String buildSystemPrompt() {
return """
你是一位资深保险理赔审核专家,具有丰富的车险、财产险理赔审核经验,熟悉相关法律法规和保险条款。
审核原则:
1. 严格基于提供的保险条款进行分析,每个结论必须引用具体条款
2. 客观评估材料一致性,发现可疑点如实标注,但不做主观判断
3. 建议赔付金额仅供参考,明确说明计算依据
4. 如材料不足以判断,明确说明需要补充哪些材料
5. 对免责条款特别谨慎,必须逐一核查
重要提示:
- 你的分析是辅助材料,最终决定由有资质的审核员做出
- 不要做肯定性的拒赔或赔付结论,只提供分析和建议
- 对于图像内容,只描述客观可见的内容,不做推断
""";
}
private ClaimsAuditReport buildAuditReport(
ClaimsCase claimsCase,
String analysisResult,
FraudRiskScore fraudScore,
List<Document> relevantClauses) {
try {
ObjectMapper mapper = new ObjectMapper();
String jsonContent = extractJsonFromResponse(analysisResult);
Map<String, Object> analysis = mapper.readValue(jsonContent, Map.class);
// 确定处理通道
AuditChannel channel = determineAuditChannel(
(Integer) analysis.getOrDefault("confidenceLevel", 50),
fraudScore
);
// 生成可追溯的条款引用
List<ClauseReference> clauseReferences = buildClauseReferences(
(List<String>) analysis.getOrDefault("keyEvidence", List.of()),
relevantClauses
);
return ClaimsAuditReport.builder()
.caseId(claimsCase.getCaseId())
.analysisTime(LocalDateTime.now())
.documentIntegrity((String) analysis.get("documentIntegrity"))
.documentConsistency((String) analysis.get("documentConsistency"))
.damageAssessment((String) analysis.get("damageAssessment"))
.applicableClausesAnalysis((String) analysis.get("applicableClausesAnalysis"))
.exclusionRiskAnalysis((String) analysis.get("exclusionRiskAnalysis"))
.recommendedPayableAmount(
new BigDecimal(analysis.get("recommendedPayableAmount").toString()))
.suspiciousPoints((List<String>) analysis.getOrDefault("suspiciousPoints", List.of()))
.auditConclusion((String) analysis.get("auditConclusion"))
.aiConfidenceLevel((Integer) analysis.getOrDefault("confidenceLevel", 50))
.fraudRiskScore(fraudScore)
.auditChannel(channel)
.clauseReferences(clauseReferences)
// 关键:保存完整的LLM响应用于审计追溯
.rawAiResponse(analysisResult)
.relevantClauseIds(
relevantClauses.stream()
.map(d -> (String) d.getMetadata().get("clause_id"))
.collect(Collectors.toList())
)
.build();
} catch (Exception e) {
log.error("Failed to build audit report for case: {}", claimsCase.getCaseId(), e);
// 解析失败:路由到人工处理,确保不漏掉任何案件
return ClaimsAuditReport.manualReviewRequired(claimsCase, "AI分析解析失败,需要人工处理");
}
}
private AuditChannel determineAuditChannel(int confidenceLevel, FraudRiskScore fraudScore) {
// 高欺诈风险,无论置信度,都走专家通道
if (fraudScore.getScore() >= 70) {
return AuditChannel.EXPERT;
}
// AI置信度低,走标准人工审核
if (confidenceLevel < 60) {
return AuditChannel.STANDARD;
}
// 中等欺诈风险,走标准通道
if (fraudScore.getScore() >= 40) {
return AuditChannel.STANDARD;
}
// 低风险,高置信度,走快速通道
return AuditChannel.FAST_TRACK;
}
}这段代码里几个设计重点:
1. 欺诈评估独立于 LLM
fraudEvaluator 是一个独立的服务,用规则引擎 + ML 模型实现,不依赖 LLM。这样做的原因是:LLM 的欺诈判断不够稳定,而且难以量化;规则+ML 的欺诈评分更可解释,也更容易向法务说清楚「为什么怀疑」。
2. rawAiResponse 字段
把 LLM 的原始响应存档,这是合规要求。监管机构来查的时候,你需要能展示 AI 到底说了什么。
3. 强制路由逻辑
高欺诈风险的案件,无论 AI 置信度多高,都强制走专家通道。这是系统设计里对高风险场景的「保险丝」,不能被绕过。
公平性和偏见检测:这个话题必须认真对待
我在做这个项目期间,专门研究了 AI 公平性的问题,这是在其他项目里没有认真做过的。
偏见的来源
保险 AI 的偏见主要来自三个地方:
历史数据偏见:如果历史上某类用户(按地区、年龄段等分组)的欺诈率被高估(可能是因为过去的人工审核本身有偏见),模型会继承这个偏见。
代理变量偏见:一些看起来无害的特征,实际上是受保护属性的代理。比如某个邮政编码对应一个特定社区,用邮政编码就可能引入地区歧视。
采样偏见:训练数据不均衡,某些群体的样本量少,模型在这些群体上的表现就会更差。
我们的应对措施
定期公平性审计:每季度按性别、年龄段、地区分组,检查各组的拒赔率、等待时间、赔付比例是否存在显著差异。超过 10% 的差异就触发调查。
特征白名单:明确列出允许输入 AI 系统的特征,显式排除受保护属性及其明显代理变量。
人工抽查机制:每月随机抽取 200 个被 AI 标记为高风险的案件,由不知道 AI 评分的审核员独立审核,对比两者结论,发现系统性偏差。
这套机制不完美,但比什么都不做要好得多。保险公司的合规部门对这套机制也比较认可,这也是最终拿下合同的重要因素。
人机协作:审核员的体验同样重要
技术做得再好,审核员不愿意用就是失败。
我观察了审核员的日常工作流程,发现几个问题:
问题一:AI 报告太长。我们的初版 AI 分析报告平均 2000 字,审核员根本没时间从头看,他们只看结论,条款引用那部分直接跳过。
改进:把报告分成「3 句话总结」和「详细分析」两部分,审核员可以快速看总结,需要深入了解时展开详细分析。
问题二:可疑点描述太模糊。AI 报告说「存在信息不一致」,审核员不知道是什么不一致,还是要自己翻文件。
改进:可疑点必须包含具体的对比:「事故认定书显示碰撞方向为'右侧',现场照片显示损伤集中在左侧,存在不一致」。
问题三:建议赔付金额缺乏计算过程。审核员要向客户解释赔付金额,如果只有数字没有计算依据,他们没法用。
改进:建议赔付金额旁边,必须列出:适用条款编号、计算基准、已扣除项目、最终金额。每一步有据可查。
这些改进做完之后,审核员的采用率从 40% 提升到 85%。技术做得好,产品设计对不上用户,一样白搭。
合规档案:每个决定都要留下完整记录
保险理赔的合规档案要求,远比普通 IT 系统严格:
不可篡改的日志:每次 AI 分析、审核员操作、理赔决定,都必须写入不可篡改的日志(我们用的是区块链存证服务,成本不高但合规性很强)。
版本追踪:AI 模型版本、提示词版本都要记录。同一个案件,在不同版本的 AI 下可能得出不同结论,版本追踪确保可以重现历史决策过程。
数据留存期:保险理赔档案至少保留 10 年(部分险种更长),系统设计要支持长期归档和检索。
访问控制:理赔档案包含客户敏感信息,必须严格的权限控制和访问审计。
这些合规要求增加了相当多的工程工作量,但在这个行业这是必须的。我的建议是:合规框架在系统设计阶段就要考虑,不要上线后再补,补的成本远高于一开始就做对。
上线后的效果和反思
这个系统上线运行了大约八个月,一些数据:
- 快速通道案件处理时间:从平均 3 天降到 6 小时
- 审核员人均处理案件量:提升约 60%
- 欺诈识别率:提升约 25%(和之前纯规则系统相比)
- 客户投诉关于「说明不清晰」的:下降约 40%
但也有不满意的地方:
AI 报告的一致性问题:同样的材料,偶尔会得到稍微不同的 AI 分析。对审核员来说,这增加了心理负担——「AI 怎么这次说法不一样了?」
我的判断是:这个问题在目前的 LLM 技术下很难根本解决,只能通过流程设计来缓解。比如:只有置信度高于 80% 的分析才直接展示给审核员,低于 80% 的明确标注「存在不确定性」。
条款更新的滞后性:保险条款会定期更新,RAG 知识库的条款要及时同步。有一次因为条款更新没有及时入库,AI 引用了一个已经废止的旧条款,被审核员发现,造成了信任危机。
这个教训之后,我们建立了条款变更的自动同步机制:保险条款文件系统一旦有更新,自动触发知识库重建流程,并通知相关审核员「AI 知识库已更新,可能影响以下险种的分析」。
总结:保险 AI 的工程哲学
在保险行业做 AI,我最深的体会是:这个行业逼着你认真对待你通常会轻描淡写的东西。
合规不是额外负担,是产品设计的一部分。公平性不是政治正确,是真实存在的技术风险。可解释性不是锦上添花,是客户的基本权利。
AI 在这个行业的价值,不是替代审核员做决定,而是帮助审核员做更好的决定。这个定位想清楚了,系统设计就有了方向。
如果你也在做金融或保险行业的 AI,合规框架那部分建议早点和客户的法务沟通,少走弯路。
