当企业需要处理数百份供应商合同时,人工打开文档、搜索字段、复制到表格的流程很快就会失控。单纯增加一个 RAG 聊天机器人也解决不了全部问题:它可以回答某一份合同中的问题,却很难稳定回答“整个供应商组合的自动续约风险是多少”或“哪些合同缺少责任上限”这类跨文档问题。
一种更适合生产环境的做法,是把合同智能拆成两条协同链路:用 AI agent 从合同中提取并验证结构化字段,再将这些字段交给 Amazon Quick 做单合同查询和组合分析。这样,非结构化文档会逐步变成可追踪、可审计、可聚合的数据资产。
从文档问答转向合同数据管道
合同智能平台的核心不应只是一个聊天界面,而应是一条有状态的数据处理管道:
- 接收 PDF、扫描件或其他合同文档,并记录合同版本、供应商、来源位置和处理时间。
- 通过 OCR 或文档解析获取文本,同时保留页码、段落或表格等定位信息。
- 由 AI agent 提取合同字段,例如生效日期、终止日期、自动续约条款、付款周期、责任上限、保险要求和适用法律。
- 对低置信度字段执行验证、交叉检查或人工复核。
- 将字段、证据片段、置信度和审核状态写入结构化存储。
- 把经过验证的数据提供给 Amazon Quick,用于单合同问答、组合筛选和趋势分析。
这里最重要的设计变化是:模型输出不应只有一段自然语言。每个字段都需要带上值、证据和状态。例如,auto_renewal 不仅应返回 true,还应记录“自动续约条款位于第 8 页第 2 段”,并标记该结果是否通过验证。
AgentCore 适合承担什么工作
在这类系统中,Bedrock AgentCore 可以作为 agent 工作流的运行基础。一个实用的 agent 通常需要完成三类任务。
字段提取
agent 根据预先定义的合同模式提取字段,而不是让模型自由发挥。模式可以包括字段类型、是否必填、允许的枚举值和证据要求。
{
"contract_id": "vendor-2025-001",
"fields": {
"effective_date": {
"value": "2025-04-01",
"confidence": 0.96,
"evidence": "This Agreement is effective as of April 1, 2025.",
"page": 1,
"status": "verified"
},
"auto_renewal": {
"value": true,
"confidence": 0.71,
"evidence": "The term will automatically renew for successive one-year periods...",
"page": 8,
"status": "needs_review"
}
}
}
字段验证
验证 agent 可以检查日期逻辑,例如终止日期是否晚于生效日期;也可以检查多个条款之间是否存在冲突。例如,合同首页写着付款周期为 30 天,而补充协议写着付款周期为 45 天时,系统应把它们标记为冲突,而不是静默选择一个值。
工具调用和人工介入
当扫描质量较差、条款存在矛盾或置信度低于阈值时,agent 应创建审核任务。人工修改后的字段还应保留修改人、修改时间和原始证据,便于后续审计和模型评估。
一个可改造的 Bedrock 调用示例
下面是一个最小的 Python 示例,用 Amazon Bedrock Runtime 请求模型按照固定 JSON 结构提取合同字段。它是一个可运行的基础示例;实际接入 AgentCore 时,可以把这段模型调用放入 agent 的工具或工作流步骤,并将输入改为文档解析服务输出的文本。
运行前需要配置 AWS 凭证和区域,并将 MODEL_ID 替换为当前账户可访问的模型 ID。示例使用 Claude 风格的请求格式,具体字段可能需要根据所选模型调整。
import json
import os
import boto3
REGION = os.getenv("AWS_REGION", "us-east-1")
MODEL_ID = os.getenv("BEDROCK_MODEL_ID", "anthropic.claude-3-haiku-20240307-v1:0")
contract_text = """
This Agreement is effective as of April 1, 2025.
The initial term is one year and will automatically renew for successive one-year periods.
Customer shall pay undisputed invoices within 30 days.
"""
prompt = f"""
Extract contract fields from the text below.
Return JSON only, with this exact shape:
{{
\"effective_date\": {{\"value\": string|null, \"confidence\": number, \"evidence\": string}},
\"term_months\": {{\"value\": number|null, \"confidence\": number, \"evidence\": string}},
\"auto_renewal\": {{\"value\": boolean|null, \"confidence\": number, \"evidence\": string}},
\"payment_terms_days\": {{\"value\": number|null, \"confidence\": number, \"evidence\": string}}
}}
Do not infer a value when the contract does not provide evidence.
Contract text:
{contract_text}
"""
client = boto3.client("bedrock-runtime", region_name=REGION)
request = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 800,
"temperature": 0,
"messages": [{"role": "user", "content": [{"type": "text", "text": prompt}]}],
}
response = client.invoke_model(
modelId=MODEL_ID,
body=json.dumps(request),
contentType="application/json",
accept="application/json",
)
payload = json.loads(response["body"].read())
text = payload["content"][0]["text"]
print(json.dumps(json.loads(text), indent=2, ensure_ascii=False))
生产系统需要在模型输出之后增加 JSON Schema 校验、数值范围校验和重试策略。不要直接把模型返回的 JSON 写入分析表,否则一个错误的日期或枚举值就可能污染整个供应商组合的统计结果。
为组合分析设计数据模型
Amazon Quick 能否回答组合级问题,取决于底层数据是否真正结构化。建议至少拆分为合同主表、字段事实表和证据表:
contract:
contract_id: vendor-2025-001
vendor_id: vendor-001
source_uri: s3://contracts/vendor-2025-001.pdf
version: 3
processing_status: completed
contract_field:
contract_id: vendor-2025-001
field_name: auto_renewal
value_boolean: true
value_date: null
value_number: null
confidence: 0.71
review_status: needs_review
contract_evidence:
contract_id: vendor-2025-001
field_name: auto_renewal
page_number: 8
text: The term will automatically renew for successive one-year periods.
extractor_run_id: run-2025-04-01-001
这种模型有几个实际好处:
- 组合筛选可以直接基于字段值,而不是每次重新搜索原始 PDF。
- 分析人员可以看到字段背后的证据,降低“黑盒答案”的风险。
- 同一合同的不同版本可以并存,避免更新数据覆盖历史事实。
- 可以按模型运行批次比较准确率、人工修改率和待审核比例。
用户的问题也可以分成两类。单合同问题,例如“这份合同的自动续约条件是什么”,需要返回字段和证据;组合问题,例如“未来 90 天内自动续约且责任上限缺失的合同有哪些”,则需要查询结构化字段并将结果交给 Quick 生成分析视图。两者共用同一份经过验证的数据,回答结果会更一致。
可靠性边界不能交给提示词
合同是高风险业务数据,提示词只能改善模型行为,不能代替系统约束。上线前应明确以下边界:
- 证据强制:没有原文证据时返回空值或待审核,不允许模型猜测。
- 置信度分流:为关键字段配置阈值,例如低于 0.85 时进入人工审核。阈值应通过历史样本校准,而不是凭感觉设定。
- 冲突检测:比较主合同、补充协议和修订版中的同名字段,并保留版本优先级规则。
- 访问控制:供应商合同通常包含价格、责任和个人信息,应在对象存储、字段查询和 Quick 仪表板层面同时控制权限。
- 可追溯性:记录提示词版本、模型 ID、输入文档版本和输出时间,确保结果可以复盘。
- 成本控制:对重复文档使用哈希去重,对长合同按章节处理,并只对发生变化的版本重新提取。
落地检查清单
可以按下面的顺序推进:
- 先选一组有代表性的合同,定义 10 到 20 个高价值字段。
- 为每个字段建立类型、证据格式、置信度和人工审核规则。
- 让 agent 输出结构化结果,而不是只生成自然语言摘要。
- 用专家标注集评估字段准确率、证据命中率和人工修改率。
- 将已验证字段写入可查询的数据层,再接入 Amazon Quick。
- 分别设计单合同页面和组合分析页面,避免用一个聊天入口承担所有任务。
- 对模型、解析器和合同版本建立可回溯的运行记录。
这类平台的价值不在于让模型“读懂一份合同”这一单点能力,而在于把大量合同转化为可验证的数据,并让业务人员能够在单份合同和整个合同组合之间自由切换。Amazon Quick 负责把结构化事实变成可用的分析体验,Bedrock AgentCore 则为提取、验证和工具调用提供可编排的 agent 基础。两者结合后,合同问答才有机会从演示功能走向真正可运营的业务系统。