教程演示如何基于Bedrock Knowledge Bases构建对话式理赔助手,涵盖文档摄取、AgenticRetrieveStream API、多轮对话、元数据过滤和护栏配置。
理赔答案分散在理赔员日志条目、维修估价单、警察报告、付款台账和扫描附件中,而非集中在某个可搜索的字段。保单持有人可能会询问理赔是否已获批准,而理赔员可能需要查找上个月所有超过 10,000 美元的未结汽车理赔。这两项任务都需要快速、准确地查找和整合证据。
检索增强生成(RAG)利用检索到的文档来为模型回复提供依据。Amazon Bedrock Knowledge Bases 是面向文档的托管 RAG 能力。Amazon Bedrock 负责解析、分块、嵌入向量和向量存储,因此你可以构建一个会话界面,从理赔文件中返回带引用的答案。
这篇技术实践文章使用合成理赔记录,不描述实际的生产客户部署。你通过以下步骤构建一个理赔助手,用引用回答自然语言问题:
从 Amazon Simple Storage Service(Amazon S3)提取理赔文档及其元数据。
使用 AgenticRetrieveStream API 用自然语言查询。
提出多轮后续问题。
使用元数据过滤器(如理赔 ID 和理赔类型)缩小检索范围。
添加上下文 grounding 护栏,使答案与记录保持关联。
保单持有人、客服中心代理和理赔员会提出不同的问题:
保单持有人需要简明的状态更新:"理赔 CLM-100482 的估价是否已获批准?支票何时发出?"
客服中心代理需要在客户等待时快速、准确地回答,无需转接电话。
理赔员会提出跨理赔的多部分问题,例如上个月提交了哪些超过 10,000 美元的未结汽车理赔,每个理赔还有哪些工作待完成。
答案以 PDF 理赔员报告、Word 往来函件和文本备注的形式存储,而非统一的数据库字段。
记录可能存在冲突或取代早期版本。修订后的估价可能取代早期估价,或者临时付款可能在之后被撤销。助手必须确定哪个估价、付款或状态是有效的。
由于理赔受到监管,每个答案都必须以源文档为依据并包含引用。客服中心代理可以在重复答案之前验证来源,主管可以审计助手是如何得出答案的。
该解决方案使用 Amazon Bedrock Knowledge Bases 从 Amazon S3 索引理赔文档以供检索。
通过 AgenticRetrieveStream 的主动检索功能会规划答案、将多部分问题分解为子查询,并运行一次或多次检索传递。它会在生成回复之前检查证据是否充分。
该 API 流式传输 trace 事件、答案文本和引用。Trace 事件暴露检索计划,每个引用将答案的一部分映射到源理赔文档。
下图展示了两条路径。摄取通道将理赔文档和元数据加载到知识库。检索通道通过 AgenticRetrieveStream 和 Amazon Bedrock Guardrails grounding 检查发送每个问题,然后返回带引用的答案。
图 1:使用 Amazon Bedrock Knowledge Bases 的会话式理赔助手
摄取通道在文档到达时运行:
PDF、Word 或文本格式的理赔文档与匹配的元数据侧文件一起进入 Amazon S3。
摄取作业在文档变化时将 S3 数据源与知识库同步。
知识库在托管向量存储中解析、分块、嵌入和索引文档及其元数据。
检索通道针对每个问题运行:
应用程序调用 AgenticRetrieveStream,传入问题、对话历史记录和可选的元数据过滤器以缩小搜索范围。
基础模型创建子查询并重复检索,直到获得足够证据,最多不超过 maxAgentIteration 轮。
上下文 grounding 检查阻止未被检索记录支持的答案。
Amazon Bedrock 流式传输答案、trace 事件和引用,因此应用程序可以在输出到达时显示。
在开始之前,请确认你满足以下条件:
一个 AWS 账户,具有 Amazon Bedrock 和 Amazon S3 的 AWS Identity and Access Management(IAM)权限。
通过 Amazon Bedrock 模型访问获得启用的基础模型(FM)的访问权限。
支持所选基础模型和 Amazon Bedrock Knowledge Bases 的 AWS 区域。本演练使用 US West(Oregon),即 us-west-2。部署前请查看 Amazon Bedrock 中的按 AWS 区域支持的模型。
AWS SDK for Python(Boto3),配置了凭证且版本支持此处使用的 API。
用于合成理赔文档和元数据的 S3 存储桶。
熟悉 Python 和基本 RAG 概念。
在 Amazon S3 中每个理赔存储一个文档。知识库直接读取 PDF 理赔员报告、Word 往来函件和文本备注,因此你可以保持文档的原始格式。
图 2 显示了一个合成理赔记录。Current exposure 是估计的理赔总成本。其证据索引标识了一个被取代的传真草案,意味着一条被新版本替换的记录。元数据侧文件重复了助手可以过滤的字段。
图 2:带有文件控制字段和证据索引的合成理赔记录
为了进行过滤,请添加一个同名的附带元数据文件,后缀为 .metadata.json。对于 CLM-100482.pdf,使用 CLM-100482.pdf.metadata.json。代位追偿是保险公司从负责任的第三方追回成本的努力。以下示例描述了一个汽车理赔:
{
"metadataAttributes": {
"claim_id": "CLM-100482",
"claim_type": "auto",
"status": "open",
"date_filed": 20260709,
"amount": 14250,
"region": "us-west",
"adjuster": "Martha Rivera",
"policyholder": "Mary Major",
"policy_number": "POL-AUTO-78432",
"customer_id": "CUST-MM-1042",
"household_id": "HHD-MM-1042",
"document_type": "adjuster_report",
"carrier": "Example Insurance",
"has_subrogation": true,
"has_litigation": false,
"complexity_tier": "high"
}
}
侧文件包含标量字符串、数字和布尔值。值类型决定可用的过滤器。下表列出了后续查询中使用的字段。
本文使用合成数据。未经所需控制和批准,不得在这些资源中放置真实的个人身份信息(PII)或受保护健康信息。
将日期存储为 YYYYMMDD 整数,因为元数据过滤器比较数字而非日期字符串。此格式支持"上个月提交"之类的范围查询。
在 amount 中仅存储一个可比较的货币值。准备金是为估计理赔成本预留的资金,而保留款是暂时扣留的资金。将准备金、付款和保留款保留在文档文本中,以使其标签保持清晰。
侧文件限制为 10 KB。有关完整格式,请参阅知识库的连接到 Amazon S3。
S3 布局将每个理赔文档与其元数据文件配对:
s3://amzn-s3-demo-insurance-claims/claims/CLM-100482.pdf
s3://amzn-s3-demo-insurance-claims/claims/CLM-100482.pdf.metadata.json
s3://amzn-s3-demo-insurance-claims/claims/CLM-100517.docx
s3://amzn-s3-demo-insurance-claims/claims/CLM-100517.docx.metadata.json
s3://amzn-s3-demo-insurance-claims/claims/CLM-100533.txt
s3://amzn-s3-demo-insurance-claims/claims/CLM-100533.txt.metadata.json
使用 bedrock-agent 客户端创建知识库。将 knowledgeBaseConfiguration.type 和 embeddingModelType 设置为 MANAGED。
Amazon Bedrock 选择并操作嵌入模型。无需向量存储配置。有关所有参数,请参阅 CreateKnowledgeBase。以下代码创建知识库:
import boto3
bedrock_agent = boto3.client("bedrock-agent", region_name="us-west-2")
kb = bedrock_agent.create_knowledge_base(
name="insurance-claims-kb",
description="Synthetic insurance claims for the claims assistant",
roleArn="arn:aws:iam::111122223333:role/InsuranceClaimsKnowledgeBaseRole",
knowledgeBaseConfiguration={
"type": "MANAGED",
"managedKnowledgeBaseConfiguration": {
"embeddingModelType": "MANAGED"
},
},
)
kb_id = kb["knowledgeBase"]["knowledgeBaseId"]
roleArn 服务角色授予知识库读取 S3 存储桶和使用托管嵌入模型的权限。请参阅为 Amazon Bedrock Knowledge Bases 创建服务角色。要使用客户托管的 AWS Key Management Service(AWS KMS)密钥加密托管向量存储,请在 serverSideEncryptionConfiguration 中传递其 ARN。
接下来,将 S3 存储桶连接为数据源。inclusionPrefixes 设置将摄取限制在 claims/ 路径:
启动一个摄取任务来解析、分块、嵌入和索引文档。每当有新的理赔文档添加或更新时,再次运行该任务以保持索引同步:
bedrock_agent.start_ingestion_job(
knowledgeBaseId=kb_id,
dataSourceId=data_source_id,
)
可以使用 get_ingestion_job 或 Amazon Bedrock 控制台检查状态。当任务完成后,理赔数据即可被搜索到。详细信息请参阅 StartIngestionJob。
摄取完理赔数据后,通过 bedrock-agent-runtime 客户端调用 AgenticRetrieveStream。完整的请求和响应语法请参阅 API 参考。请求由三部分组成:
以下请求询问某个理赔的状态。将 generateResponse 设为 True 会返回自然语言答案:
bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name="us-west-2")
response = bedrock_agent_runtime.agentic_retrieve_stream(
messages=[
{"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}}
],
retrievers=[
{
"configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}},
"description": "Synthetic insurance claim records",
}
],
agenticRetrieveConfiguration={
"foundationModelType": "MANAGED",
"maxAgentIteration": 5,
},
generateResponse=True,
)
遍历 response["stream"] 并处理以下三种事件类型:
以下循环在答案片段到达时将其流式输出,并保留最终结果用于引用渲染:
answer = ""
final_result = None
for event in response["stream"]:
if "traceEvent" in event:
attributes = event["traceEvent"]["attributes"]
print(f"[trace] {attributes.get('step')}: {attributes.get('status')}")
elif "responseEvent" in event:
chunk = event["responseEvent"]["text"]
answer += chunk
print(chunk, end="", flush=True)
elif "result" in event:
final_result = event["result"]
上述基础循环打印每个步骤和状态。以下辅助函数还会打印子查询、完整文档获取和护栏操作:
def report_trace(trace_event):
attributes = trace_event.get("attributes", {})
print(f"[trace] {attributes.get('step')}: {attributes.get('status')}")
for action in attributes.get("actions", []):
if "retrieve" in action:
sub_query = action["retrieve"].get("inputQuery", {}).get("text", "")
print(f" sub-query: {sub_query}")
elif "fullDocumentExpansion" in action:
document = action["fullDocumentExpansion"].get("documentId", "")
print(f" full document: {document}")
for warning in attributes.get("warnings", []):
if "guardrail" in warning:
print(f" guardrail: {warning['guardrail'].get('action')}")
图 3 展示了 AI 智能体循环。服务先规划策略、创建子查询、检索证据,然后检查是否已收集足够信息。如有需要,会再执行一轮,然后生成带引用的答案。
图 3:从问题到带引用答案的 AI 智能体检索循环

每个引用都标明了答案中的字符跨度,并引用 result 事件 results 数组中的相关条目。应用程序通过索引将显示的文本与其来源文档关联。
以下代码打印每个被引用的跨度及其来源文档的内置 x-amz-bedrock-kb-source-uri 值:
generated = final_result["generatedResponse"]
results = final_result["results"]
for citation in generated.get("citations", []):
span = generated["answer"][citation["startIndex"]:citation["endIndex"]]
for reference in citation["references"]:
source = results[reference["resultIndex"]]
source_uri = source.get("metadata", {}).get("x-amz-bedrock-kb-source-uri")
print(f'"{span}"\n -> {source_uri}')
后续问题依赖于之前的对话轮次。在得到状态答案后,保单持有人可能会问:"负责的理赔员是谁?"这里的"它"需要从 conversation history 中传入的 messages 里进行解析。
在应用程序中维护对话。每轮结束后,将用户的问题和助手的答案追加到列表中,然后在下次调用时发送完整的列表:
messages = [
{"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}},
{"role": "assistant", "content": {"text": answer}},
{"role": "user", "content": {"text": "Who is the adjuster assigned to it?"}},
]
response = bedrock_agent_runtime.agentic_retrieve_stream(
messages=messages,
retrievers=[
{"configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}}}
],
agenticRetrieveConfiguration={"foundationModelType": "MANAGED"},
generateResponse=True,
)
服务利用之前的对话轮次将"它"解析为理赔 CLM-100482,并检索该理赔的理赔员信息。按照之前的方式处理响应流。
元数据过滤器在语义搜索之前对文档进行限制。将过滤器添加到 retriever 的 retrievalOverrides 下。使用查询过滤器来提高相关性,根据服务器端已认证会话派生授权过滤器。
对于按理赔 ID 直接查找,使用 equals 过滤器:
retrievers = [
{
"configuration": {
"knowledgeBase": {
"knowledgeBaseId": kb_id,
"retrievalOverrides": {
"filter": {"equals": {"key": "claim_id", "value": "CLM-100482"}}
},
}
}
}
]
对于 2026 年 7 月提交的超过 10,000 美元的非封闭汽车理赔,使用 andAll 组合理赔类型、状态、金额和日期条件:
claims_filter = {
"andAll": [
{"equals": {"key": "claim_type", "value": "auto"}},
{"equals": {"key": "status", "value": "open"}},
{"greaterThan": {"key": "amount", "value": 10000}},
{"greaterThanOrEquals": {"key": "date_filed", "value": 20260701}},
{"lessThanOrEquals": {"key": "date_filed", "value": 20260731}},
]
}
response = bedrock_agent_runtime.agentic_retrieve_stream(
messages=[
{
"role": "user",
"content": {
"text": "Summarize the outstanding items on the open auto "
"claims over $10,000 filed in July."
},
}
],
retrievers=[
{
"configuration": {
"knowledgeBase": {
"knowledgeBaseId": kb_id,
"retrievalOverrides": {
"filter": claims_filter,
"maxNumberOfResults": 50,
},
}
}
}
],
agenticRetrieveConfiguration={"foundationModelType": "MANAGED"},
generateResponse=True,
)
此查询可能匹配多个理赔,因此 maxNumberOfResults 设为 50。限制过小可能导致匹配的理赔被排除在摘要之外。
支持的运算符包括 equals、notEquals、数值比较、in、notIn、stringContains、listContains 以及逻辑 andAll/orAll。startsWith 仅限于 Amazon OpenSearch Serverless 向量存储。请参阅 Metadata and filtering 并确认运算符支持情况。
如果过滤器返回空文档,请检查空结果并返回明确的消息,例如"没有符合条件的理赔",而不是生成一个答案。
我们在 30 份文档的合成语料库上使用 Retrieve 和 RetrieveAndGenerate 进行了测量,而非 AgenticRetrieveStream。请将结果视为该语料库和元数据模式的基准,而非 AI 智能体检索的性能基准。
这 40 道题的测试套件包括直接查询、比较、别名、已替代记录、已逆转付款以及类似指令的文档文本。自动化基础模型评分使事实级结果具有方向性指导意义。
预期来源检索召回率衡量所需文档被找到的比例。引用召回率衡量所需文档被引用的比例。两者均按文档级计算每道题的平均值,不衡量分块精度。
下表展示了整体结果。
来源:此处描述的 40 道题评估套件和基础模型评分器。
在 20 道对抗性问题上,检索召回率为 96.7%,引用召回率为 90.2%。模型将名称相似的公司区分开来,将指控保留为指控,并忽略了附件内类似指令的文本。
图 4 比较了完整套件和对抗性子集的预期来源检索与引用召回率。这些测量使用 Retrieve 和 RetrieveAndGenerate。
图 4:预期来源检索与引用召回率,完整套件与对抗性子集对比
狭窄的特定理赔问题表现最佳。宽泛的未过滤清单问题产生了最弱的三个结果。
引用覆盖率不能保证答案完整性,因此在需要时应单独测量完整性。
这些结果使用合成文档和自动化评分。在向保单持有人开放助手之前,在你自己的语料库上进行人工审核。
理赔助手需要访问控制和有依据的响应。
将元数据过滤器视为访问边界。从认证会话中获取 region 或 customer_id,使用 andAll 将其与查询过滤器组合,切勿从用户文本中接受边界。userContext 字段也支持访问控制过滤。
仅授予智能体检索、知识库访问、模型流式输出和护栏操作所需的权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "bedrock:AgenticRetrieveStream",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"bedrock:Retrieve",
"bedrock:GetDocumentContent"
],
"Resource": "arn:aws:bedrock:us-west-2:111122223333:knowledge-base/*"
},
{
"Effect": "Allow",
"Action": "bedrock:InvokeModelWithResponseStream",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"bedrock:GetGuardrail",
"bedrock:ApplyGuardrail"
],
"Resource": "*"
}
]
}
AWS CloudTrail 记录对 Amazon Bedrock 的调用以供审计。
Amazon S3 默认对对象进行静态加密。参阅配置默认加密。你可以为存储桶和托管向量存储使用客户管理的 AWS KMS 密钥。API 流量使用传输层安全(TLS)。
添加 Amazon Bedrock Guardrails 上下文 grounding 检查,以阻止低于配置 grounding 或相关性阈值的响应:
使用 bedrock 客户端创建护栏。参阅 CreateGuardrail 了解所有策略类型,并为理赔选择较高的 grounding 阈值:
bedrock = boto3.client("bedrock", region_name="us-west-2")
guardrail = bedrock.create_guardrail(
name="claims-assistant-guardrail",
description="Contextual grounding for the claims assistant",
contextualGroundingPolicyConfig={
"filtersConfig": [
{"type": "GROUNDING", "threshold": 0.85},
{"type": "RELEVANCE", "threshold": 0.75},
]
},
blockedInputMessaging="I can't help with that request.",
blockedOutputsMessaging="I can only answer questions using the claim records.",
)
guardrail_id = guardrail["guardrailId"]
guardrail_version = bedrock.create_guardrail_version(
guardrailIdentifier=guardrail_id
)["version"]
更高的阈值会阻止更多响应。在理赔工作流中,拒绝回答比生成不支持的内容更安全。在 policyConfiguration 中传递护栏 ID 和版本:
response = bedrock_agent_runtime.agentic_retrieve_stream(
messages=[
{"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}}
],
retrievers=[
{"configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}}}
],
agenticRetrieveConfiguration={"foundationModelType": "MANAGED"},
policyConfiguration={
"bedrockGuardrailConfiguration": {
"guardrailId": guardrail_id,
"guardrailVersion": guardrail_version,
}
},
generateResponse=True,
)
智能体检索支持 BLOCK 操作。失败的 grounding 检查会阻止响应,追踪事件记录该干预。
让人保持在循环中审查引用的证据并做出最终理赔决定。
完成后删除资源以避免未来产生费用:
删除知识库。这也会删除托管向量存储:bedrock_agent.delete_knowledge_base(knowledgeBaseId=kb_id)
bedrock_agent.delete_knowledge_base(knowledgeBaseId=kb_id)
删除护栏:bedrock.delete_guardrail(guardrailIdentifier=guardrail_id)
bedrock.delete_guardrail(guardrailIdentifier=guardrail_id)
清空并删除 S3 存储桶。
删除知识库 IAM 角色和策略。
你使用 Amazon Bedrock Knowledge Bases 和 Amazon S3 中的合成文档构建了一个理赔助手。
AgenticRetrieveStream 处理多部分问题、对话历史、元数据过滤器、grounding 检查、流式回答和引用。
同样的模式适用于核保和保单服务文档。在 Amazon Bedrock Knowledge Bases 和使用智能体检索查询知识库中了解更多。