AWS 博客详解如何在 Bedrock Managed Knowledge Base 上构建企业级多租户文档问答应用,覆盖数据隔离、异步索引生命周期和生产运维最佳实践。
多租户 AI 智能体聊天助手已成为大型客户的常见需求,而文档问答需求位居榜首。用户上传一份合同、报告或产品手册,然后立即或日后针对其中内容进行研究或提问。会话式界面构建起来很简单,但背后的多租户 AI 智能体检索系统却并非如此。
每个租户的文档必须与所有其他租户的文档隔离开来,而且这种边界必须基于经验证的 identity(身份)来强制执行,而非依赖客户端发送的值。AI 智能体检索使问题更加复杂。AI 智能体会将一个问题分解为多个子查询并运行多个检索,而这些跳转中的每一个都必须携带租户过滤器,否则隔离就会被破坏。此外,你仍然需要一个向量和全文搜索引擎、一条解析和嵌入多种模态内容的摄取管道,以及一个同步的索引。对于一个着手交付此功能的团队而言,这是一项需要构建、保护和运营的大量基础设施工作。
借助 Amazon Bedrock Managed Knowledge Base,你可以减轻这些无差异的工作。该服务管理摄取、存储、嵌入和排名,因此无需配置基础设施或监控容量。除了基础设施之外,它还提供内置的 AI 智能检索功能,使用迭代式规划和多跳检索来回答复杂问题,并在每一次跳转中都尊重访问权限。通过自定义连接器直接摄取,你的应用程序将文档直接发送到知识库,并在数秒内变得可检索。
在本文中,我们展示了一种基于 Amazon Bedrock Knowledge Bases 构建的多租户 AI 智能体文档聊天应用程序的架构。该解决方案有两条数据流:文档摄取和会话检索。我们将描述这两条数据流,以及异步索引生命周期、每用户数据隔离和规模化运营最佳实践。我们还提供了一个配套代码库,方便你在自己的账户中部署该代码。
该解决方案解决了引言中概述的挑战。它提供了一种多租户文档聊天体验,其中每个用户都可以上传自己的文档,并立即针对这些文档提出有依据的问题,而无需团队去构建检索栈或保持各用户内容相互隔离的隔离逻辑。
当用户提问时,应用程序调用 Amazon Bedrock Knowledge Bases 上的 AI 智能检索 API。该 API 运行一个 AI 智能体工作流来决定如何回答问题。对于简单查询,它发出单一检索;对于复杂或多部分问题,它将问题分解为子查询并在生成响应之前运行多次检索(多跳检索)。
在这两种情况下,响应都以检索到的段落为依据并包含引用。这种架构易于运营的原因是,知识库拥有负责检索和生成的组件:决定查询什么的规划步骤、向量索引、排序器以及生成最终响应的基础模型。你的应用程序只负责特定于你产品的部分,例如上传体验、聊天 UI、身份验证、每用户隔离和任何自定义业务逻辑。
该解决方案由以下关键组件构成:
Amazon Bedrock Managed Knowledge Base:抓取、解析、存储和检索多模态内容。它为文本、向量、元数据以及 CSV 和 Excel 文件等结构化内容配置和管理检索基础设施,包括托管解析、嵌入和索引。自定义连接器数据源直接摄取用户上传。
Amazon API Gateway 和 AWS Lambda:公开上传、状态和聊天端点并运行应用程序逻辑。
Amazon Cognito:对用户进行身份验证,并提供应用程序用来隔离每个用户文档的经验证身份。
Amazon Simple Queue Service(Amazon SQS):将上传与摄取解耦,吸收上传突发,并将反复失败的消息路由到死信队列。这使得上传端点无论摄取压力如何都能保持响应。
Amazon DynamoDB:跟踪每个文档的索引状态,以便应用程序可以向用户显示文档何时就绪。
Amazon Simple Storage Service(Amazon S3):对超过内联限制的文件进行暂存,并在 Amazon CloudFront 后面托管单页应用程序。
下图展示了这个解决方案的架构。
图 1:多租户文档聊天解决方案的架构
工作流由以下步骤组成,编号与图中的标注相对应:
用户通过 Amazon Cognito 登录并向应用程序上传文档。每个请求都携带用户的 JSON Web Token(JWT),Amazon API Gateway 对其进行验证。应用程序在服务器端派生用户身份,而不是信任客户端发送的值。
应用程序从经验证的 JWT 中提取用户身份,并将其与文档(或其 S3 引用)一起包含在 SQS 消息中。它立即向用户返回响应,这样浏览器在后台摄取运行时不会被阻塞。最大 6 MB 的文件在 API 请求中以内联方式发送。较大的文件先上传到 Amazon S3,SQS 消息携带 S3 URI,以便 Amazon Bedrock 可以直接从 S3 读取文件。
工作线程 Lambda 函数从队列中读取消息,并使用调用者的 Amazon Cognito sub 设置的 user_id 元数据属性标记文档。经验证的上传处理程序将该值放在消息上。然后工作线程调用 IngestKnowledgeBaseDocuments API,Amazon Bedrock 异步地对文档进行分块、嵌入和索引。
工作线程在 Amazon DynamoDB 中记录每个文档的状态。浏览器轮询一个从 DynamoDB 读取的状态端点并更新 UI。用户无需刷新页面即可看到每个文档从已接收变为处理中再变为就绪的状态。
要提问时,用户将其发送到应用程序。
为了响应这个问题,应用程序使用对 user_id 的显式等于过滤器调用 AgenticRetrieveStream API。应用程序从经验证的 JWT(而非请求体)在服务器上构建过滤器值,因此用户只能检索自己的文档。知识库返回匹配的段落,基础模型生成带引用的响应,应用程序将其流式传输回用户。
以下各节追踪一个请求通过该解决方案的完整路径:我们更深入地了解摄取路径、索引生命周期、每用户隔离和检索。
用户上传的直接摄取
由于用户是在应用程序运行期间上传文档,因此应用程序通过自定义连接器数据源而非 S3 连接器直接摄取文档。S3 连接器专为批量摄取定期同步刷新的文档而设计,而同步可能会覆盖或删除用户刚刚添加的文档。通过 IngestKnowledgeBaseDocuments API 直接摄取没有同步,因此文档会持久保留直到你删除它。你还可以分配自己的文档 ID,这使得每用户管理和更新变得简单。知识库保留每个原始文件的副本,你可以通过 GetDocumentContent API 检索。因此,你无需运营单独的文档存储,用户可以打开响应背后的源文档。
应用程序根据文件大小选择两条摄取路径之一。最大 6 MB 的内联限制的文件作为字节在 API 调用本身中发送,这涵盖了大多数文本文档、合同和报告。较大的文件(文本最大 50 MB)先暂存到 Amazon S3,然后通过其 S3 URI 按引用摄取。大小路由器在服务器上应用此规则,因此路径对用户透明,两条路径在同一个知识库上汇合。
有两个 API 行为值得在设计中考虑。首先,因为你可以设置文档 ID,用同一个 ID 重新摄取文档会就地更新而不是创建重复,这正是你希望用户替换文件时的行为。你的应用程序拥有用户文件与其文档 ID 之间的映射。在参考实现中,跟踪索引状态的同一个 DynamoDB 表也存储了 (user_id, filename) → document_id 的映射,因此当用户重新上传文件时,应用程序会查找现有 ID 并重用它。(没有部分更新。编辑即完整重新摄取。)其次,单个 IngestKnowledgeBaseDocuments 调用最多接受 10 个文档,因此工作线程可以将多个摄取作业打包到单个请求中。我们在最佳实践部分介绍如何使用此功能。
文档索引生命周期
IngestKnowledgeBaseDocuments API 是异步的。它立即返回一个 STARTING 状态,但文档在 Amazon Bedrock 完成解析、嵌入和索引之前无法被检索。每份文档会经历五个状态,只有到达 INDEXED 状态时才能完全可查询,如下表所示。
索引时间取决于文档类型。下表展示的是我们对空闲知识库中小文档(5 MB 以下)进行测试时观察到的值。时间会因文档大小、内容复杂度、所在区域以及知识库的负载而有所不同,这些数字并非服务级别承诺。请将其作为设计时的量级参考,而非保证的延迟。
在负载情况下,文档还会在 PENDING 状态下等待处理槽位,因此到达 INDEXED 状态所需的时间会随摄取队列的深度而增长。
应用程序通过轮询 GetKnowledgeBaseDocuments API 来获取每份文档的状态,并在 DynamoDB 中记录下来,在 UI 上展示为已接收、处理中和就绪。文档一旦到达 TEXT_INDEXED 状态即可搜索,因此应在该阶段将其标记为就绪,而不必等待 INDEXED 状态。两种状态的差异仅对 PDF 和其他多模态内容有意义。在 TEXT_INDEXED 阶段,文本块已经可查询,满足大多数检索需求。在 INDEXED 阶段,多模态元素(如 PDF 中的图像和表格)也可查询。如果将接受阶段(STARTING)视为可搜索,则对仍在索引中的文档发出的查询会返回空结果。
在多租户应用程序中,一个用户的文档绝不能出现在另一个用户的结果中。你可以通过以下两种方式之一来强制执行这一边界:为每个租户配置独立知识库,或使用一个共享知识库并通过调用方身份对每次查询进行作用域限定。对于拥有大量最终用户的应用程序,共享知识库是正确的选择,因为它避免了每个账户的知识库配额、多个小型索引的基础成本,以及注册时创建知识库的预配置延迟。Amazon Bedrock Knowledge Bases 支持在单次调用中查询多个知识库。该功能旨在为单个用户组合不同的知识领域,而非用于租户之间的隔离。当你有少量大型租户且有严格分离需求时,每个租户独立知识库仍然合理。对于用户级多租户,共享知识库扩展性更好,配置也更少。
如工作流所示,工作进程为每份文档添加 user_id 元数据属性,应用程序在每次查询时都基于同一属性进行过滤。过滤值在服务器端根据已验证的 JWT 构建。这种服务器端派生是安全边界。知识库也可以从问题的措辞中推断过滤条件,但这种推断是一种相关性功能,而非访问控制。隔离必须来自应用程序根据已认证身份构建的显式过滤。作为深度防御,参考实现在每次请求前确认过滤条件作用域限于调用方,并丢弃任何返回的 user_id 与调用方不匹配的块。
未认证的请求返回 HTTP 401 响应,具有有效认证但无可解析 sub 的请求返回 HTTP 403 响应。对于需要服务本身强制执行访问控制的受监管工作负载,知识库还支持在查询时根据 userContext 评估的文档级访问控制列表(ACL)。这将强制执行从应用程序代码中分离出来。
检索是两种流程中更直接的一种。AgenticRetrieveStream API 在单次调用中完成完整的对话轮次。它将问题分解为子查询,对每个子查询应用用户级过滤,并在启用 generateResponse 时流式返回有依据的、带引用的响应。它清晰地映射到聊天界面,且首次生成 token 的等待时间短,无需自行编排检索和生成流程。Managed Knowledge Base 不支持 RetrieveAndGenerate API。当你需要更多控制时,例如为租户定制提示词或使用特定模型,请使用 Retrieve API 获取段落,并自行调用 Converse API,传入相同的用户级过滤。要展示引用来源,GetDocumentContent API 会返回原始文档以供预览或下载。
以下实践可确保随着使用量增长该流程的可靠性。
通过队列将上传与摄取解耦。对于低负载工作负载,你可以直接从上传处理程序调用 IngestKnowledgeBaseDocuments。对于任何预期有多用户并发上传的应用程序,请在上传端点和摄取之间放置一个 Amazon SQS 队列。上传端点接收文件,向队列写入摄取任务后立即返回,这样浏览器不会在摄取阶段被阻塞。工作进程 Lambda 函数从队列中读取,并将最多 10 份文档打包到每次 IngestKnowledgeBaseDocuments 调用中——这是当上传同时到达时摄取吞吐量的主要调节杠杆。例如,当大约 500 名用户在同一时刻各自上传一份文档时,工作进程将 500 个排队的任务转换为大约 50 个批处理的 API 调用。反复失败的消息会被路由到死信队列以供调查。这种设计吸收了突发流量,在一处实现了摄取调用速率的计量,并使上传端点无论下游背压如何都能保持响应。关于当前的摄取吞吐量限制,请参阅 Amazon Bedrock quotas 文档。
以摄取上限而非检索上限为规划依据。摄取和检索的扩展方式不同。Retrieve API 支持每知识库每秒 25 次查询(QPS)的突发流量,或持续 10 QPS,远超对话工作负载,因此很少成为约束。摄取吞吐量(如前所述)足以支持交互式上传,但对现有存储库的批量迁移会使其饱和。对于这些场景,请使用 S3 连接器和计划同步功能,该功能专为大型语料的一次性加载设计,且不会与实时用户上传竞争。
将并发限制视为可重试条件。当你超过并发限制时,Amazon Bedrock 返回的是 ValidationException,而非 ThrottlingException。仅重试限流错误的重试分类器会将其视为致命错误并丢弃文档。
监控预测上限的信号。追踪摄取成功率、到达 INDEXED 状态的时间(P50 和 P99 百分位)以及检索延迟。到达 INDEXED 状态的时间上升是摄取管道接近其吞吐量限制的最早指标,远在任何请求开始失败之前。
自行持久化对话历史。AgenticRetrieveStream API 通过 messages 参数接受先前的对话轮次以支持多轮上下文,但它不会在调用之间持久化这些内容。将对话历史存储在你自己的数据存储中(如 Amazon DynamoDB),并在每次请求时传递相关轮次。在应用程序中维护这些历史也意味着你可以像对文档一样对对话历史强制执行用户级隔离。
解决方案的成本取决于你的模型配置。使用托管模型时,Managed Knowledge Base 仅按存储和检索计费(按调用计费,而非按 token 计费),摄取不产生额外费用。如果你选择了 Amazon Bedrock 模型,则需要为嵌入 token(摄取时)以及使用智能体检索时的编排和生成 token 付费。关于当前费率,请参阅 Amazon Bedrock pricing 页面。
支持性服务(AWS Lambda、Amazon API Gateway、Amazon SQS、Amazon DynamoDB 和 Amazon S3)在中等规模下仅占总成本的很小一部分。
在这篇文章中,我们详细介绍了构建在 Amazon Bedrock Knowledge Bases 之上的多租户智能体文档聊天应用程序的架构。该服务负责处理企业级多模态智能体检索基础设施,因此你的团队可以专注于你产品的特有部分。你的团队负责上传和聊天体验、身份验证,以及对每个检索进行作用域限定的用户级隔离——包括智能体计划每一步的隔离。
要开始使用,请在你的账户中部署 GitHub 仓库中附带的示例,并将其作为你自有文档聊天应用程序的基础。
要深入了解 Amazon Bedrock Managed Knowledge Base,请参阅以下博客文章:
Build enterprise search for agents with Amazon Bedrock Managed Knowledge Base.
Agentic retrieval for Amazon Bedrock Managed Knowledge Base.