跳到正文
AWS Machine Learning Blog· Prabhakar Chandrasekaran·· 3 小時前精選AI 評分62

AWS CDK 如何在 Managed Amazon Bedrock Knowledge Base 上構建智能體檢索

Build agentic retrieval on a Managed Amazon Bedrock Knowledge Base with CDK

AI 導讀

AWS Machine Learning Blog 示範以 Python AWS CDK,在 Managed Amazon Bedrock Knowledge Base 上構建跨兩個知識庫的智能體檢索系統。

推薦理由

文章展示如何用 CDK 管理跨堆疊依賴,並把跨知識庫檢索、追蹤與評估一併部署,提供企業檢索系統的實作路徑。

正文 · 繁體中文

本文使用 AWS Cloud Development Kit (AWS CDK),在 Managed Amazon Bedrock Knowledge Base 上建置企業級代理式檢索。要了解這項建置的價值,不妨先看看一般的檢索增強生成(RAG)在哪些情況下會失效。大多數 RAG 系統的運作方式都相同:將問題轉換為嵌入向量,從單一索引擷取最相近的區塊,交給模型,再傳回答案。一次檢索、一次生成。對很多問題來説,這種設計恰如其分,無須建置更複雜的系統。

它的失效方式很容易辨認。若問題的答案涉及兩個語料庫,單次檢索可能只會返回模型所需資料的一半;這比甚麼也不返回更糟,因為答案讀來流暢,卻不完整。若問題的適合資料來源取決於問題本身,單一索引便沒有機制可作出選擇。若問題需要在看到首個結果後再次查閲語料庫,系統便無法進行這第二次查閲。

企業級代理式檢索透過讓推理代理參與其中,解決上述三種問題。代理會決定是否進行檢索、要查閲哪個知識庫,以及在撰寫答案前是否需要再次檢索。這正是Amazon Bedrock Knowledge Bases的演進方向。Managed Knowledge Base 推出後,檢索不再只是一次嵌入並擷取資料的呼叫,而是成為代理式功能:支援多輪規劃、由工具驅動的檢索,以及有根據並附有引文的答案。AgenticRetrieveStream API 將這些功能作為一級服務功能提供,而不是要你自行組裝。這種做法確實可行,但也帶來更棘手的營運問題。單次執行的管道可以透過閲讀程式碼來推敲;能夠反覆推理和檢索的代理,則會因應每個問題走上不同路徑。預設情況下,你既看不到它採取的路徑,也無從得知它產生的答案是否可靠。可觀測性不再只是錦上添花,而是瞭解系統是否正常運作的唯一方法。

2024 年 8 月,使用 Amazon Bedrock Knowledge Bases 和 AWS CDK 建置端對端 RAG 解決方案以 CDK 應用程式部署了單次執行的設計:包括 Amazon Simple Storage Service (Amazon S3) 語料庫、Amazon OpenSearch Serverless 集合和索引、知識庫,以及資料來源;這些資源以 CDK 堆疊佈建,並由你手動安排部署次序。自文章發布以來,已有三項變化。

  1. Amazon Bedrock 現在提供受管理的知識庫(Type: MANAGED),由服務自行負責資料擷取、儲存、索引和檢索。文章中佈建的 OpenSearch Serverless 集合和索引,現在不再需要你建立、擴充或支付 OpenSearch Compute Units (OCUs) 費用。
  2. Amazon Bedrock AgentCore 提供代理式功能的另一半:Gateway 可將每個知識庫公開為模型上下文協定(MCP)工具;Runtime 可託管推理代理;AgenticRetrieveStream 則會在內部重新排序,並返回經綜合整理且附有引文的答案。代理式檢索只適用於 Managed Knowledge Base。
  3. 可觀測性與評估方案如今已可直接配置,而非之後才加裝。這套方案隨附兩個 Amazon CloudWatch 儀錶板,涵蓋七層遙測資料,並提供兩種評估方式:按需評估及持續評估,全部來自同一部署。

本文會以 Python 編寫的單一 AWS CDK 應用程式建構這套系統:一個代理程式可在兩個知識庫之間路由,透過 Gateway 擷取資料,並提供有根據且附有引用來源的答案,同時為每一層行為加入監測。只需執行一個命令即可部署所有元件,CDK 會推導部署次序。

如果你讀過2024 年的文章,從 Amazon S3 儲存貯體到知識庫的流程會似曾相識;其後的部分則全是新內容:不再使用向量儲存庫,檢索改採代理式流程,而應用程式配置的資源中,約有一半用來呈現代理程式的操作情況。如果你未讀過,本文內容亦完整獨立。

以下展示相關服務,以及一條問題經過這些服務的路徑:代理程式會決定是否需要檢索,以及要查閲哪個知識庫;Gateway 會將每個知識庫公開為可供呼叫的工具;Managed Knowledge Bases 負責搜尋及引用資料;循環會按問題需要重複執行。代理程式沿途的所有操作都會記錄至 Amazon CloudWatch。

Agent routing a question across two managed knowledge bases through the Gateway, with every step landing in Amazon CloudWatch

圖 1:涉及的服務,以及單一問題經過這些服務的路徑

背景

開始逐步講解前,先了解三件事會有所幫助:令檢索成為代理式檢索的特點、Managed Knowledge Base 為何是合適的基礎,以及為何應從設計之初便納入可觀測性與評估,而非日後才加裝。

由 RAG 走向企業級代理式檢索

傳統檢索增強生成(RAG)只會執行一次檢索及一次生成。企業級代理式檢索則會加入推理代理,由它決定是否需要檢索及要檢索甚麼,並可多次檢索以完善結果、選擇相關的知識庫(語義路由),然後才撰寫有根據且附有引用來源的答案。使用 Managed Knowledge Base 時,這是服務內建的功能:AgenticRetrieveStream API 會執行多輪規劃、進行檢索並傳回附有引用來源的答案,無需在原始向量搜尋之上自行建立及維護協調層。這能為複雜問題帶來更好的答案,但也令系統更複雜、更難以運作,正因如此,可觀測性與評估從一開始便已納入其中。

Managed Knowledge Base 與自行管理知識庫的比較

Amazon Bedrock 現時提供Managed Knowledge Base(類型:MANAGED):Amazon Bedrock 會為你管理資料匯入、儲存、索引及檢索,預設亦會使用服務管理的模型進行嵌入及重排序,因此無需配置、擴展或修補向量資料庫。這與客戶自行管理(DIY)知識庫不同;使用後者時,你須自行選擇及運作向量儲存庫(例如 Amazon OpenSearch Serverless)。

對這套方案而言,以下兩項差異最為重要:

功能 Amazon Bedrock 管理 客戶自行管理(DIY)
代理式檢索(AgenticRetrieveStream) ✅ 支援 ❌ 不支援
AgentCore Gateway 整合 ✅ 支援 ❌ 不支援
資料儲存區 自動擴展,由 Amazon Bedrock 全面管理 由你配置、擴展及維護
嵌入 + 重排序 內置託管模型,無需額外費用 由你設定
需要管理的基礎架構 無 向量資料庫 + 更多

由於只有託管知識庫提供代理式檢索及 AgentCore Gateway 連接器,因此它自然成為企業級代理式檢索的基礎。這亦代表 Amazon Bedrock 會代你管理儲存和索引,因此在此設計中,無需佈建 OpenSearch Serverless 集合或 OCU 容量。如果你想自行選擇並操作向量儲存庫,例如重用現有的 OpenSearch Serverless 集合,或滿足特定的資料駐留、調校或合規要求,客戶管理選項仍是合適之選。託管知識庫正是讓企業級代理式檢索成為可能的關鍵。

為何需要可觀測性與評估

代理式系統在正式環境中,光是返回答案並不足夠。你需要了解系統的運作情況(延遲、呼叫量、Token 用量)、檢索和答案的質素,並持續取得這些指標。本方案提供兩個 CloudWatch 儀錶板,涵蓋七層遙測資料;另有兩種評估方式(按需和持續),全部由同一個 CDK 應用程式佈建。答案依據、引文及評估層亦有助負責任地使用。附有引文的答案可追溯至來源段落,讓回應保持可供審核;忠實度和正確性評分則有助你及早發現答案偏離來源,而非等到正式環境中才察覺。

為何這個方案特別適合使用 CDK

任何基礎架構即程式碼工具都能建立這些資源。CDK 在此方案中發揮作用,有一個與這種架構直接相關的原因:四個堆疊之間有大量交叉引用。Gateway 需要兩個知識庫 ID。代理程式需要 Gateway 的 URL 和 ARN。儀錶板則需要知識庫 ID、Gateway ARN,以及代理程式執行環境 ID;共有七個值跨越堆疊邊界,每個值都是某項指標的維度或某個連接器的目標。

若以原始範本編寫,就需要一組堆疊匯出和跨堆疊查詢,並靠人手保持一致;還要有一個按正確次序部署並逐步傳遞輸出的指令碼。只要有任何名稱更改,兩者便會立即出現偏差。在 CDK 中,你只需傳入 construct,匯出項目和依賴關係邊便會由這個傳遞動作自動推導出來。2024 年的方案有三個堆疊,依賴鏈大致呈線性。當架構擴展至四個堆疊,並有七個值在堆疊間傳遞時,這種差異便不再只是風格上的分別。

方案概覽

以下展示單一問題如何從頭到尾經過整個系統。值得仔細看一遍,因為文章其餘部分會由左至右逐步講解這個流程。

下圖展示端到端的代理式檢索工作流程。用戶的問題進入 AgentCore Runtime 上的代理程式,並由它經 AgentCore Gateway 路由至兩個 AgenticRetrieveStream 工具之一;每個工具對應一個託管知識庫,分別是金融和天氣知識庫,兩者均從 Amazon S3 匯入資料。所選工具會返回一個有根據並附有引文的答案,而每個步驟的資料都會串流至 Amazon CloudWatch 和 AWS X-Ray。編號標記對應下文的流程説明。

Flow diagram: user question to AgentCore Runtime, out through AgentCore Gateway to two AgenticRetrieveStream tools backed by financial and weather managed knowledge bases fed from Amazon S3, returning a cited answer, with every step streaming to CloudWatch and X-Ray.

圖 2:單一問題的端到端代理式檢索工作流程

圖中的編號步驟對應以下工作流程。

步驟 0 — 部署時一次性執行。 提出任何問題之前,Amazon S3 中的每個語料集都會載入各自的 Managed Knowledge Base:Amazon Bedrock 會自動解析內容、分塊、生成嵌入向量並建立索引。這項工作只會在堆疊部署時執行一次,不屬於每個問題的處理流程,因此圖中以虛線箭頭表示,並標示為步驟 0。之後,每個問題都會依序經過步驟 1–6:

  1. 用戶向託管於 Amazon Bedrock AgentCore Runtime 的 Agent 提交問題。Runtime 會透過 OpenTelemetry (OTEL) spans 自動為整個推理與行動循環加入儀表化,因此係統從第一次呼叫起便具備可觀測性。
  2. Agent 的推理模型會規劃並選擇要查詢的知識庫。由於每個知識庫都以獨立的檢索工具形式提供,Agent 會選取主題與問題相符的工具,例如財務或天氣,而不是搜尋混合在一起的索引。
  3. 所選工具呼叫會透過 MCP 由 AgentCore Gateway 轉送,並由 Agent 的 IAM 任務角色授權及以 SigV4 簽署,接着呼叫該知識庫的 AgenticRetrieveStream API,查詢 Managed Knowledge Base。
  4. AgenticRetrieveStream 會處理知識庫內的工作:將問題拆解為子查詢,從 Amazon Bedrock 管理的資料儲存區(由 Amazon S3 中的語料集載入)反覆檢索,並整理出有根據、附有引文的答案,再透過 Gateway 以串流方式傳回。
  5. Agent 會檢查傳回的上下文是否足夠。如果不足,便會再次選擇路由並檢索,然後撰寫最終答案;如果足夠,便會將附有引文的答案傳回用戶。
  6. 整個過程中,Runtime 會將 spans、token 數量及指標傳送至 Amazon CloudWatch 和 AWS X-Ray,填入七個可觀測性層,並提供資料給按需及持續評估評分。

整個工作流程由一個 CDK app app.py 實作,並宣告四個堆疊。你無須選擇執行順序;CDK 會根據你傳入的 construct 參照推導順序:

kb_stack = KnowledgeBasesStack(app, f"{project}-kb", env=env)

gateway_stack = AgenticGatewayStack(
    app, f"{project}-gateway", env=env,
    financial_kb=kb_stack.financial_kb,  # ← the reference creates the dependency
    weather_kb=kb_stack.weather_kb,
)

agent_stack = AgentRuntimeStack(
    app, f"{project}-agent", env=env,
    gateway=gateway_stack.gateway,
)

DashboardsStack(
    app, f"{project}-dashboards", env=env,
    financial_kb=kb_stack.financial_kb,
    weather_kb=kb_stack.weather_kb,
    gateway=gateway_stack.gateway,
    agent_runtime=agent_stack.agent_runtime,
)

以上就是全部連接設定。這四個建構函式呼叫取代了匯出/匯入管理工作及部署指令碼。

# 堆疊 建立項目 備註
1 -kb S3 儲存貯體、語料集上載、兩個 Type: MANAGED 知識庫、資料來源、IAM、資料擷取 知識庫進入 ACTIVE 狀態,語料集完成載入
2 -gateway Gateway (AWS_IAM / MCP)、各知識庫的 AgenticRetrieveStream 目標 不需要 Cognito
3 -agent ECR、CodeBuild、在 Runtime 上執行且已加入儀表化功能的 Strands agent、輸出的日誌/追蹤資料、線上評估 約 8–10 分鐘(建立映像檔)
4 -dashboards agentic-observability + kb-observability 儀錶板 尚未有流量時為空

Agent 會執行推理與行動循環:先思考(呼叫大型語言模型 (LLM)),再決定要呼叫哪個知識庫工具,讀取 Gateway 傳回的內容,並經常再次檢索,然後撰寫附有引文的最終答案。Runtime 會自動為每個步驟加入儀表化,因此七個可觀測性層會根據實際流量逐步填入資料。

七個層級。L1 知識庫原生指標、L2 資料擷取、L3 代理式檢索品質、L4 Gateway/MCP 指標、L5 OTEL span 樹、L6 token 用量,以及 L7 評估分數。第 1、4 和 5 層會自動產生。第 3、6 和 7 層則由 driver notebook 發佈為自訂指標。

所有可調整的設定都在同一個檔案 config.py 中:

設定 説明 預設值
EnvSettings.PROJECT_NAME 每個堆疊和資源的名稱前綴 bmkb-obs-cdk
EnvSettings.ACCOUNT_REGION 部署所在的 AWS 區域 us-west-2(或你的設定檔所指定的區域)
KbConfig.EMBEDDING_MODEL_TYPE MANAGED(隨附)或 CUSTOM(自備 ARN) MANAGED
AgentConfig.MODEL_ID Agent 的推理模型、Layer 6 的支出 Claude Haiku 4.5
EvalConfig.SAMPLING_PERCENTAGE 線上評估抽樣率,請參閲免責聲明 100

更改 PROJECT_NAME 會建立一個使用獨立名稱的完整方案副本,因此兩個部署可以在同一個帳戶中共存。驅動 Notebook 會讀取同一個常數,因此會自動配合名稱變更,無須手動同步堆疊名稱。

描述數據集

方案隨附兩個小型語料庫,存放在存放庫的 data/ 之下:

  • 財務 — 合成的 Octank Financial 10-K(octank_financial_10K.pdf,約 198 KB)。
  • 天氣 — 一份真實、公開提供的美國國會研究處龍捲風報告(IF12695,tornadoes_report.pdf,約 560 KB)。

⚠ 關於數據: 財務語料庫是合成的。Octank 是一間虛構公司,而 10-K 是由模型生成的樣本數據(採用 CC0 授權)。它並非 真實財務數據。天氣語料庫是真實的美國政府公有領域作品,內容是一份國會研究處報告,可在 sgp.fas.org/crs/misc/IF12695.pdf 公開取得(美國政府作品不受版權保護)。如要使用自己的數據,只需將檔案放在 data/ 之下,並調整 config.py 中的前綴,無須作其他更改。

這兩個語料庫刻意採用不同領域,讓 Agent 必須將每個問題路由至正確的知識庫,呈現語義路由的重點。由於這些是 Managed Knowledge Bases,我們不需要設定分塊、嵌入或索引:匯入時,Amazon Bedrock 會自動剖析每份 PDF、將內容分塊、使用其受管理模型建立嵌入向量,並建立索引。

我們使用兩個獨立的知識庫,並透過 Gateway 將各自作為一個檢索工具提供,而非使用一個同時存放兩個語料庫的知識庫;這是刻意的選擇。為 Agent 提供兩個具名工具,令路由成為一個可觀察的明確推理過程:span tree 會顯示它針對特定問題選擇了哪個工具,而第 3 層的檢索質素指標會按知識庫分開,因此財務和天氣領域的精確率不會混成單一數字。若用一個工具涵蓋兩個語料庫,兩者的區別便會消失;路由決策會隱藏在單一索引的排名過程中,而所有質素指標都會變成兩個無關領域的平均值。將語料庫和工具分開,才能清楚瞭解 Agent 的行為;這正是這項練習的目的。

在 CDK 中,將語料庫放入 S3 的方式是使用 BucketDeployment:

s3deploy.BucketDeployment(
    self, "FinancialCorpus",
    sources=[s3deploy.Source.asset(str(ROOT / "data" / "financial"))],
    destination_bucket=self.source_bucket,
    destination_key_prefix=KbConfig.FINANCIAL_PREFIX,
)

BucketDeployment 值得了解,正是因為另一種做法看起來很方便:若不使用它,負責觸發資料匯入的自訂資源往往會加入上傳步驟,結果同一個資源便要負責兩項互不相關的工作。在這裏,它只需負責匯入。

受管理的資料匯入會自動掃描、分塊、建立嵌入向量,並為每份文件建立索引:每個知識庫各有一份文件完成索引,失敗數為零。

Managed ingestion result showing one document indexed per knowledge base with zero failures

圖 3:受管理的資料匯入結果;每個知識庫各有一份文件完成索引,失敗數為零

部署方案

本節將介紹如何用一個命令部署整個方案。完成先決條件後,cdk deploy --all 會依照 CDK 推導出的相依順序佈建全部四個堆疊,並自動傳遞所有跨堆疊值。

先決條件

  • 具備 Amazon Bedrock、AgentCore (Runtime + Gateway)、AWS Identity and Access Management (IAM)、CloudWatch、AWS X-Ray、Amazon Elastic Container Registry (Amazon ECR)、AWS CodeBuild、Amazon S3、AWS Lambda 及 AWS CloudFormation 權限的 AWS 帳戶。
  • 帳戶中有代理程式所用的模型(預設 us.anthropic.claude-haiku-4-5-20251001-v1:0)。
  • 已啟用 CloudWatch Transaction Search,讓 OTEL spans 寫入 aws/spans,供第 5 至 7 層使用。
  • Node.js 18+ 和 CDK CLI(npm install -g aws-cdk),以及 Python 3.13+。
  • 已為 CDK 完成 bootstrap 的帳戶和區域(cdk bootstrap),每個帳戶/區域只需執行一次。
  • 本機不需要 Docker;代理程式映像檔會由 CodeBuild 建置(ARM64)。

一個命令

要部署此方案,請複製存放庫、建立虛擬環境、安裝相依套件,然後執行 cdk deploy --all。請在終端機中執行以下命令:

git clone https://github.com/aws-samples/amazon-bedrock-samples.git
cd rag/managed-knowledge-bases/07-IaaC/managed-kb-observability-cdk/
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cdk bootstrap  # once per account/region
cdk deploy --all

首兩個命令會複製範例並進入專案目錄。接下來兩個命令會建立並啟用 Python 虛擬環境,以及安裝 CDK 應用程式的相依套件。cdk bootstrap 會為 CDK 準備帳戶和區域(每個帳戶/區域只需執行一次),而 cdk deploy --all 會部署全部四個堆疊。

帳戶和區域取自你的 AWS 設定檔(CDK_DEFAULT_ACCOUNT / CDK_DEFAULT_REGION),因此無須修改任何內容即可部署應用程式。

區域可用性:受管知識庫、代理式擷取(AgenticRetrieveStream)及 Amazon Bedrock AgentCore(Runtime 和 Gateway)並非在所有 AWS 區域均可使用。部署前,請確認目標區域提供以上所有服務,並相應設定 ACCOUNT_REGION(位於 config.py)。預設值為 us-west-2。如需查閲最新的可用性資訊,請參閲 Amazon Bedrock 和 Amazon Bedrock AgentCore 文件,以及 AWS 區域服務清單。

此版本沒有部署指令碼,這正是設計用意:cdk deploy --all 會巡覽它從 app.py 推導出的相依性圖,依序部署四個堆疊,並自動傳遞所有跨堆疊值。終端機會在每個堆疊完成時顯示其狀態:bmkb-obs-cdk-kb [1/4](預設 PROJECT_NAME),接著是 gateway [2/4]、agent [3/4],最後是 dashboards [4/4]。這個順序是推導而來,並非預先指定:它由堆疊之間的建構項目參照關係自然形成,因此新增一個使用現有輸出的第五個堆疊時,部署順序便會自動重新排列。

Stack -agent 會使用 CodeBuild 建置代理程式容器,因此此階段大約需要 8–10 分鐘。其餘三個堆疊所需時間較短。每個堆疊完成時都會顯示輸出,你可在此取得知識庫 ID、Gateway URL、執行階段 ARN,以及兩個儀錶板 URL。部署完成後,四個堆疊都已部署完成。以下螢幕截圖顯示成功執行 cdk deploy --all 後的 AWS CloudFormation 主控台。

AWS CloudFormation console listing four stacks — bmkb-obs-cdk-kb, -gateway, -agent, and -dashboards — each with status CREATE_COMPLETE.

圖 4:成功部署後的 AWS CloudFormation 主控台,四個堆疊的狀態均為 CREATE_COMPLETE

在主控台中,kb、gateway、agent 和 dashboards 這四個堆疊的狀態均為 CREATE_COMPLETE。每個堆疊的描述都顯示其在推導出的相依性順序中的位置 [n/4]。

關於長時間執行資源的説明

此方案中有兩項工作所需時間遠超過 AWS Lambda 函數 15 分鐘的執行上限,無法透過簡單輪詢來處理:知識庫擷取同步,以及 CodeBuild 映像檔建置。AWS CDK Provider 架構會以 on_event / is_complete 的方式處理這些工作:一個處理常式會啟動工作,另一個則會持續接受輪詢,直至回報工作完成。

cr.Provider(
    self, "IngestSyncProvider",
    on_event_handler=on_event,        # StartIngestionJob, return the job id
    is_complete_handler=is_complete,  # GetIngestionJob, report IsComplete
    query_interval=Duration.seconds(30),
    total_timeout=Duration.minutes(30),
)

沒有任何操作會阻塞執行;回傳至 CloudFormation 的回應協定由框架負責處理,而不必在每個處理常式中手動編寫;30 分鐘的時間預算則是個屬性,不需要另行設計方案去繞過。

啟動及測試

開啟 notebooks/01-drive-and-observe.ipynb,並由上而下執行(先執行 pip install -r requirements-notebook.txt)。它會讀取堆疊輸出,然後向已部署的 Agent 傳送針對不同主題的提示詞,每個 KB 使用一個工作階段,讓你在同一處查看回答和語意路由:財務問題會根據 Octank 10-K 作答,天氣問題則根據龍捲風報告作答;兩者都會自動路由至相應的 AgenticRetrieveStream 工具。

Notebook 會從堆疊輸出中找出所有所需資料,因此不必手動貼上任何內容:

# Stack names are derived from the same PROJECT_NAME the CDK app uses, so renaming the
# project in config.py cannot leave this notebook pointing at stale stacks.
from config import EnvSettings

PROJECT = EnvSettings.PROJECT_NAME
STACKS = {suffix: f'{PROJECT}-{suffix}'
          for suffix in ('kb', 'gateway', 'agent', 'dashboards')}

def outputs(stack_name):
    s = cfn.describe_stacks(StackName=stack_name)['Stacks'][0]
    return {o['OutputKey']: o['OutputValue'] for o in s.get('Outputs', [])}

Notebook 匯入的 config.py 與應用程式所用的相同,因此兩者對堆疊名稱的理解不會有分歧。

驅動程式會透過已部署的 Agent 傳送針對各個 KB 的提示詞。財務問題會路由至財務 KB,天氣問題則會路由至天氣 KB;兩者都會提供有根據並附有引用的回答。

Driver notebook output showing financial and weather questions each routed to the matching knowledge base with a cited answer

圖 5:針對各個 KB 的提示詞會路由至相應的知識庫,並各自提供有根據、附有引用的回答

Notebook 亦會根據 Agent 實際檢索及引用的內容,計算無參照的第 3 層檢索品質指標;不需要 ground truth 或額外評審模型,並會將指標發佈至 CloudWatch。

Per-KB Layer 3 retrieval-quality signals: retrieval utilization (precision proxy), grounded coverage (faithfulness proxy), duplicate rate, and retrieval-set counts

圖 6:各個知識庫的無參照第 3 層檢索品質指標

觀察:七層儀錶板

七層的資訊會在兩個儀錶板上呈現。堆疊會建立這兩個儀錶板,而送入流量後便會填入數據。以下截圖展示兩個儀錶板在 CloudWatch 主控台中的畫面。

CloudWatch dashboards list showing two dashboards: the end-to-end agentic-observability dashboard and the per-KB (BMKB) observability dashboard.

圖 7:CloudWatch 主控台中的兩個儀錶板,分別用於端對端 Agent 可觀測性及每個 KB 的可觀測性

兩個儀錶板都會顯示在 CloudWatch 主控台中:一個用於端對端 Agent 可觀測性,另一個用於每個 KB 的可觀測性(BMKB,Bedrock Managed Knowledge Base)。本節其餘部分會逐一説明各層所顯示的內容。

這個版本的儀錶板以具型別的物件建構,而非 JSON 字串。指標是 Metric,元件是 GraphWidget,而版面配置則是 Rows 清單:

cw.GraphWidget(
    title="L4 — Gateway metrics (MCP)",
    width=12, height=6, period=PERIOD, statistic="Sum",
    left=[
        self._gateway_metric("Invocations", gateway_arn, "tools/call Invocations"),
        self._gateway_metric("SystemErrors", gateway_arn, "SystemErrors"),
        self._gateway_metric("UserErrors", gateway_arn, "UserErrors"),
        self._gateway_metric("Throttles", gateway_arn, "Throttles"),
    ],
)

實際好處不在於減少行數;dashboards_stack.py 長達 400 行,比功能相同的 DashboardBody JSON 還要長。好處在於,拼錯屬性名稱或使用無效的元件組合,會在 cdk synth(你的手提電腦上)約一秒內報錯。同樣的錯誤若寫在 DashboardBody 字串中,部署仍會成功,並在 AWS Management Console 顯示為故障元件;你只能查看畫面才會發現。

由於 Row 接受任何元件,文件説明便成為版面配置的一部分,而非會逐漸過時的 wiki 頁面。每個儀錶板都會在圖表之間穿插 TextWidgets:

[cw.TextWidget(width=24, height=7, markdown=self._l3_explainer())],
[
    self._quality_widget("L3 · Financial KB — agentic quality (reference-free, 0–1)", fin_id),
    self._quality_widget("L3 · Weather KB — agentic quality (reference-free, 0–1)", wx_id),
],

_l3_explainer() 會傳回一個 Markdown 表格,定義各項比率及其解讀方式。因此,説明 grounded_coverage 的元件會與繪製該指標的元件在同一次提交中一併交付;初次開啟儀錶板的讀者也不必猜測無參照指標代表甚麼。

儀錶板 A — 端到端代理式可觀測性。儀錶板首先説明各層的統計項目各不相同(對於 N 次查詢,你會看到約 N 次代理呼叫、約 2N 次檢索、約 3N 次 LLM 呼叫,以及約 5N 次 Gateway MCP 操作,讓代理式循環清晰可見),接着顯示知識庫指標(L1)、Gateway 指標及延遲(L4)、token 用量(L6);此外,由於代理使用 AgenticRetrieveStream,傳回的是經綜合整理並附有引文的答案,而非逐區塊評分,因此也會顯示內嵌定義、並按知識庫繪製的第 3 層無參照品質指標。

在儀錶板 A 上,第 3 層的無參照品質指標按知識庫分別繪製。首先是財務知識庫。以下圖表繪出其 retrieval_utilization、grounded_coverage 和 duplicate_rate。

CloudWatch line chart of the financial KB’s Layer 3 quality, plotting retrieval_utilization, grounded_coverage, and duplicate_rate on a 0 to 1 scale.

圖 8:財務知識庫第 3 層品質,繪出檢索利用率、有依據涵蓋率及重複率

天氣知識庫顯示相同的三項指標,並分開追蹤,確保兩個領域不會混為一個數字。

CloudWatch line chart of the weather KB’s Layer 3 quality, plotting retrieval_utilization, grounded_coverage, and duplicate_rate on a 0 to 1 scale.

圖 9:天氣知識庫第 3 層品質,與財務知識庫分開追蹤

兩張圖表分別繪出財務知識庫(左)和天氣知識庫(右)的檢索利用率、有依據涵蓋率及重複率,讓每個知識庫的檢索品質各自呈現,而不是平均成一個數字。

儀錶板 B — 按知識庫劃分(BMKB)的可觀測性。以下營運指標同時也決定開支,並按知識庫列出:索引大小(根據 S3 來源位元組數計算)、檢索量、代理式工具呼叫次數、工作階段 token 用量,以及按模型劃分的生成 token 用量;每項指標均附有內嵌説明。

以下截圖展示儀錶板 B 的四個指標元件,這些元件在執行完成後已填入數據。第一個元件顯示各知識庫的索引大小,根據 S3 來源位元組數計算。

CloudWatch widget showing index size in MB from S3 source bytes, broken out per knowledge base.

圖 10:儀錶板 B 各知識庫的索引大小,根據 Amazon S3 來源位元組數計算

第二個元件統計各知識庫的檢索呼叫次數。

CloudWatch widget showing Retrieve call invocations count, per knowledge base.

圖 11:儀錶板 B 各知識庫的檢索呼叫次數

第三個元件統計經 Gateway 發出的代理式工具呼叫次數。這項指標由兩個知識庫共用,並非分開列示。

CloudWatch widget showing agentic tool-call invocations through the AgentCore Gateway, as a single shared count.

圖 12:經 AgentCore Gateway 發出的代理式工具呼叫次數,由兩個知識庫共用

第四個元件顯示各知識庫的工作階段 token 用量。

CloudWatch widget showing session token usage (SessionQuotaTokens), per knowledge base.

圖 13:儀錶板 B 各知識庫的工作階段 token 用量

四個元件分別顯示索引大小(根據 S3 來源位元組數計算)、檢索呼叫量、經 Gateway 發出的代理式工具呼叫次數,以及工作階段 token 用量。除了由兩個知識庫共用的 Gateway 工具呼叫次數外,其餘指標均按知識庫分開列出。

有一項維度細節值得指出,因為具型別的 API 不會替你檢查這一點:AWS/Bedrock/KnowledgeBases 命名空間要求使用帶前綴的 ID knowledge-base/<id>,而方案本身的 BMKB/* 命名空間則使用不帶前綴的 ID。對 CDK 而言,兩者都只是一串字串。

# L1 — AWS/Bedrock/KnowledgeBases wants the prefixed form.
dimensions_map={"Operation": "Retrieve", "KnowledgeBaseId": f"knowledge-base/{kb_id}"}

# BMKB/* — our own namespaces use the bare id.
dimensions_map={"KnowledgeBaseId": kb_id}

第 5 層:span 樹

第 5 層是 aws/spans 中的原始 OTEL span 樹,也是直接呈現代理式循環的層。值得仔細閲讀,因為其巢狀結構並不明顯:一次 LLM 呼叫會產生三個 span。Strands invoke_agent span 包住整個回合,內部的 chat span 包住模型呼叫,而 chat <model> span 的類型為 CLIENT,代表實際呼叫;三者都會重複相同的 gen_ai.usage.* token 屬性。

以下截圖展示 aws/spans 中的 span 樹,頂部幾行可見三個 span 的巢狀結構。

CloudWatch span tree in aws/spans. The top three rows show an invoke_agent Strands Agents aggregate, an internal chat span, and a CLIENT chat span, all reporting an identical 7,299 input and 268 output tokens.

圖 14:aws/spans 中的第 5 層 span 樹,展示單次 LLM 呼叫的三個 span 巢狀結構

頂部三列依次是:invoke_agent Strands Agents 聚合項目、內部聊天 span,以及 CLIENT 聊天 span;三者報告的輸入 token 均為 7,299,輸出 token 均為 268。這是同一個 LLM 呼叫在樹狀結構的三個層級中出現,因此聚合時需要小心。

要進行聚合時,這種結構便十分重要。若要每個 LLM 呼叫只計算一次,請篩選至 CLIENT 葉節點:

fields attributes.gen_ai.request.model as model,
       attributes.gen_ai.usage.input_tokens as in_tok,
       attributes.gen_ai.usage.output_tokens as out_tok
| filter ispresent(in_tok) and kind = 'CLIENT' and name like /^chat /
| stats sum(in_tok) as input_tokens, sum(out_tok) as output_tokens,
        count(*) as llm_calls by model

若不套用這個篩選條件,同一查詢報告的 token 數和呼叫次數都會是三倍。

套用這項 CLIENT 葉節點篩選條件後,下方截圖顯示按模型劃分的生成 token 用量,每個 LLM 呼叫只計算一次。

CloudWatch results table of generation token usage by model, counting each LLM call once: 14 calls, 60,472 input tokens and 2,709 output tokens.

圖 15:按模型劃分的生成 token 用量,每個 LLM 呼叫只計算一次

套用篩選條件後,這次執行顯示 14 次 LLM 呼叫,總計 60,472 個輸入 token 和 2,709 個輸出 token。若不套用,同一查詢報告的呼叫次數和 token 數都會是三倍。

評估:隨需及持續

品質以兩種方式衡量,兩者均由應用程式佈建。

隨需:驅動程式筆記本會呼叫 AgentCore。這個版本沒有部署指令碼,這正是重點: (LLM-as-judge) 會針對每個工作階段的 spans 執行內置評估器 Correctness、Faithfulness 和 Tool-Selection Accuracy,並將評分發佈至 CloudWatch,評分會在 Dashboard A 上顯示為 Layer 7。

以下截圖顯示 Dashboard A 的 Layer 7:按知識庫劃分的隨需評估評分,並在同一儀錶板上顯示 Layer 5 OTEL span 資料表。

CloudWatch dashboard showing Layer 7 on-demand evaluation scores per knowledge base, with the Layer 5 OTEL span table beside them.

圖 16:Layer 7 按知識庫劃分的隨需評估評分,旁邊是 Layer 5 span 資料表

Layer 7 顯示按知識庫劃分的隨需評估評分,旁邊是 Layer 5 OTEL span 資料表,讓評分與產生評分的 spans 可在同一個儀錶板上對照查看。

持續(線上): 代理程式堆疊亦會佈建 AWS::BedrockAgentCore::OnlineEvaluationConfig,用於抽樣即時工作階段並自動評分,無須執行筆記本。設定本身可在 Bedrock AgentCore 主控台的「評估」→「評估」→「評估設定」 中查看。結果會寫入日誌羣組 /aws/bedrock-agentcore/evaluations/results/<config-id>,每個評分亦會以 CloudWatch 指標形式發佈至 Bedrock-AgentCore/Evaluations 命名空間,並以評估器名稱和設定 ID 為鍵,因此無須剖析日誌,也可將評分製成圖表或設定警報。

以下截圖顯示 AgentCore 主控台中的線上評估設定,路徑為「評估」→「評估」→「評估設定」。

AgentCore console showing the online evaluation configuration with four built-in evaluators (Tool-Selection Accuracy, Faithfulness, Correctness, Response Relevance), 100 percent sampling, status ACTIVE and enabled.

圖 17:AgentCore 主控台中的線上評估設定,包含四個內置評估器,取樣率為 100%

設定列出四個內置評估器:Tool-Selection Accuracy、Faithfulness、Correctness 和 Response Relevance;取樣率設為 100%,並顯示為 ACTIVE 及已啟用。

由於評分是一般 CloudWatch 指標,因此可像其他指標一樣繪製圖表,無須剖析日誌;同一個小工具亦可設定警報。以下截圖顯示這四個評估器的評分以一般 CloudWatch 指標形式繪製成圖表。

CloudWatch graph of the four evaluator scores in the Bedrock-AgentCore/Evaluations namespace

圖 18:四個持續評估器的評分以一般 CloudWatch 指標形式繪製成圖表

四個評估器的評分會以指標形式顯示在 Bedrock-AgentCore/Evaluations 命名空間中,每項指標均以評估設定 ID 和代理程式的服務名稱為鍵,因此無須剖析日誌,也可將它們製成圖表或設定警報。

線上評估結果只會在工作階段結束後出現。評分會在工作階段完成後執行,因此發送流量後,結果日誌羣組會在約一個工作階段閒置逾時(~30 分鐘)內保持空白。執行後羣組即時空白是預期情況,並非設定錯誤。每個結果事件都包含 session.id,因此可與其他所有層的資料關聯。筆記本中的按需評估流程無需等待,這就是兩種方式都列在這裏的原因。

在這次執行中,四個內置評估器的持續評估流程在正確性、忠實度、回應相關性及工具選擇準確度上均取得 1.00;每個評估器評分五筆追蹤記錄,每項結果均附有文字説明。

⚠ 抽樣與成本。這個應用程式將 SAMPLING_PERCENTAGE = 100 設為 純粹用於這次網誌實驗,因此每個工作階段都會評分,結果亦會即時顯示。這並非生產環境的建議設定。線上評估會為每個抽樣工作階段調用 LLM-as-judge,因此成本會隨抽樣率及流量增加。正式部署時,請選擇符合品質監察需求及預算的抽樣百分比,並在啟用前確保設定符合機構本身的政策及成本管治要求。抽樣率由單一常數 EvalConfig.SAMPLING_PERCENTAGE 設定,位於 config.py。

清理

完成後,請移除方案以停止產生費用,因為即使堆疊閒置,已儲存的 KB 資料、ECR 中的 Agent 映像,以及仍在運作的線上評估都會產生費用。只需一個命令即可全部移除:

cdk destroy --all

CDK 會自行按相反的相依次序刪除堆疊:先是 dashboards,然後是 agent、gateway,最後是 kb。這就是它為部署推導出的相同依賴圖,只是反向執行。無需維護一份必須與部署指令碼保持一致的拆除指令碼;只建模一次相依關係,是其中一項較不顯眼但相當有價值的特點。

有兩項移除行為值得留意,因為兩者都取代了手寫的清理程式碼:

self.source_bucket = s3.Bucket(
    self, "SourceBucket",
    removal_policy=RemovalPolicy.DESTROY,
    auto_delete_objects=True,  # replaces a list_object_versions delete loop
)

self.repository = ecr.Repository(
    self, "AgentImageRepo",
    removal_policy=RemovalPolicy.DESTROY,
    empty_on_delete=True,  # replaces an image-delete loop
)

兩者均已設定為方便範例清理;如有任何需要保留的資料,請將儲存貯體設定為 RemovalPolicy.RETAIN。

CDK bootstrap 堆疊(CDKToolkit)及其暫存儲存貯體不會被移除。它們是整個帳戶共用的基礎設施,其他 CDK 應用程式可能會依賴它們。

與單次方案相比,有哪些改變

本文與2024 年方案都是以 Python 編寫的 CDK 應用程式,並使用 cdk deploy 部署。編寫工具始終如一,改變的是底層架構,而大部分改動都是刪減:

考量項目 2024:單次 RAG 本方案
向量儲存區 需要自行佈建及擴展 OpenSearch Serverless 集合和索引,並按 OCU 付費 無。類型:MANAGED,儲存及索引由 Amazon Bedrock 管理
索引生命週期 自訂資源會建立索引,並等待索引可供搜尋 無需建立任何項目
嵌入模型 由你選擇並授予模型存取權限 預設由服務管理
堆疊 3:KB 角色 → OpenSearch 基礎設施 → KB + 資料來源 4:kb → gateway → agent → dashboards
檢索 一次 Retrieve,按向量相似度擷取 top-k 個區塊 AgenticRetrieveStream 會在內部重新排序,並傳回整合且附有引用來源的答案
選擇知識庫 不適用,只有一個索引 Agent 會根據語義在兩個知識庫之間進行路由
再次檢視語料庫 單次流程中無法做到 Agent 會在回答前再次進行檢索
遙測 沒有佈建任何項目 七層、兩個儀錶板
評估 手動:同步、選擇模型、提出問題 按需及持續評估,兩者均已佈建
閒置時的最低成本 無論是否發出查詢,OCU 費用都會持續累積 僅收取儲存費用

這種取捨確實有兩面。單一索引回答單次問題,每次查詢的成本較低、較易推理;如果答案都在同一個語料庫內,這種做法便完全足夠。當情況並非如此時,才採用這種設計。

負責處理工作的 CDK 構造

這個應用程式主要由四個構造承擔工作,值得逐一説明,因為每個構造都取代了原本需要手動編寫的部分:

  • Provider – 用於執行時間超過 AWS Lambda 函式 15 分鐘上限的自訂資源。on_event / is_complete 的拆分方式,代表不需要任何程序在輪詢迴圈中空等;而回傳給 CloudFormation 的回應協定由框架負責處理,毋須在每個處理常式內加入 vendored urllib 回呼。
  • BucketDeployment – 負責上載語料庫,讓擷取資料的自訂資源只需負責擷取。
  • auto_delete_objects=True 和 empty_on_delete=True 取代了手寫的 list_object_versions 和刪除映像的迴圈;否則,堆疊根本無法銷毀。
  • repository.grant_pull_push(project) – 一行程式碼便能授予 CodeBuild 所需的八項 ecr:* 動作,並由構造確保拼寫正確。

還有 Observe 區段中的型別化儀錶板:使用 Metric / GraphWidget / Row 物件,而非 DashboardBody JSON 字串,讓無效的元件組合不再是「在主控台上顯示錯誤」,而是在 cdk synth 時便失敗。

CDK 不會改變兩件事,開始使用前值得先了解:

  • 自由格式的 JSON 仍採用 camelCase。connector_parameters 和 parameter_values 會原樣傳遞,因此 AWS CDK 將 snake_case 轉換為 PascalCase 的規則不適用於其中。bucketName 和 inclusionPrefixes 等鍵必須完全按照 API 的要求拼寫;否則要到資源失敗時,才會發現問題。
  • 以字串型別表示的值仍然是字串。Observe 區段中 knowledge-base/<id> 與裸寫的 <id> 之間的維度差異,型別系統無法察覺。型別化構造會檢查結構,而非語義。

兩者都不是偏好其中一種工具的理由。這些正是「型別化」所能提供的範圍;瞭解這個界線所在,便能大致掌握 CDK 為何易用而不令人意外。

結語

我們利用 Managed Amazon Bedrock Knowledge Base 和 AgentCore 建構了完整的企業級代理式檢索方案:多知識庫語義路由、推理 Agent、七層可觀測性,以及按需和持續評估,並將所有內容部署為單一 AWS CDK 應用程式。

有兩點值得記住。受管理的知識庫減少了所需的基礎設施,而非增加基礎設施:無須佈建向量儲存區、建立索引並等待索引就緒,也不會在系統閒置時持續累積 OCU 費用。正如 Amazon Bedrock 文件所述,這亦是支援代理式檢索和 AgentCore Gateway 連接器的知識庫類型。當檢索採用代理式方式後,可觀測性便不再是可選項。這個應用程式佈建的資源中,約有一半用來回答 Agent 實際做了甚麼,以及答案是否理想;對代理式系統而言,這不是額外負擔,而是令系統可運作的關鍵部分。

CDK 的編寫模式在各個交界處發揮了價值。在這個架構中,有七個值需要跨越堆疊邊界,而每個值都是構造參照,而非一組匯出/匯入設定;因此不需要部署指令碼或拆除指令碼,也毋須記住固定次序。

在此基礎上,你可以將數據來源指向自己的語料庫、將 Agent 部署在虛擬私有雲(VPC)中、按預算和政策調整線上評估的取樣率,或為路由器新增更多知識庫。如欲瞭解更多,請參閲 Amazon Bedrock 詳細資訊頁面及 Amazon Bedrock 文件。應用程式、驅動程式筆記本及自包含工具均位於隨附的 GitHub 儲存庫,你可以複製該儲存庫,並以一個命令部署自己的副本。


作者簡介

Prabhakar Chandrasekaran

Prabhakar Chandrasekaran

Prabhakar 是 AWS Enterprise Support 的資深技術客戶經理。他樂於協助客戶在雲端建立 AI 和 ML 解決方案。他亦與企業客戶合作,提供主動指引及營運協助,協助他們提升使用 AWS 時的解決方案價值。Prabhakar 持有八項 AWS 認證及七項其他專業認證。他擁有逾 23 年專業經驗,加入 AWS 前曾在金融服務領域擔任數據工程師及項目主管。

Siddhant Sahu

Siddhant Sahu

Siddhant 是 AWS 的資深產品經理,負責領導 Amazon Bedrock Managed Knowledge Base 的產品開發。他專注於建立及推出基礎設施軟件服務,透過全託管的資料擷取、剖析及代理式搜尋管線,以具成本效益、準確及安全的方式處理多模態、多語言的企業數據,並運用混合搜尋、多次檢索、工具使用及嵌入技術等先進功能。他的工作讓數以千計的企業客戶及 ISV 能夠大規模建立 Agent。

來源:AWS Machine Learning Blog · aws.amazon.com