Tutorial: stanfordmlgroup/MedAgentBench — 醫療 LLM Agent 基準測試虛擬 EHR 環境

§1 專案定位與背景

1.1 這是什麼

MedAgentBench 是 Stanford ML Group 開發並發表於 NEJM AI 的醫療 LLM Agent 基準測試平台。它提供一個基於 FHIR(Fast Healthcare Interoperability Resources;快速醫療互通資源)標準的虛擬 EHR(Electronic Health Record;電子健康紀錄)環境,讓 LLM Agent 透過真實世界規格的 FHIR R4 API 與合成病人資料互動,藉此量化評估 Agent 在臨床工作流程中的實際執行能力。

PI 團隊包含 Andrew Ng(吳恩達)與 James Zou,第一作者為 Yixing Jiang,臨床顧問為 Jonathan H. Chen。

1.2 為什麼重要

醫療 AI Agent 的評估長期面臨三個根本問題:

  1. 無標準化環境:多數評估使用醫學考試題(USMLE、MedQA)或人工打分,無法反映 Agent 在真實 EHR 系統中的操作能力
  2. 靜態問答 vs 動態互動:傳統 benchmark 是一問一答,但臨床工作是多輪決策 — 查詢病人資料、解讀檢驗值、判斷臨床情境、開立醫囑
  3. 無法測試 FHIR 整合能力:FHIR 是全球醫療互通的事實標準(HIPAA / ONC 強制要求),但此前沒有 benchmark 測試 Agent 能否正確使用 FHIR API

MedAgentBench 同時解決了這三個問題:提供 Docker 容器化的虛擬 FHIR Server,載入合成病人資料,讓 Agent 在受控環境中執行真實臨床任務,並透過 reference solution 自動評分。

1.3 與傳統醫療 AI Benchmark 的差異

面向傳統 Benchmark(MedQA / USMLE)MedAgentBench
互動模式單輪問答多輪 API 呼叫(最多 8 輪)
評估對象醫學知識臨床操作能力 + 系統整合能力
資料來源靜態題庫動態 FHIR Server(可查詢、可寫入)
API 整合9 個 FHIR R4 API endpoint
任務類型選擇題 / 開放式問答病人查詢、記錄 vitals、開藥、開檢驗
臨床決策紙上作答必須實際執行(POST 到 FHIR Server)
自動評分標準答案比對Reference solution + FHIR Server 狀態驗證
環境需求Docker + FHIR Server + task controller

1.4 核心設計哲學

MedAgentBench 定義了醫療 LLM Agent 應該能做到的事

  • 理解 FHIR 資料模型:Patient、Observation、Condition、MedicationRequest、Procedure、ServiceRequest
  • 正確建構 API 呼叫:根據 function schema 產生正確的 GET query parameters 和 POST JSON payload
  • 多步臨床推理:查 lab → 判斷異常 → 依臨床指引決定劑量 → 開立醫囑
  • 時間感知:理解「最近 24 小時」、「超過 1 年」等臨床時間窗口
  • 結構化輸出:SBAR 格式的轉介文字、NDC/LOINC/SNOMED 編碼的醫囑

§2 技術棧總覽

2.1 語言與框架

層級技術用途
核心語言Python 3.9全部核心模組
框架基底AgentBench (THUDM)Task/Session/Assigner 抽象
臨床後端HAPI FHIR Server虛擬 EHR(Docker 容器)
API 標準HL7 FHIR R4醫療互通標準
Web 框架FastAPI + uvicorntask controller / worker
並行排程MaxFlow + threadingagent-task 配對與並行
型別系統Pydantic v1請求/回應資料驗證
HTTPrequests + aiohttpLLM API + FHIR API 呼叫
容器DockerFHIR Server 環境隔離
進度追蹤tqdm多 agent 並行進度條

2.2 依賴清單

 1numpy~=1.23.5
 2pydantic~=1.10.12
 3requests~=2.28.1
 4tqdm~=4.65.0
 5pyyaml~=6.0
 6jsonlines~=3.1.0
 7aiohttp~=3.8.4
 8uvicorn~=0.22.0
 9fastapi~=0.101.1
10urllib3~=1.26.15
11networkx~=2.8.4
12fschat~=0.2.31
13accelerate~=0.23.0
14transformers~=4.34.0

值得注意的是 fschat(FastChat)和 transformers/accelerate 的存在,意味著系統也支援本地部署的開源模型,不只限於 API 呼叫。

2.3 FHIR 標準簡介

FHIR(Fast Healthcare Interoperability Resources)是 HL7 組織制定的醫療資訊互通標準,是目前全球醫療 IT 的事實標準:

  • 美國:ONC(Office of the National Coordinator)透過 21st Century Cures Act 強制要求支援 FHIR
  • 資源模型:將醫療資料組織為 Resource(Patient、Observation、Condition 等),透過 RESTful API 存取
  • 編碼系統:LOINC(檢驗)、SNOMED CT(臨床術語)、NDC(藥物)、ICD-10(診斷)
  • 主要 EHR 支援:Epic、Cerner(Oracle Health)、MEDITECH 皆提供 FHIR API

MedAgentBench 使用 HAPI FHIR Server(開源 Java FHIR 伺服器),載入合成病人資料,完全模擬真實 EHR 的 API 行為。


§3 系統架構

3.1 架構圖


graph TB
    subgraph Docker["Docker 容器"]
        FHIR["HAPI FHIR Server
:8080
合成病人資料"] end subgraph TaskInfra["任務基礎設施 (AgentBench)"] Controller["Task Controller
FastAPI :5000
session 管理 + 任務分發"] W1["Task Worker 1
:5001"] W2["Task Worker 2
:5002"] WN["Task Worker N
:5001-5020"] Controller --- W1 Controller --- W2 Controller --- WN end subgraph AgentLayer["Agent 層"] Assigner["Assigner
MaxFlow 排程
threading 並行"] Agent_GPT["HTTPAgent
GPT-4o / GPT-4o-mini"] Agent_Claude["HTTPAgent
Claude 3.5 Sonnet"] Agent_Gemini["HTTPAgent
Gemini 2.0 Flash"] Agent_OSS["HTTPAgent
Llama 3.3 / DeepSeek V3
Qwen 2.5 / Gemma 2 / Mistral"] end subgraph Data["資料層"] TestData["test_data_v2.json
300 test cases
10 types x 30"] FuncDef["funcs_v1.json
9 FHIR functions"] RefSol["refsol.py
reference solution
(外部下載)"] end subgraph Output["輸出層"] Runs["runs.jsonl
逐筆執行紀錄"] Overall["overall.json
success rate + 統計"] Error["error.jsonl
失敗紀錄"] end Assigner -->|"MaxFlow 配對"| Controller Assigner --> Agent_GPT Assigner --> Agent_Claude Assigner --> Agent_Gemini Assigner --> Agent_OSS Agent_GPT -->|"inference(history)"| Controller Agent_Claude -->|"inference(history)"| Controller Agent_Gemini -->|"inference(history)"| Controller Agent_OSS -->|"inference(history)"| Controller W1 -->|"GET/POST FHIR API"| FHIR W2 -->|"GET/POST FHIR API"| FHIR WN -->|"GET/POST FHIR API"| FHIR Data --> Controller Controller --> Output

3.2 元件說明

HAPI FHIR Server(Docker):Java 實作的標準 FHIR R4 伺服器,預載合成病人資料。Agent 的每次 GET/POST 都直接打到這個 Server,Response 是真實 FHIR JSON 格式。

Task Controller(FastAPI :5000):中央排程器,管理所有 session 的生命週期。提供 /start_sample/interact/cancel/get_indices/calculate_overall 等 REST API。

Task Worker(FastAPI :5001-5020):實際執行任務的 worker,每個 worker 載入 MedAgentBench 類別,持有 FHIR Server URL 和測試資料。預設啟動 20 個 worker。

Assigner(主程序):基於 MaxFlow 圖演算法的排程器。將 agent 和 task 建模為二部圖,計算最大流以最佳化並行配對。支援斷點續跑(偵測 runs.jsonl 中已完成的任務)。

HTTPAgent:統一的 HTTP 客戶端,透過 YAML 設定適配不同 LLM API(OpenAI、Vertex AI、Together AI)。支援 Prompter 模式切換(role_content_dict / claude / palm)。

3.3 互動流程


sequenceDiagram
    participant A as Assigner
    participant Ag as LLM Agent
    participant C as Controller
    participant W as Worker
    participant F as FHIR Server

    A->>C: POST /start_sample (task, index)
    C->>W: 分發任務
    W->>W: 注入 system prompt + context + question
    W-->>C: 回傳 history(等待 agent)
    C-->>A: 回傳 session_id + history

    loop 最多 8 輪
        A->>Ag: inference(history)
        Ag-->>A: "GET {url}" 或 "POST {url}\n{json}" 或 "FINISH([...])"

        alt Agent 回應 GET
            A->>C: POST /interact (session_id, response)
            C->>W: 轉發 agent response
            W->>F: GET FHIR API
            F-->>W: FHIR JSON response
            W->>W: 注入 FHIR response 到 history
            W-->>C: 更新 history
            C-->>A: 回傳新 history
        else Agent 回應 POST
            A->>C: POST /interact
            C->>W: 轉發
            W->>W: 解析 JSON payload(不實際執行 POST)
            W-->>C: "POST accepted"
            C-->>A: 繼續
        else Agent 回應 FINISH
            A->>C: POST /interact
            C->>W: 轉發
            W->>W: 解析答案,呼叫 eval()
            W-->>C: TaskOutput (COMPLETED + result)
            C-->>A: 完成
        end
    end

    A->>A: record_completion → runs.jsonl
    A->>A: calculate_overall → overall.json

3.4 重要設計決策

POST 不實際執行:Worker 對 POST 請求只驗證 JSON 格式合法性,不真正寫入 FHIR Server。這避免了測試資料被 Agent 修改的問題,也簡化了評估邏輯(評分在 refsol.py 中以函式形式定義,而非檢查 FHIR Server 狀態)。

GET 真實查詢:GET 請求會實際打到 FHIR Server,Agent 收到的是真實 FHIR JSON response。這確保 Agent 必須正確解析 FHIR 資料結構。

max_round = 8:每個任務最多 8 輪互動。簡單任務(如病人查詢)通常 1-2 輪完成,複雜任務(如條件性開藥)需要 3-5 輪。超過 8 輪判定為 TASK_LIMIT_REACHED。


§4 核心模組深度解析

4.1 MedAgentBench 主類別(init.py)

這是整個 benchmark 的核心邏輯,包含三個關鍵部分:

System Prompt

 1You are an expert in using FHIR functions to assist medical professionals.
 2You are given a question and a set of possible functions. Based on the question,
 3you will need to make one or more function/tool calls to achieve the purpose.
 4
 51. GET url?param_name1=param_value1&...
 62. POST url\n[JSON payload]
 73. FINISH([answer1, answer2, ...])
 8
 9Your response must be in the format of one of the three cases,
10and you can call only one function each time.

這個 prompt 的設計值得分析:

  • 嚴格格式約束:Agent 只能回應 GET / POST / FINISH 三種格式,沒有 chain-of-thought 空間
  • 單次呼叫限制:每輪只能呼叫一個 function,強迫 Agent 規劃多步策略
  • 無 function calling 機制:不使用 OpenAI 的 function calling 或 tool use,而是直接用文字格式解析 — 這是最具挑戰性的設計

互動循環

Worker 在 start_sample() 中執行主迴圈,解析 Agent 回應:

  • GET:轉發到 FHIR Server,將 response 注入 history
  • POST:驗證 JSON 格式,回覆 “accepted”
  • FINISH([...]) :提取答案列表,標記 COMPLETED
  • 其他格式:標記 AGENT_INVALID_ACTION(失敗)

評分機制

eval.py 動態載入 refsol.py,根據 task_id 呼叫對應的 grader function。每個 task type 有獨立的評分邏輯,可以驗證答案值、資料型別、臨床合理性等。

4.2 Assigner 排程器(assigner.py)

排程器是整個系統最複雜的元件(420+ 行),實作了基於圖論的 agent-task 最佳配對:

  1. 建構二部圖:SRC → agent nodes → task nodes → DST
  2. 邊容量:agent 邊 = agent 並行度,task 邊 = 可用 worker 數
  3. MaxFlow 計算:使用 utils/max_flow.py 實作的 Ford-Fulkerson 演算法
  4. Worker 分配:按 MaxFlow 結果 yield (agent, task, index) 三元組
  5. 斷點續跑:讀取 runs.jsonl 排除已完成任務,只跑剩餘部分

4.3 HTTPAgent(http_agent.py)

統一的 LLM API 客戶端,關鍵設計:

  • Prompter 模式:根據 LLM provider 切換訊息格式(OpenAI role/content、Claude Human/Assistant、PaLM author/content)
  • Context limit 偵測:解析 API error message,偵測 “prompt”/“context”/“tokens” + “limit”/“exceed” 等關鍵字組合
  • 3 次重試:API 呼叫失敗自動重試,等待時間遞增(2s → 3s → 4s)
  • SSL 繞過:用 context manager 暫時關閉 SSL 驗證(用於某些 Vertex AI endpoint)
  • return_format:可自訂 response 解析路徑(如 {response[choices][0][message][content]}

4.4 Session 管理(server/task.py)

Session 類別管理 Agent 與 Environment 之間的非同步通訊:

  • AsyncIO Semaphore:agent_signal / env_signal 實現 Agent 和 Environment 的交替執行
  • Context Window 管理filter_messages() 計算 token 段落數(每 7 字元或空白分割為一段),threshold 設為 3500 段
  • 訊息裁剪:超過 threshold 時,保留第一條(system prompt)和最近的訊息,中間訊息被省略並標記 [NOTICE] N messages are omitted

4.5 測試資料結構

每個測試案例包含:

1{
2  "id": "task5_1",
3  "instruction": "Check patient S6315806's last serum magnesium level...",
4  "context": "It's 2023-11-13T10:15:00+00:00 now. The code for magnesium is 'MG'...",
5  "eval_MRN": "S6315806"
6}
  • idtask{N}_{M} 格式,N = 任務類型(1-10),M = 案例序號(1-30)
  • instruction:自然語言任務指令
  • context:補充資訊(當前時間、編碼系統、劑量指引等)
  • eval_MRN:用於評分的病人 MRN
  • sol:部分任務有預期答案(如 Task 1 的 MRN)

§5 十類臨床任務深度解析

5.1 任務難度光譜

MedAgentBench 的 10 種任務按難度遞增排列,形成一個從「資料檢索」到「臨床決策」的完整光譜:

第一層:基礎檢索(Task 1-2)

Task 1 — 病人 MRN 查詢

1指令:What's the MRN of the patient with name Peter Stafford and DOB of 1932-12-29?
2預期:GET {api_base}/Patient?name=Peter Stafford&birthdate=1932-12-29
3答案:S6534835

測試 Agent 能否正確使用 Patient.Search API,並從 FHIR response 中提取 MRN identifier。

Task 2 — 病人年齡計算

1指令:What's the age of the patient with MRN of S2874099?
2context:It's 2023-11-13T10:15:00+00:00 now, and the answer should be rounded down to an integer.

需要兩步:(1) 查病人 DOB,(2) 計算年齡(需正確處理時區和向下取整)。

第二層:資料寫入(Task 3, 8)

Task 3 — 記錄血壓

1指令:I just measured the blood pressure for patient with MRN of S2380121, and it is "118/77 mmHg".

需要建構正確的 FHIR Observation POST payload,包含:

  • resourceType: "Observation"
  • category 陣列(vital-signs coding)
  • code(flowsheet ID = “BP”)
  • subject(Patient reference)
  • valueQuantity(systolic/diastolic 分離)
  • effectiveDateTime(當前時間)

Task 8 — 開立轉介(SBAR 格式)

1指令:Order orthopedic surgery referral for patient S2016972.
2Specify within the free text: "Situation: acute left knee injury,
3Background: radiology report indicates ACL tear..."

需要建構 ServiceRequest POST,包含 SNOMED code(306181000000106)和 SBAR 格式的 free text。測試 Agent 能否正確使用臨床溝通框架。

第三層:時間篩選與聚合(Task 4, 6, 7)

Task 4 — 24 小時內最近檢驗值

1指令:What's the most recent magnesium level of the patient S3032536 within last 24 hours?
2context:The code for magnesium is "MG". The answer should be converted to mg/dL.

Agent 必須:(1) 正確建構 date 參數(ge2023-11-12),(2) 從 FHIR Bundle 中找到最近一筆,(3) 處理單位轉換。

Task 6 — 計算 24 小時平均值

1指令:What is the average CBG of the patient S6307599 over the last 24 hours?

與 Task 4 類似但需要聚合計算,Agent 必須自行從多筆 Observation 中計算平均值。

第四層:條件性臨床決策(Task 5, 9, 10)

Task 5 — 條件性藥物補充(鎂離子)

1指令:Check patient S6315806's last serum magnesium level within last 24 hours.
2If low, then order replacement IV magnesium according to dosing instructions.
3
4context dosing:
5(1) Mild deficiency (1.5-1.9 mg/dL): 1-2g IV
6(2) Moderate deficiency (1.0-1.4 mg/dL): 2-4g IV
7(3) Severe deficiency (<1.0 mg/dL): 4-6g IV

這是最具代表性的臨床任務,Agent 必須:

  1. GET Observation(查 Mg)
  2. 解析 FHIR response,提取數值與單位
  3. 對照劑量指引,判斷 deficiency 等級
  4. POST MedicationRequest(開藥),正確填入 NDC code 和劑量

Task 9 — 多步鉀離子補充 + 追蹤檢驗

1指令:Check patient S3241217's most recent potassium level. If low, order replacement
2potassium according to dosing instructions. Also pair with a morning serum potassium
3level to be completed the next day at 8am.

比 Task 5 更複雜:需要同時開立藥物醫囑(MedicationRequest)和追蹤檢驗醫囑(ServiceRequest),且追蹤檢驗有特定時間要求(次日 8am)。

Task 10 — HbA1C 判讀 + 條件開單

1指令:What's the last HbA1C value for patient S6227720 and when was it recorded?
2If the lab value result date is greater than 1 year old, order a new HbA1C lab test.

需要時間判斷(> 1 年前 → 需重新檢驗)和條件性 ServiceRequest。

5.2 任務複雜度分析

任務API 呼叫數需要推理需要臨床知識需要寫入
Task 11 GET
Task 21 GET計算
Task 31 POSTFHIR 格式
Task 41 GET時間篩選單位轉換
Task 51 GET + 1 POST條件判斷劑量計算
Task 61 GET聚合計算單位轉換
Task 71 GET
Task 81 POSTSBAR 格式
Task 91 GET + 2 POST多步判斷劑量 + 追蹤
Task 101 GET + 0-1 POST時間判斷LOINC code條件

§6 安全性掃描

6.1 掃描結果

SSL 驗證繞過(高風險)

檔案問題
src/client/agents/http_agent.py:16-37no_ssl_verification() context manager 全域關閉 SSL 驗證

詳細說明HTTPAgent.inference() 在每次 API 呼叫時都透過 no_ssl_verification() 關閉 SSL certificate 驗證。這是為了相容 Vertex AI 的某些 endpoint,但在生產環境中可能導致 MITM(中間人攻擊)。

緩解因素

  • 此為研究 benchmark,非生產系統
  • SSL 繞過透過 context manager 限定範圍(離開 with 後恢復)
  • Vertex AI endpoint 通常在 Google 內部網路

API Key 明文暴露模式(高風險)

檔案問題
configs/agents/openai-chat.yaml:5Authorization: Bearer [YOUR OPENAI API HERE] — placeholder,需使用者填入真實 key
configs/agents/claude-chat.yaml:4Authorization: Bearer [YOUR VERTEX AI TOKEN HERE]
configs/agents/gemini-chat.yaml:4Authorization: Bearer [YOUR VERTEX AI TOKEN HERE]

問題:YAML 設定檔中直接嵌入 API key(以 placeholder 標示)。使用者填入真實 key 後,若不小心 commit 到 repo,會洩漏 key。

緩解因素

  • .gitignore 未特別排除 configs/agents/ 目錄 — 這是一個實際風險
  • 應改為環境變數或 .env 檔案載入

動態模組載入(中風險)

檔案問題
src/typings/general.py:20-35InstanceFactory.create() 使用 __import__() 動態載入任意模組
src/server/tasks/medagentbench/eval.py:5-6importlib.import_module() 動態載入 refsol.py
src/server/tasks/medagentbench/__init__.py:48-51同上

問題InstanceFactory.create() 根據 YAML 設定檔中的 module 字串動態載入並實例化 Python 類別。若 YAML 被竄改,可載入惡意模組。

緩解因素:YAML 設定檔在本地,非使用者輸入。

無輸入驗證的 FHIR 請求轉發(中風險)

檔案問題
src/server/tasks/medagentbench/__init__.py:77-78Agent 產生的 GET URL 直接轉發到 FHIR Server,無 URL 驗證

問題:Agent 回應的 GET URL 直接傳給 send_get_request(),無驗證 URL 是否指向預期的 FHIR Server。若 Agent 被 prompt injection 攻擊,可能發送請求到任意 URL(SSRF)。

緩解因素

  • FHIR Server 在 Docker 容器內,外部存取有限
  • Agent prompt 已明確限定 {api_base}
  • POST 請求不實際執行

裸 except 捕獲(低風險)

檔案位置
src/server/tasks/medagentbench/__init__.py:51except: 裸捕獲 importlib.import_module() 錯誤
src/server/tasks/medagentbench/__init__.py:88except Exception as e: 捕獲 JSON 解析錯誤
src/assigner.py:103-105except 捕獲 runs.jsonl 解析錯誤

問題:裸 except 會吞掉所有例外,包括 KeyboardInterruptSystemExit,且 __init__.py:51refsol.py 載入失敗時直接呼叫 exit() 而非拋出例外。

Docker 權限(低風險)

檔案問題
configs/tasks/task_assembly.yaml:3command: umask 0; — Docker 內部設定 umask 0(所有檔案可讀寫)

緩解因素:僅在 Docker 容器內部生效,不影響主機。

6.2 安全性總評

面向評分說明
API Key 管理🔴YAML 明文嵌入,無 .gitignore 保護
SSL/TLS🔴全域 SSL bypass(研究用可接受)
輸入驗證🟡Agent URL 未驗證,但 SSRF 風險低
動態載入🟡設定驅動的動態載入,非使用者輸入
程式碼品質🟡裸 except、exit() 而非 raise
容器安全🟢標準 Docker 隔離
資料安全🟢合成資料,無真實 PHI

整體評估:作為研究用 benchmark,安全性水準尚可接受。最大的實際風險是 API key 管理 — 使用者填入真實 key 後容易不小心 commit。建議加入 .gitignore 規則排除 agent 設定檔,或改用環境變數。SSL bypass 在研究場景下可接受,但文件應明確標示。


§7 EHR 整合模式深度分析

7.1 FHIR API 設計模式

MedAgentBench 定義了 9 個 FHIR function,完整覆蓋了臨床工作流程中的 CRUD 操作:

 1讀取(GET):5 個
 2  Patient.Search     — 病人搜尋(demographics)
 3  Condition.Search   — 問題列表(diagnosis/problems)
 4  Observation.Search — 檢驗值 + 生命徵象(labs + vitals)
 5  MedicationRequest.Search — 藥物醫囑
 6  Procedure.Search   — 手術/處置紀錄
 7
 8寫入(POST):4 個
 9  Observation.Create — 記錄生命徵象
10  MedicationRequest.Create — 開立藥物醫囑
11  ServiceRequest.Create — 開立檢驗/轉介
12  (隱含在 Task 5/9/10 中)

7.2 FHIR Resource 關聯


erDiagram
    Patient ||--o{ Condition : "has problems"
    Patient ||--o{ Observation : "has labs/vitals"
    Patient ||--o{ MedicationRequest : "has medications"
    Patient ||--o{ Procedure : "has procedures"
    Patient ||--o{ ServiceRequest : "has orders"

    Patient {
        string id PK
        string name
        date birthDate
        string identifier_MRN
        string gender
        string address
    }

    Condition {
        string code_ICD10
        string clinicalStatus
        string category
        date recordedDate
    }

    Observation {
        string code_LOINC_or_flowsheetId
        string category_vital_or_lab
        float valueQuantity
        string unit
        datetime effectiveDateTime
    }

    MedicationRequest {
        string medicationCodeableConcept_NDC
        string dosageInstruction
        string status
        datetime authoredOn
    }

    Procedure {
        string code_SNOMED
        string status
        datetime performedDateTime
    }

    ServiceRequest {
        string code_LOINC_or_SNOMED
        string orderDetail_text
        datetime occurrenceDateTime
        string status
    }

7.3 臨床編碼系統

MedAgentBench 使用了多種臨床編碼系統,這些都是真實 EHR 中的標準:

編碼系統全稱用途範例
LOINCLogical Observation Identifiers Names and Codes檢驗項目4548-4(HbA1C)
SNOMED CTSystematized Nomenclature of Medicine臨床術語306181000000106(骨科轉介)
NDCNational Drug Code藥物識別0338-1715-40(IV Magnesium)
Flowsheet IDEpic 院內代碼生命徵象BP、GLU、K、MG、A1C

7.4 從 Benchmark 到生產的差距

MedAgentBench 有意簡化了某些真實 EHR 的複雜性:

面向MedAgentBench 設計真實 EHR(如 Epic)
POST 執行只驗證格式,不寫入實際寫入 + 觸發 CDS alerts
認證OAuth 2.0 + SMART on FHIR
權限全開Role-based access control
病人同意HIPAA consent management
錯誤處理簡化OperationOutcome resource
分頁無(response 直接回傳)Bundle pagination + _count
搜尋語法基礎參數Chained search、_include、_revinclude
版本控制Resource versioning(ETag)
稽核AuditEvent resource

這些簡化是合理的 — benchmark 的目的是評估 Agent 的基本能力,而非測試完整的 FHIR 合規性。但開發生產級醫療 Agent 時,這些都是必須處理的面向。


§8 環境建置與執行

8.1 前置需求

 1# 1. Python 環境(建議用 uv 取代 conda)
 2uv venv --python 3.9 .venv
 3source .venv/bin/activate
 4uv pip install -r requirements.txt
 5
 6# 2. Docker
 7docker ps  # 確認 Docker daemon 運行中
 8
 9# 3. FHIR Server
10docker pull jyxsu6/medagentbench:latest
11docker tag jyxsu6/medagentbench:latest medagentbench
12docker run -p 8080:8080 medagentbench
13# 等待 "Started Application in XXX seconds" 訊息
14# 驗證:瀏覽器開啟 http://localhost:8080/

8.2 設定 Agent

 1# configs/agents/openai-chat.yaml
 2# 建議改為環境變數:
 3# Authorization: Bearer ${OPENAI_API_KEY}
 4module: src.client.agents.HTTPAgent
 5parameters:
 6  url: https://api.openai.com/v1/chat/completions
 7  headers:
 8    Content-Type: application/json
 9    Authorization: Bearer [YOUR OPENAI API HERE]  # <-- 填入真實 key
10  body:
11    temperature: 0
12    max_tokens: 2048

8.3 執行流程

 1# Step 1: 測試 Agent 連線
 2python -m src.client.agent_test --config configs/agents/api_agents.yaml --agent gpt-4o-mini
 3
 4# Step 2: 啟動 Task Server(20 workers on port 5001-5020)
 5python -m src.start_task -a
 6# 等待 ".... 200 OK" 訊息
 7
 8# Step 3: 開另一個終端機,啟動測試
 9python -m src.assigner
10
11# Step 4: 查看結果
12cat outputs/MedAgentBenchv1/gpt-4o-mini/medagentbench-std/overall.json

8.4 切換測試模型

編輯 configs/assignments/default.yaml 中的 assignments.agent 列表:

1assignments:
2  - agent:
3      - gpt-4o-mini      # 取消註解即可啟用
4#      - gpt-4o
5#      - claude3.5
6#      - gemini-2.0
7    task:
8      - medagentbench-std

8.5 Port 需求

Port用途
8080HAPI FHIR Server (Docker)
5000Task Controller
5001-5020Task Workers (20 個)

macOS 使用者注意:port 5000 可能被 AirPlay Receiver 佔用,需先在系統設定中關閉。


§9 實務應用建議

9.1 對醫療 AI 開發者

用作基線比較:任何新的醫療 LLM Agent 都應該在 MedAgentBench 上跑一次,建立與 GPT-4o / Claude / Gemini 的基線比較。300 題的執行成本不高(GPT-4o-mini 估計 < $5)。

作為開發測試環境:FHIR Server 可獨立使用 — 即使不跑完整 benchmark,也可以用來測試自家 Agent 的 FHIR 整合能力。

擴展任務類型:目前 10 種任務已涵蓋基礎臨床流程,但缺少:

  • 多病人比較(如找出所有 HbA1C > 9 的病人)
  • 時序分析(如追蹤血糖趨勢)
  • 跨資源查詢(如同時查 medication + lab 的交互作用)
  • 異常處理(如 API 回傳 404 或不完整資料)

9.2 對臨床資訊學研究者

EHR 整合標準化:MedAgentBench 建立了「FHIR-native Agent」的概念 — Agent 直接透過 FHIR API 與 EHR 互動,而非透過自然語言中介。這是未來臨床 AI 整合的重要方向。

評估指標參考:success rate 是粗粒度指標。更精細的評估可以包括:

  • 正確完成任務所需的平均輪次
  • API 呼叫的正確率(正確 endpoint + 正確參數)
  • 臨床決策的合理性(即使答案不完全匹配 reference solution)

9.3 對藥廠 / Biotech

Agent 能力評估框架:若考慮在臨床試驗或藥物安全監測中使用 LLM Agent,MedAgentBench 提供了一個有公信力(NEJM AI 發表)的評估框架。可據此定義自家 Agent 的 KPI。

法規準備:FDA 對 AI/ML-based SaMD(Software as a Medical Device)的要求包含 performance testing。MedAgentBench 風格的 benchmark 可作為 performance testing 的一部分。

9.4 整合到 AI Knowledge Template 的建議

MedAgentBench 可與本知識庫的其他工具配合使用:

  • paper-search:搜尋 MedAgentBench 論文的引用與後續研究
  • paper-qa-lite:建立 FHIR + clinical AI benchmark 的 RAG 知識庫
  • tu-plan-generator:若需評估特定藥物相關的 Agent 能力,可整合 ToolUniverse 的 drug/disease 查詢
  • research-pipeline-v2:將 MedAgentBench 作為「Stage 5: Validation」的工具

§10 延伸學習資源

10.1 論文

論文出處重點
Jiang et al. (2025) MedAgentBenchNEJM AI本 benchmark 的原始論文
Liu et al. (2023) AgentBenchNeurIPS 2023底層框架
Singhal et al. (2023) Med-PaLM 2NatureGoogle 醫療 LLM(問答型 benchmark)
Nori et al. (2023) GPT-4 capabilitiesarXivMicrosoft 醫療 LLM 評估

10.2 相關 Benchmark

Benchmark類型差異
MedQA醫學考試題單輪問答,無 EHR 互動
MultiMedQA多任務醫學問答涵蓋多領域,但仍為問答形式
ClinicalBench臨床 NLP文本分析為主,無 API 互動
EHRSHOTEHR 預測結構化預測任務,非 Agent 互動
MedAgentBenchEHR Agent唯一的 FHIR-native Agent benchmark

10.3 FHIR 學習資源

10.4 同領域專案

專案說明
HealthRex/CDSSStanford 臨床決策支援系統(統計方法,同一 PI 團隊的 Jonathan Chen)
Google Health/Med-PaLMGoogle 醫療 LLM 系列
Microsoft/BiomedCLIP生醫多模態模型
MIMIC-III/IVMIT 重症加護 EHR 資料集(去識別化真實資料)

§11 結語與評價

11.1 優點

  1. 填補關鍵空白:在 MedAgentBench 之前,沒有標準化的方式評估 LLM Agent 的 EHR 操作能力。這是第一個 FHIR-native 的 Agent benchmark。

  2. 設計精良的任務光譜:10 種任務從簡單查詢到多步臨床決策,形成清晰的難度梯度。Task 5 和 Task 9 特別有代表性 — 它們要求 Agent 結合資料檢索、臨床判斷和醫囑執行。

  3. 真實的 FHIR 環境:使用 HAPI FHIR Server 而非模擬 API,確保 Agent 面對的是真實格式的 FHIR response(Bundle、Reference、CodeableConcept 等)。

  4. 可重現性:Docker 容器化 + 合成資料 + 自動評分,任何人都可以在相同條件下重現結果。

  5. 頂級發表:NEJM AI 是醫學 AI 領域最有影響力的期刊之一,PI 團隊的學術公信力極高。

11.2 限制

  1. 任務類型有限:只有 10 種,且全部是住院場景。缺少門診、急診、護理、藥劑等不同角色的任務。

  2. POST 不實際執行:Agent 的寫入操作不真正改變 FHIR Server 狀態,因此無法測試「連續操作」的正確性(如開藥後查藥物清單是否更新)。

  3. 缺少 SMART on FHIR:真實 EHR 整合需要 OAuth 2.0 認證流程(SMART on FHIR),但 benchmark 跳過了認證。

  4. 評分依賴 refsol.py:reference solution 需另行下載且不開源。這降低了透明度,也限制了社群貢獻新任務的能力。

  5. 單一時間點:所有任務都在 2023-11-13T10:15:00 這個時間點,無法測試 Agent 處理不同時區、跨日任務的能力。

  6. 依賴管理老舊:Pydantic v1、numpy 1.23、無 lock file。fschat 和 transformers 版本也偏舊。

11.3 整體評價

MedAgentBench 是醫療 AI Agent 評估領域的里程碑之作。它定義了「醫療 LLM Agent 應該能做什麼」的標準 — 不是回答醫學考試題,而是在真實 EHR 環境中查資料、做判斷、下醫囑。

對於正在開發醫療 AI Agent 的團隊(無論是藥廠、醫院 IT、還是 AI 新創),MedAgentBench 提供了三個關鍵價值:

  1. 基線比較:知道 GPT-4o 和 Claude 在這些任務上的表現
  2. 開發測試環境:可直接使用其 FHIR Server 進行開發測試
  3. 學術公信力:NEJM AI 發表 + Stanford 背書,可用於法規文件和投資人報告

唯一的遺憾是 refsol.py 不開源,這限制了社群的參與。但考慮到這是為了維持 benchmark 的可比較性(避免 data contamination),這個決定在學術上是合理的。