精选AWS AI Blog新闻
KnowledgeForge:从ITSM工单坟墓中挖掘知识金矿
本文介绍了KnowledgeForge,一个基于AWS生成式AI的文档处理流水线,用于从已解决的ITSM工单中自动生成知识库文章,并对现有知识库进行去重、质量评分和改进。系统采用闭环架构,使用Amazon Bedrock进行内容生成,Amazon S3 Vectors进行重复检测,AWS Step Functions进行编排。文章详细说明了各组件选择理由和实现细节,适合构建大规模文档处理流水线的开发者参考。
KnowledgeForge致力于从IT服务管理(ITSM)工单坟场中挖掘黄金:那些已解决的故障工单,其知识从未沉淀到知识库文章中。企业IT支持团队每月解决数千张工单,每张工单都蕴含着有价值的信息:症状、根因,以及工程师应用的修复方案。这些知识被锁在工单历史中,下一个遇到相同问题的工程师无法找到它们。
知识库本身则面临相反的问题。它在增长,但增长得杂乱无章:重复文章堆积,内容过时,质量因作者和撰写时间的不同而参差不齐。支持工程师搜索答案时,要在近乎相同的草稿中艰难跋涉,有些是准确的,有些则已经落后了三个产品版本。
我们构建KnowledgeForge就是为了弥合这两端的差距。它从已解决的故障工单中挖掘新文章。同时,它通过按类型对文章分类、去除重复、评分质量、重写薄弱内容来整理现有知识库。知识管理员负责审核并批准结果,因此最终上线的内容仍由人来掌控。
本文介绍KnowledgeForge背后的AWS构建模块:Amazon Bedrock用于生成和内容改进,Amazon S3 Vectors(Amazon Simple Storage Service(Amazon S3)的一项功能)用于重复检测,AWS Step Functions用于编排。对于每个组件,我们都会解释选择它的原因并附上文档链接。如果你正在基于生成式AI构建大规模文档处理流水线,可以直接复用这些模式。
前置条件
- 一个可访问Amazon Bedrock的AWS账户,并已启用Anthropic Claude Sonnet 4.5和Amazon Titan Text Embeddings V2模型的访问权限。
- 创建本解决方案所用资源的权限:Amazon S3存储桶和Amazon S3 Vectors索引、AWS Step Functions状态机、AWS Lambda函数、AWS Fargate上的Amazon Elastic Container Service(Amazon ECS)服务、Amazon DynamoDB表、Amazon Simple Queue Service(Amazon SQS)队列、Amazon Bedrock防护机制以及AWS Key Management Service(AWS KMS)密钥。
- 已安装AWS Cloud Development Kit(AWS CDK),并熟悉Amazon Bedrock、AWS Step Functions、Amazon ECS和向量嵌入。
- 来自aws-samples/sample-knowledgeforge仓库的代码。
闭环知识库生命周期
KnowledgeForge由两个相互馈送的子系统组成。生成子系统将聚类后的故障工单转化为新的草稿文章。当一组相关工单描述同一问题时,系统会从该聚类中撰写一篇知识库文章和一份根因分析文档。随后,整理子系统对每篇文章(包括新生成的和已有的)执行四个步骤:按类型分类、检查重复、评分质量、改进薄弱内容。完成后的文章进入ServiceNow供知识管理员审核。
闭环之所以成立,是因为整理子系统为每篇文章存储一个向量,而生成子系统在撰写任何新内容之前会先读取这些向量。下图展示了两个子系统如何连接。

图1:闭环知识库生命周期。数据摄取为生成和整理提供输入,知识管理员审核输出,整理子系统对每篇文章进行向量嵌入,以便生成子系统在下一轮运行时将这些向量作为 grounding 复用。
- 数据摄取——已解决的工单和现有文章落入Amazon S3,由数据目录跟踪。
- 生成——聚类后的工单在AWS Fargate上的Amazon ECS中转化为新的草稿文章。
- 整理——每篇文章通过AWS Lambda上的AWS Step Functions工作流进行分类、去重、质量评分和改进。
- 人工审核——增强后的文章进入ServiceNow供知识管理员审批,审批决定写回Amazon DynamoDB。
- 闭环——整理子系统将每篇文章嵌入Amazon S3 Vectors索引,生成子系统在下一轮运行时复用这些向量。
两个子系统运行在不同的计算平台上,原因将在后续章节跟随一篇文章走完整个系统时逐一说明。
从故障工单聚类生成文章
生成从一组共享主题的工单聚类开始。上游流程按所描述的问题对已解决的故障进行分组,并将结果以JSON文件形式放入Amazon S3存储桶,范围限定为单个客户。每个主题携带关键词、文章范围,以及工单描述和工作备注的样本。
存储桶中的新文件会向Amazon SQS队列发送一个事件。AWS Fargate上的Amazon ECS容器轮询该队列,读取文件,并同时处理一个客户最多五个主题。
写作之前,系统会先以现有内容为基础进行自我锚定。针对每个主题,它会从该客户的 Amazon S3 Vectors 索引中检索出五篇最相似的现有文章,并将其作为参考上下文传递给模型。这种检索增强生成(RAG)方式保持了术语的一致性,并减少了凭空捏造的流程。当尚不存在参考文章时,系统仅根据工单数据生成内容,并将这些流程标记为待审核。
生成过程在 Amazon Bedrock 上的 Anthropic Claude Sonnet 4.5 中运行。针对每个主题,模型会生成两份结构固定的文档:
- 知识库文章:标题与摘要、症状、根本原因、解决步骤、预防措施及相关主题。
- 根本原因分析文档:执行摘要、问题描述、客户影响、五问分析、临时解决方案与最终修复、纠正与预防措施、关键事件时间线及原因代码。
我们使用 Amazon Bedrock 的响应流式传输,因此容器会在令牌到达时逐步组装每份文档,而无需等待完整响应。
为何选择容器而非函数
我们选择在带有 AWS Fargate 的 Amazon ECS 上运行生成任务,这是由工作形态决定的。为一个主题生成两份完整文档可能需要几分钟,而一个繁忙的文件包含许多主题,因此单个工作单元可能运行很长时间。工作负载也是突发性的,有时沉寂一段时间,然后一次性涌入大批量任务。一个长期运行的容器服务,根据队列深度伸缩任务数量,并在队列清空时缩回,非常契合这种模式。
AWS Fargate 符合这一需求。它以无服务器方式运行我们的容器,随着主题到来按需扩展,让团队专注于生成逻辑而非计算容量管理。每份文档以 JSON 格式存入 Amazon S3,随时可供审核整理。
使用 Amazon S3 Vectors 查找重复文章
审核整理的首要挑战是检测文章是否已存在。重复有多种形式:两篇文章用不同措辞描述同一个修复方案;新文章取代旧文章;或者工程师复制一篇文章,改动两行后另存为新文章。
我们选择 Amazon S3 Vectors 来解决这个问题。它直接将嵌入向量存储在 Amazon S3 中,无需独立的向量数据库。它将元数据与每个向量一同保存,支持按客户过滤,并按查询次数和存储容量计费,而非按运行节点计费。这使得为库中每篇文章保留一个向量变得经济实惠。如果您已将内容存储在 Amazon S3 中,就可以在不新增基础设施的情况下添加向量搜索。详情请参阅 Amazon S3 用户指南。
关键词匹配无法识别这些重复形式,因此该流程基于语义进行匹配。每篇文章都会通过 Amazon Titan Text Embeddings V2 生成一个 1,024 维的嵌入向量,存储在按客户划分的 Amazon S3 Vectors 索引中。向量存储通常用于检索,而这里同一个索引还兼作重复检测器。新文章被嵌入后,系统查询索引中最近的现有向量,任何落在严格余弦距离阈值内的结果都被视为重复。我们以 0.05 的余弦距离(即相似度 0.95 或更高)和 top-K 为 5 作为起点。我们通过抽样检查被标记的配对来调整距离阈值,逐步收紧,直到近乎相同的文章能被匹配出来,同时不会误捕仅属相关的文章。阈值过松会产生误报重复,过紧则会漏掉改写过的副本。该查询只需一次调用,并按当前客户和有效文章进行过滤:
response = s3vectors.query_vectors(
vectorBucketName=VECTOR_BUCKET,
indexName=VECTOR_INDEX,
queryVector={"float32": embedding},
topK=TOP_K + 1, # +1 因为文章可能匹配到自身
returnMetadata=True,
returnDistance=True,
filter={"$and": [
{"tenant_id": {"$eq": TENANT_ID}}, # 按客户隔离
{"status": {"$in": ["UNIQUE", "PENDING"]}}, # 忽略已停用文章
]},
)
matches = [v for v in response.get("vectors", []) if v["key"] != article_id]当系统发现重复配对时,默认做法是保留较新的文章并停用旧文章,而不是直接丢弃新文章。最新且准确的版本胜出——这正是支持工程师想要的行为。
以这种方式复用索引也有助于重试场景。生成嵌入需要调用模型,而重新运行时可以直接读取已存储的向量,无需重新计算,从而在批次重跑时节省时间和 Amazon Bedrock 费用。
使用 AWS Step Functions 大规模编排审核流程
审核整理针对的是成批的文章,需要编排以将工作分散到多个工作节点并实现故障恢复。AWS Step Functions 通过两阶段分布式映射提供了这一能力。它管理工作流状态,应用定义中声明的重试和错误处理策略,并将工作分发到各工作节点,无需自定义协调代码。有关分布式映射的运作方式,请参阅 AWS Step Functions 开发者指南。
有两个配置选择值得特别说明。首先,我们将条目处理器设置为 STANDARD 而非 EXPRESS。每篇文章都会发起长时间运行的 Amazon Bedrock 调用,超出 5 分钟的 EXPRESS 限制,而 STANDARD 模式会保留完整的执行历史以供调试。其次,我们将 ItemReader 指向 Amazon S3 中的清单文件,而不是内联传递条目,这样可以使工作流状态保持精简。
Amazon EventBridge 上的每日调度启动运行。一个 AWS Lambda 函数查找有新文章或文章有变动的客户,将变更分组为批次,并将每个批次放入 Amazon SQS 先进先出(FIFO)队列。FIFO 队列以客户 ID 作为消息组键,按客户对跨运行的批次进行排序,因此不同客户仍可并行运行。跨运行排序只是其中一部分。在单次执行中,阶段 2 可同时处理多达 40 个批次,因此仅靠 FIFO 并不能阻止不同批次中的两个重复项发生竞争。真正保障去重一致性的机制是:去重在 worker 内部每个批次内串行执行,而质量评分和改进则并行运行。每批次串行去重、质量与改进并行处理、以及 FIFO 实现跨运行排序,三者共同确保重复检测的一致性。
一个调度函数每次拉取一个批次并启动 Step Functions 执行。状态机分两个阶段运行,每个阶段都是一个分布式映射(distributed map),使批次内的文章并发处理:
- 分类与嵌入——每篇文章按类型分类并生成向量嵌入。
- 去重、评分与改进——管道查找重复项、评估质量,并改进低于阈值的內容。
下图展示了触发链、两个阶段以及保护运行容错机制。

图 2:内容策展以两阶段分布式映射运行。批次通过 Amazon SQS FIFO 队列按客户排序,文章内容以 Amazon S3 指针而非内联状态传递,断路器(circuit breaker)和死信队列(dead-letter queue)防止坏批次阻塞运行。
传递指针而非负载
Step Functions 执行在状态之间传递状态,上限为 256 KB。知识库文章包含完整的 HTML 正文,很快就会超过该限制。我们没有将文章内容贯穿状态机,而是将批次写入 Amazon S3,仅通过工作流传递位置信息。每个映射 worker 直接从 Amazon S3 读取所需内容,因此无论文章多大,状态负载都保持精简。
分布式映射从 Amazon S3 中的清单读取工作项,而非从内联状态读取。容错百分比允许运行吸收少量坏文章而不会中止整个批次:
"Phase1_ClassifyEmbed": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": { "Mode": "DISTRIBUTED", "ExecutionType": "STANDARD" }
},
"ItemReader": {
"Resource": "arn:aws:states:::s3:getObject",
"ReaderConfig": { "InputType": "JSON" },
"Parameters": { "Bucket.$": "$.bucket", "Key.$": "$.manifest_key" }
},
"MaxConcurrency": 40,
"ToleratedFailurePercentage": 10
}从故障中恢复
- 死信队列——反复失败的批次会被搁置以待调查,而不会阻塞其后的队列。
- 断路器(尽力而为)——连续三次失败后,调度函数停止启动新批次,并将受影响的文章重置为初始状态。失败计数器保存在热 Lambda 函数的内存中,因此不会在并发的调度容器之间共享,并在新任务启动时重置。在交错的多租户负载下,断路器可能不会触发,因此我们将其视为尽力而为的后备机制而非保证。无论哪种情况都不会丢失任何内容:下一次定时运行会拾取已重置的文章,而触发的断路器则表明某个服务依赖需要优先关注。
让 Amazon Bedrock 在大规模下保持可靠,并提升文章质量
工程工作的重点在于并发运行数万次模型调用并共享服务配额。管道通过 Amazon Bedrock 模型推理调用 Anthropic Claude Sonnet 进行生成和改进,使用 Amazon Titan Text Embeddings V2 生成去重向量。关于各 AWS 区域的模型可用性,请参阅按 AWS 区域划分的受支持模型。
让模型调用保持在限额之内
每次执行都设有硬性的挂钟超时,因此响应缓慢不会让工作人员无限期地保持占用状态。
自动重试与退避——Amazon Bedrock 客户端以自适应模式运行,遇到限流时自行重试,对较长的内容改进调用采用指数退避策略。
护栏回退——我们在模型输出上运行 Amazon Bedrock 护栏,以过滤非预期内容。护栏是一项生产控制措施,而下面的回退是一种弹性措施,确保在正常条件下护栏持续生效,而非暗示它是可选的。
护栏 API 有自己的速率限制。如果它被限流,流水线会在不使用护栏的情况下处理文章,并记录一条警告而不是失败,这样在流量高峰期间流程仍能继续推进。在代码中,这个回退是模型调用包装器中的一小段:
try:
return converse_with_timeout(kwargs, BEDROCK_CALL_TIMEOUT)
except ClientError as e:
if "ThrottlingException" in str(e) and guardrail_config:
log.warn("Guardrail throttled, retrying without guardrail")
del kwargs["guardrailConfig"]
return converse_with_timeout(kwargs, BEDROCK_CALL_TIMEOUT)
raise第四项控制处理截断输出。内容改进响应有 token 预算,长文章可能触及上限,导致 JSON 响应被截断。系统检测到“因 token 上限而停止”的信号后,会以双倍预算重试,直到达到模型的上限。短文章永远不会触发这条路径,因此常见情况下无需为安全网付出任何代价。
改进前后的质量评分
并非每篇文章都需要改进,改进也并非总是有益。由质量评分来决定。每篇文章按十个加权维度评分,权重从高到低排列:
- 完整性
- 可操作性
- 结构
- 连贯性
- 可读性
- 自助服务价值
- 时效性
- 自动化就绪度
- 语法
- 安全性
加权总分产生一个分数,阈值决定文章是原样达标,还是需要进入改进流程。阈值是可配置的,因此客户可以对生成内容设定比导入内容更高的标准。
低于阈值的文章会进入内容改进环节,同样在 Amazon Bedrock 上运行。这一步有一个实际挑战:被要求改进文风的模型往往也会改动图片标签和超链接,并导致它们损坏。占位符解决了这个问题。改进之前,系统将每个图片和链接替换为编号 token,围绕这些 token 改进正文,之后再将真实媒体换回。模型从未看到原始标记,因此标题和结构得以保留。
在代码中,这是围绕改进调用的一对函数。第一个函数将每个媒体标签和链接替换为编号 token,并记录它移除了什么。第二个函数在模型返回后将原始内容放回:
# 改进之前:将媒体/链接替换为 [IMG_N] / [LINK_N] token
html_with_placeholders, placeholder_map = extract_placeholders(article_html)
enriched = improve_with_bedrock(html_with_placeholders) # 模型从未看到原始标记
# 改进之后:原位恢复确切的原始标签
restored_html, missing = restore_placeholders(enriched, placeholder_map)因为模型只看到 [IMG_1] 或 [LINK_3],它不可能破坏 URL 或图片引用。恢复步骤确保发布文章的媒体与开始时完全一致。
改进之后,文章会再次评分。只有新版本得分超过原版时才保留新版本,否则维持原版。这种前后对比检查让流水线能够自动改进内容,而不会悄悄让知识库变得更差。
安全地服务众多客户
系统在共享基础设施上运行多个客户,而知识库恰恰是客户期望被严格隔离的数据。隔离从设计之初就内置其中:每个客户拥有与其内容相关的所有内容的独立副本:
- 一个配置档案
- 一个 Amazon S3 Vectors 索引
- 一组模型提示词
- 一个 Amazon Bedrock 护栏
- 一个 AWS KMS 加密密钥
由于这些资源是按客户隔离的,每个客户的数据都保持在自己的边界内。重复检查仅针对该客户的索引运行,内容改进使用该客户的提示词,数据使用该客户的密钥加密。不存在任何共享池,让一个客户的文章出现在另一个客户的结果中。
接入新客户不需要编辑中央列表。系统在运行时从数据目录中发现客户,因此添加一个客户只需配置其资源,无需更改流水线代码。
结果与经验教训
这里的行为来自我们的内部测试,并非有保障的服务水平。由于每个客户都流经自己的 Amazon SQS FIFO 消息组,因此增加一个客户只是增加一条并行工作流,而不会拖慢其他客户。您自己的吞吐量将取决于文章大小、模型延迟以及您的 Amazon Bedrock 配额。
一次有代表性的运行展示了您可以预期的模式。大多数文章在第一次处理时就完整通过,一小部分被保留以待改进,更小的一部分作为重复内容被移除。该次运行完成时没有死信队列消息,也没有超时。少数文章触及了内容改进的令牌限制,被自动重置,并在下一次运行时以更高的预算重试,而不是失败。最后这种情况很重要,因为它展示了弹性控制如何将原本的硬性失败转化为自动重试。
四条经验值得注意。将向量索引复用为重复检测器,把一个难题变成了最近邻查询。通过 Step Functions 传递 Amazon S3 指针而非文章正文,消除了一类状态大小故障。在改进前后两侧都进行质量评分,使得自动运行变得安全。将护栏限流视为警告,使管道在负载高峰期间保持健康。更大的要点在于闭环本身:生成的内容为策展提供输入,而策展又为下一轮生成提供基础,因此知识库会随着系统的运行而不断改进。
清理资源
本解决方案中的资源均需计费,因此请在完成后将其移除,以避免持续产生费用。删除两个 AWS CDK 堆栈(一个用于知识库生成,一个用于知识库策展)即可移除大部分资源。这包括 AWS Lambda 函数、AWS Step Functions 状态机、AWS Fargate 上的 Amazon ECS 服务、Amazon SQS 队列以及 Amazon DynamoDB 表。
- Amazon S3 Vectors 索引和向量存储桶 – 先删除每个客户的索引,再删除向量存储桶。
- Amazon S3 存储桶 – 清空并删除源存储桶、输出存储桶和管道存储桶。
- Amazon Bedrock 护栏 – 如果堆栈未移除每个客户的护栏,请手动删除。
- AWS KMS 密钥 – 安排删除每个客户的密钥。
- Amazon DynamoDB 表 – 如果您禁用了时间点恢复保留,请确认指标表和文章状态表已被移除。
有关确切的删除命令,请参阅存储库 README。
结论
ITSM 工单墓地是一个看起来像数据问题的知识问题。解决方案早已存在,却被困在无人能够复用的地方,旁边是一个衰败速度远超任何团队手工策展能力的知识库。KnowledgeForge 利用 AWS 上的生成式 AI 弥合了这一差距。它通过 Amazon Bedrock 将工单挖掘成文章,通过 Amazon S3 Vectors 捕获重复内容,并通过 AWS Step Functions 编排整个流程。知识管理员始终掌控着最终上线的内容。
- 使用 Amazon S3 Vectors 文档创建向量索引。
- 嵌入您自己文章的一个样本并加载向量。
- 运行前面展示的最近邻查询以标记重复内容。
- 添加 AWS Step Functions 分布式映射以批量处理文章。
- 叠加“评分—改进—重新评分”的质量门控。
完整代码可在 GitHub 上的 aws-samples/sample-knowledgeforge 存储库中获取。全文中的代码示例展示了每种模式的承重部分,可随时适配到您自己的知识库。
如需了解更多信息,请参阅 Amazon Bedrock 用户指南、AWS Step Functions 开发人员指南和 Amazon S3 用户指南。
关于作者