用 Amazon Bedrock 构建多智能体向量提示文档分类系统

2026-08-19 46 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

保险文档分类并不只是“读一段文字,然后输出一个标签”。保单、宣誓书、批单和理赔材料往往同时包含文本、表格、印章、签名以及固定版式。只依赖 OCR 文本,可能错过决定文档类型的视觉线索;只做图像相似度搜索,又难以理解条款内容。

一种更稳健的方案是使用 Amazon Bedrock 构建多智能体分类流程:让专门的智能体分别处理文本语义、视觉相似度和最终决策,再由协调智能体汇总结果。Strands Agents SDK 可以用来组织这些智能体,Claude Haiku 4.5 负责轻量文本分析,Amazon Titan Multimodal Embeddings 负责文本与图像的向量表示。

为什么要把分类任务拆成多个智能体

单个提示词通常能处理简单分类,但在保险文档场景中会遇到三个边界:

  • 文本不完整:扫描件可能只有部分 OCR 结果,表格和页眉信息容易丢失。
  • 视觉结构重要:宣誓书可能具有固定的签名区、见证人区和公证章;保单通常包含条款标题、保险责任和保费信息。
  • 分类证据不同:一个智能体擅长解释文本,另一个智能体擅长比较版式或页面图像,最终结果需要合并而不是互相替代。

可以将流程拆成三个角色:

  1. 文本分析智能体:读取 OCR 文本,抽取标题、关键词、实体和候选类别。
  2. 视觉检索智能体:调用 Titan Multimodal Embeddings,将文档页面与已标注样本进行相似度比较。
  3. 决策智能体:结合文本证据、视觉证据和置信度,输出最终类别、理由以及是否需要人工复核。

这不是为了“让更多模型参与”而增加复杂度,而是为了让每种证据都有明确的来源。生产环境中还可以把每个智能体的输出保存下来,方便审计和回溯。

一个可落地的处理流程

典型流程可以表示为:

S3 文档
  │
  ├── OCR / 文本抽取 ──> 文本分析智能体
  │
  ├── 页面渲染 ────────> Titan Multimodal Embeddings ──> 向量检索
  │
  └────────────────────> 决策智能体 ──> 类别、理由、置信度

向量检索库中可以预先保存经过人工确认的样本文档,例如:

{
  "document_id": "sample-policy-001",
  "label": "insurance_policy",
  "page": 1,
  "embedding_model": "amazon.titan-embed-image-v1",
  "metadata": {
    "language": "en",
    "source": "human_reviewed"
  }
}

对于新文档,视觉智能体不应只返回“最相似的样本”,还应该返回相似度、命中的类别和样本 ID。决策智能体可以据此判断:视觉证据是否足够强,是否与文本证据冲突,以及是否必须转人工。

用 Strands Agents SDK 组织智能体

下面是一个可改造的 Python 示例。它展示了三个智能体的职责边界,以及如何把结构化结果交给最终决策智能体。示例中的模型 ID、索引查询函数和输入字段需要根据 AWS 账户所在区域及实际部署方式调整。

运行前安装依赖并配置凭证:

python -m venv .venv
source .venv/bin/activate
pip install strands-agents boto3
export AWS_REGION=us-east-1
export BEDROCK_TEXT_MODEL_ID=your-enabled-haiku-model-id
export BEDROCK_VISION_MODEL_ID=amazon.titan-embed-image-v1

示例代码:

import json
import os
from pathlib import Path

import boto3
from strands import Agent
from strands.models import BedrockModel

REGION = os.getenv("AWS_REGION", "us-east-1")
TEXT_MODEL_ID = os.environ["BEDROCK_TEXT_MODEL_ID"]
VISION_MODEL_ID = os.getenv("BEDROCK_VISION_MODEL_ID", "amazon.titan-embed-image-v1")

runtime = boto3.client("bedrock-runtime", region_name=REGION)

text_model = BedrockModel(
    model_id=TEXT_MODEL_ID,
    region_name=REGION,
)

text_agent = Agent(
    model=text_model,
    system_prompt=(
        "You classify insurance documents from OCR text. "
        "Return JSON with label, evidence, and confidence. "
        "Allowed labels: insurance_policy, affidavit, endorsement, unknown."
    ),
)

decision_agent = Agent(
    model=text_model,
    system_prompt=(
        "You are the final insurance-document classifier. "
        "Combine text evidence and visual-search evidence. "
        "Return strict JSON: label, confidence, reasons, needs_human_review. "
        "If evidence conflicts or confidence is below 0.80, request human review."
    ),
)


def embed_image(image_path: str) -> list[float]:
    """Create a Titan multimodal embedding for one page image.

    Confirm the request schema and model ID in the target AWS Region before use.
    """
    image_bytes = Path(image_path).read_bytes()
    body = json.dumps({
        "inputImage": image_bytes.hex(),
        "embeddingConfig": {"outputEmbeddingLength": 1024},
    })

    response = runtime.invoke_model(
        modelId=VISION_MODEL_ID,
        body=body,
        contentType="application/json",
        accept="application/json",
    )
    payload = json.loads(response["body"].read())
    return payload["embedding"]


def search_visual_examples(embedding: list[float]) -> list[dict]:
    """Replace this adapter with OpenSearch Serverless, Aurora, or another vector store."""
    # 生产实现中应使用向量数据库的 k-NN 查询,并返回 metadata 与 score。
    return [
        {
            "sample_id": "sample-affidavit-004",
            "label": "affidavit",
            "score": 0.91,
            "evidence": "signature and notary block are visually similar",
        }
    ]


def classify_document(ocr_text: str, first_page_image: str) -> dict:
    text_result = text_agent(
        f"OCR text:\n{ocr_text}\n\nReturn JSON only."
    )

    embedding = embed_image(first_page_image)
    visual_result = search_visual_examples(embedding)

    decision_input = {
        "text_analysis": str(text_result),
        "visual_search": visual_result,
        "policy": {
            "human_review_threshold": 0.80,
            "conflict_rule": "text and visual evidence conflict => review",
        },
    }
    final_result = decision_agent(json.dumps(decision_input, ensure_ascii=False))
    return {"result": str(final_result), "visual_matches": visual_result}


if __name__ == "__main__":
    result = classify_document(
        ocr_text="AFFIDAVIT OF LOSS ... subscribed and sworn before me ...",
        first_page_image="page-001.jpg",
    )
    print(json.dumps(result, ensure_ascii=False, indent=2))

这个示例有两个重要的工程假设:

  • Titan 的请求字段、输出维度和具体模型 ID 可能随模型版本或区域配置变化,部署前应以目标区域的 Bedrock 文档和控制台为准。
  • search_visual_examples 只是向量数据库适配器。生产环境需要保存 embedding、类别、文档版本、数据来源和人工标注状态,并对查询结果做权限控制。

“向量提示”不只是相似度搜索

向量检索返回的是候选证据,不是最终答案。更可靠的决策提示应该把候选样本、分数、文本分析和业务规则一起传给决策智能体,例如:

You classify one insurance document.

Text evidence:
- OCR keywords: "subscribed", "sworn", "notary"
- Text candidate: affidavit
- Text confidence: 0.86

Visual evidence:
- Top match: sample-affidavit-004
- Similarity: 0.91
- Visual cues: signature area and notary block

Rules:
1. Choose only from the approved label set.
2. Do not treat similarity alone as proof.
3. If evidence conflicts or confidence < 0.80, set needs_human_review=true.
4. Return valid JSON only.

这种提示把“模型自由发挥”变成了可检查的证据合并过程。还可以要求输出 reasonsevidence_idsmissing_information,让下游系统知道为什么做出决定。

生产环境需要重点控制的风险

置信度不能直接当作准确率

模型输出的 0.91 不一定代表真实准确率为 91%。应该使用一批经过人工标注的验证集做校准,并分别统计每种文档类型的 precision、recall 和人工复核率。

多页文档不能只看第一页

第一页通常能提供强线索,但附加条款或签名可能出现在后续页面。可以对每页生成 embedding,再通过最大相似度、平均相似度或页面级投票汇总文档级结果。

OCR 和图像数据都要做隐私保护

保险文档可能包含姓名、地址、保单号和健康信息。应使用 S3 加密、最小 IAM 权限、日志脱敏和明确的数据保留策略。调试日志中不要直接输出完整 OCR 文本或原始图像。

低置信度路径必须真实可用

人工复核不是一个布尔字段就结束了。系统至少需要把原文档、候选标签、文本证据、视觉命中样本和模型版本一起交给审核人员,并保存最终修正结果,用于后续评估和样本库更新。

采用前的检查清单

  • [ ] 定义有限且互斥的保险文档标签集合。
  • [ ] 为每个标签准备经过人工确认的文本和页面图像样本。
  • [ ] 明确 OCR、页面渲染、向量数据库和 Bedrock 的数据流向。
  • [ ] 让文本智能体、视觉智能体和决策智能体输出可审计的结构化证据。
  • [ ] 用验证集校准置信度,并设置人工复核阈值。
  • [ ] 对多页文档、低质量扫描件、混合语言和类别未知样本单独测试。
  • [ ] 记录模型版本、提示版本、embedding 模型和检索结果。

多智能体架构的价值不在于把一个分类器拆成三个黑盒,而在于把不同类型的证据显式组合起来。对保险文档这类既依赖语义又依赖版式的任务,Amazon Bedrock、Claude Haiku 4.5、Titan Multimodal Embeddings 和 Strands Agents SDK 可以组成一条清晰的工程链路;真正上线前,则要用数据集、阈值、审计和人工复核把它变成可控的业务系统。


相关推荐