下拉重新整理

台灣的 FHIR 生態

4,233 字 11 分鐘閱讀 7 次閱讀
字級
行距

前天我們自己定了一套叫號規格。定完之後有一個問題一直放在心裡:這東西以後要怎麼跟標準接上?

要回答它,得先知道台灣的 FHIR 版圖長什麼樣。這篇就是要把那張圖畫出來。

事先聲明:下面每個版本號、每個發布狀態,都是查證當天的狀態。查證日就是這篇發布的 2026 年 8 月 26 日。IG 會改版,你讀到這篇的時候數字可能已經不一樣了。所以我會把每個主張的來源附上,你可以自己去核對。

底層是 FHIR R4.0.1

整張圖的地基只有一個:FHIR R4.0.1。

先解釋一下什麼是 IG。IG 是 implementation guide 的縮寫,中文叫實作指引。一份 IG 就是一套規定某個場景該怎麼用 FHIR 的文件。

下面要講的每一份 IG,fhirVersion 欄位填的都是 4.0.1。TW Core 是、TWPAS 是、IPS 是、US Core 也是。

這件事的意義是:這幾份 IG 都沒有動資料模型,只在上面加限制。 大家都用同一套 resource,差別在誰把哪個欄位訂成必填、哪個代碼表訂成必用。

上面一層是 IPS 與 US Core

R4 之上有兩份常被提到的 IG:IPS 和 US Core。

IPS 全名是 International Patient Summary,中文叫國際病人摘要。發布者是 HL7 International 的 Patient Care 工作小組。查證當天是 2.0.1 版。

它定義的是一份病人摘要該有哪些東西,設計目標是跨國就醫時對方看得懂。它自己的說法是這份資料集刻意做得最小。不分科別、不綁特定疾病,但臨床上仍然用得到。

US Core 是美國的核心 IG,查證當天 9.0.0 版。發布者是 HL7 International 的 Cross-Group Projects

它跟美國法規綁在一起。年度改版跟著 USCDI 走,那是美國聯邦訂的互通性核心資料集。它也支援 ONC 那套認證測試,ONC 是美國管醫療資訊政策的單位。

它自述的定位是先把標準的最低要求立起來,美國其他 IG 從這條線往上加。

這裡有一個很容易畫錯的地方:IPS 和 US Core 不是上下層。

兩者的相依清單互不包含,那是 IG 裡的 dependsOn 欄位。US Core 的相依清單裡沒有 IPS,IPS 的相依清單裡也沒有 US Core。它們是平行的,一個是國際的、一個是區域的。IPS 只在文件裡提到參考過 US Core 的經驗。

台灣的最小共識是 TW Core IG

再往下就是台灣了。

TW Core IG 全名是臺灣核心實作指引。發布者欄位填的是衛生福利部,主責單位是資訊處。

查證當天是 1.0.0 版,狀態 active,日期 2025-12-10。頁面上明寫這是目前發布的版本。

它的正式相依宣告有四項:

  • HL7 術語表 7.0.0
  • FHIR extensions 5.2.0
  • IPS 1.1.0
  • SDC 3.0.0(結構化資料擷取,管問卷與表單那一塊)

注意那個 IPS 版本。TW Core 綁的是 1.1.0,不是現行的 2.0.1。畫層級圖標版本號的時候很容易寫錯。

還有一個更容易畫錯的。TW Core 的文件裡寫著它「參考了」IPS 與美國核心實作指引。但是 US Core 不在正式相依清單裡

這個差別很重要。有正式相依代表機器讀得出來、產生 IG 的工具會自動去抓那份套件;只在文件裡寫「參考了」代表那是人的參考,不是機器的關係。所以 US Core 那條線只能畫成虛線,標「參考」,不能畫成繼承。

兩者對照圖,標題「同一份 IG,宣告與敘述不一樣」,副標「US Core 只出現在內文,沒進 dependsOn」。上半部是左右並排的兩張卡片。左邊是白底加淺色外框的卡片,標題為等寬字的 ImplementationGuide.dependsOn,右上角灰字註明機器可讀;一條分隔線之下是四列相依宣告,每列左邊是套件名、右邊是版本號,依序為 hl7.terminology.r4 對 7.0.0、hl7.fhir.uv.extensions.r4 對 5.2.0、hl7.fhir.uv.ips 對以珊瑚色標示的 1.1.0、hl7.fhir.uv.sdc 對 3.0.0。右邊是深藍色實心卡片,標題為 IG 內文,右上角淺灰字註明人讀的敘述;分隔線之下是內文原句「參考了國際病人摘要(International Patient Summary,IPS)1.1.0-CI Build 及美國核心實作指引(US Core Implementation Guide)」,其中 IPS 與 US Core 以白色粗體標出;引文下方一個深紅底標籤,等寬字寫著 hl7.fhir.us.core,後面接小字「左邊沒有」。下半部是一張白底的四欄對照表,欄標題依序是對象、dependsOn、IG 內文、圖上怎麼畫。第一列對象是 hl7.fhir.uv.ips,dependsOn 欄寫「有,1.1.0」,IG 內文欄寫「有」,最右邊是一段深藍色實線加文字「實線,繼承」。第二列對象是 hl7.fhir.us.core,dependsOn 欄以珊瑚色寫著「沒有」,IG 內文欄寫「有」,最右邊是一段灰色虛線加文字「虛線,參考」。圖最下方一行灰字註記寫著兩邊不一致的時候以宣告為準,因為產生 IG 的工具只會去抓 dependsOn 裡的那幾個套件

健保的 TWPAS 站在 TW Core 之上

TW Core 之上還有一層:只管某一個業務場景的 IG。

健保署的 TWPAS IG 已經發布到正式版。查證當天是 1.2.5,全名是臺灣健保事前審查實作指引。

這份 IG 改過名。1.0.9 以前叫「臺灣健保癌症用藥事前審查實作指引」,1.1.0 起改掉了。現行版本的目錄同時列了癌藥與免疫製劑兩個情境,範圍已經不只癌症用藥。現行網站有些地方還留著舊名。

它的相依裡有兩份上游 IG,這點常被忽略。一條是 TW Core 0.3.2,另一條是美國 Da Vinci PAS 2.2.1。所以它的上游不只有台灣的核心,還有一份美國的事前審查 IG。

再看一次那個版本號。TWPAS 繼承的是 TW Core 0.3.2,不是現行的 1.0.0。0.3.2 發布於 2024-12-12,跟 1.0.0 差了將近一年。

這種 IG 跟著核心 IG 升版是有延遲的,這在真實世界很正常。但畫圖的時候不能寫成 1.0.0。

健保署另外還有一份基礎 IG。全名臺灣健保署基礎實作指引,簡稱 TWNHIBASE IG。它的定位是要當健保署所有實作指引的共同基礎。

但它目前只有持續建置版本,還沒正式發布。 版本 0.0.1,狀態 draft。它自己的頁面上就寫著這不是正式出版品,是持續建置版,內容會經常變動。它宣告的正式發布網址在查證當天打開是衛福部的找不到網頁。

更關鍵的一點:TWPAS 1.2.5 的相依清單裡沒有這份基礎 IG。所以「基礎 IG 是所有健保 IG 的底座」目前只是它自己的規劃敘述。這項規劃還沒反映在 TWPAS 的宣告上。

這裡花了不少力氣查證。第一直覺是照著它的定位描述,把它畫成 TWPAS 的下一層。逐份比對 dependsOn 之後發現不成立。畫圖的時候寧可少一層,也不要畫一條不存在的線。

台灣 FHIR 實作指引的層級關係圖,標題「台灣的 FHIR IG 疊在誰之上」,副標「實線是 dependsOn 宣告得出來的,虛線只有文件寫過」。全圖由上而下排成四層,底層畫在最下面。最上面一層是健保署的兩份 IG:左邊是米色底加灰色虛線外框的方塊,等寬字寫著 TWNHIBASE IG 0.0.1,下方灰字註明健保署、draft、持續建置版,尚未正式發布;右邊是白底方塊,寫著 TWPAS IG 1.2.5,下方註明健保署。兩者之間有一條灰色虛線箭頭,由 TWPAS 指向 TWNHIBASE,上方標著「規劃中」。第二層左邊是全圖最大的深藍色實心方塊,白色等寬字寫著 TW Core IG 1.0.0,下方淺藍字註明衛生福利部;右邊是白底方塊 Da Vinci PAS 2.2.1,下方註明 HL7 美國。第一層到第二層有三條深藍色實線箭頭:TWNHIBASE 往下指向 TW Core,標籤是 dependsOn 加珊瑚色的 0.3.2;TWPAS 往下指向 TW Core,標籤同樣是 dependsOn 加珊瑚色的 0.3.2;TWPAS 另有一條往下指向 Da Vinci PAS,標籤是 dependsOn。第三層是兩份國際核心 IG,左邊白底方塊 IPS 2.0.1,下方註明 HL7 International,右邊白底方塊 US Core 9.0.0,下方同樣註明 HL7 International;兩個方塊中間的空白處寫著「互不相依」,沒有任何線把它們連起來。第二層到第三層有兩條線:一條深藍色實線箭頭由 TW Core 往下指向 IPS,標籤是 dependsOn IPS 加珊瑚色的 1.1.0;另一條是灰色虛線箭頭由 TW Core 往下指向 US Core,標籤寫著「參考,不在 dependsOn」。最下面一層是橫跨整個畫面的深藍色實心橫條,左邊等寬白字 FHIR R4.0.1,右邊淺藍小字寫著上面每一份的 fhirVersion 都是 4.0.1;IPS 與 US Core 各有一條深藍色實線箭頭往下接到這條橫條。圖最下方是圖例與註記:一段深藍色實線代表 dependsOn 宣告,機器讀得到;一段灰色虛線代表只有文件敘述,dependsOn 裡沒有;最後一行寫著這兩份 IG 相依的 TW Core 都是 0.3.2,沒有一份跟上現行的 1.0.0

那我們自己那套規格呢

回到開頭那個問題。

前天定的叫號規格,疊在整張圖的最上面,本地擴充層。它不繼承任何一份 IG。它只是在 FHIR R4 的 Appointment 上加一個 extension 與一組自訂的 identifier.system

會停在這個位置,原因很單純:候診叫號進度沒有落在上面任何一份 IG 裡。

但是往上接回標準的路是清楚的,順序有兩步。

第一步,先看我們用的 resource 在 TW Core 底下有沒有 profile。有的話就照它的限制填,別自己另定一套。

第二步,等候診場景被寫進某一份 IG,再把 extension URL 換成那份定的。

這份 IG 不一定要等別人推,自己也可以去提一份。

這一步做得到,是因為前天那個決定。我們只加 extension,沒有改任何既有欄位的語意。 換 URL 是一個字串替換,改語意就是整個資料集要重跑。

這個好處要到往上接標準的那一天才用得上。

第二步不是只能等

上面那句「自己也可以去提一份」,得有地方可以提才算數。有。

衛福部 2025 年 3 月啟動臺灣醫療資訊標準大平台,網址是 medstandard.mohw.gov.tw。IG 的提案與審查作業說明就掛在上面。我看的那一版標的是 2026 年 1 月的 V.4.3。

提案分三類,差別在會不會變成國家標準。

類型 誰提 走到哪裡
Top down 政府機關 只過技術審查,通過就在平台公開
Bottom up 民間單位 技術審加內容審,再由專家會議核定要不要上架為國家標準
民間自由提案 前兩類以外的 在專區實名公開分享,作業說明明寫不涉及國家標準

叫號規格要往上走,走的是 Bottom up 那一條。作業說明對它開的條件是「有急迫性與必要性」。

流程本身不快。審查會議原則上每半年開一次,預計三月與九月,必要時也可以加開。開會前兩週把審查要求的地方改完,才排得進議程。專家會議做成決議之後,草案還要在平台公開三十天蒐集意見,假日也照算。取得共識、調整完才正式公告。

提案要交什麼也寫得很細。交換情境、需求、規劃的標準欄位,還有那些欄位能填哪些代碼、代碼之間怎麼對應。

附件裡有一條正好對得上這篇。IG 的「介紹」章節要明確寫出與 TW Core IG 的繼承關聯。版本與範圍都要寫。

講白一點,前面那張層級圖你得自己畫一次,畫的是你那份規格站在哪。

這個提案方式我也還沒提過,因此,上面只敘述作業說明頁載明的內容。

生態的另一半:誰在做

規格是一回事,有沒有人在做是另一回事。

衛福部辦過第一屆「臺灣 50 優良 SMART 應用程式」徵選。全國 115 件報名,50 件入選。

頒獎典禮在 2026 年 4 月 13 日。SMART on FHIR 的共同創辦人 Mandl 教授到了場。FHIR 的創始人 Grahame Grieve 也來了。

入選的 50 件拆開來看,分布是這樣:

類型 件數 單位數
醫療機構 29 16
科技公司 19 18
學術與研究機構 2 2

這張表有兩件事直接讀得出來。

醫院自行研發跟廠商產品幾乎各佔一半。 29 對 19。台灣現在的 SMART on FHIR 應用有兩條供給線,不是只有廠商在做。

學術端只有 2 項。 這個比例明顯偏低。

還有一個數字差異。醫療機構 29 項只來自 16 個單位,科技公司 19 項卻來自 18 個單位。前者平均一個單位快兩項,後者幾乎一單位一項。

跟著做:翻一次 TW Core IG

今天不寫程式,就只是去官方頁面上找答案。

第一步: 打開 https://twcore.mohw.gov.tw/ig/twcore/,確認首頁標的版本是不是還是 1.0.0。如果不是,代表它又改版了,後面的數字你要自己更新。

第二步: 打開 https://twcore.mohw.gov.tw/ig/twcore/artifacts.html。這一頁列出這份 IG 定義出來的所有 artifact。profile、代碼表、範例都算。往下滑,找 Structures 那幾個區塊。

第三步: 找出 Patient 的 profile。你會看到兩個 id:Patient-twcoreTWPatient

第四步: 找出 Observation 的 profile。這裡會看到一整排,依字母序前六個是 Observation-averageBloodPressure-twcoreObservation-bloodPressure-twcoreObservation-bmi-twcoreObservation-body-height-twcoreObservation-body-temperature-twcoreObservation-body-weight-twcore

看到最後那個沒有?Observation-body-weight-twcore

那就是我們第三幕畫體重趨勢時讀的那個 Observation。你在 sandbox 讀到的是沒套 TW Core 限制的 FHIR R4 resource。TW Core 在它之上加了一層台灣的限制。同一個東西,兩個層級。

第五步:數一下總共有幾個。 想確認的話可以直接讀 IG 的 JSON:

curl -s https://twcore.mohw.gov.tw/ig/twcore/ImplementationGuide-tw.gov.mohw.twcore.json \
  | python3 -c "import json,sys; d=json.load(sys.stdin); r=d['definition']['resource']; print(sum(1 for x in r if x['reference']['reference'].startswith('StructureDefinition/')))"

我跑出來是 99

99 個 StructureDefinition 站在 FHIR R4 原本的 resource 之上,Patient-twcore 就是其中一份。StructureDefinition 是 FHIR 拿來定義 profile 與 extension 的那種 resource。這就是「一份核心 IG 到底在做什麼」最具體的答案。它不是另一套資料模型,是對既有 resource 加限制。

回頭看 day03 認識的那幾種 Resource,再看這 99 個。Patient 還是 PatientObservation 還是 Observation。TW Core 沒有發明新的 resource type。它只是換一組 profile id,多半在後面接 -twcoreTWPatient 那種寫法也有。同一個 Observation 再往下細分成血壓、身高、體重那幾種。

執行結果圖,標題「翻完 TW Core IG 的樣子」,副標「420 筆宣告裡,99 筆是 StructureDefinition」。畫面上有三個綠色圓形編號,與圖片下方三條註記一一對應。上方是一個白色瀏覽器視窗,右上角掛著編號 1,網址列顯示 https://twcore.mohw.gov.tw/ig/twcore/artifacts.html。頁面最上一列是 TW Core IG 加兩顆標籤,淺藍底的 1.0.0 與淺綠底的 active。一條分隔線之下先是灰色分組標題 Patient,底下兩行等寬字的 profile id 為 Patient-twcore 與 TWPatient。接著是灰色分組標題 Observation,後面註明依字母序前六個,底下六行 profile id 依序是 Observation-averageBloodPressure-twcore、Observation-bloodPressure-twcore、Observation-bmi-twcore、Observation-body-height-twcore、Observation-body-temperature-twcore,以及以珊瑚色粗體標示的 Observation-body-weight-twcore,最後這一行左緣掛著編號 2。視窗下半是灰底標著 Console 的面板,兩行輸出:definition.resource 是 420,StructureDefinition 是以珊瑚色放大標示的 99,這一行左緣掛著編號 3。圖片下方三條綠色編號註記:這一頁就是第二步打開的 artifacts 頁,查證當天回 HTTP 200;這個 profile 就是第三幕畫體重趨勢時讀的那個 Observation,TW Core 在它之上又加了一層限制;420 筆 definition.resource 裡,有 99 筆是 StructureDefinition

小結

台灣的 FHIR 層級由下往上有四層,最底下是 FHIR R4.0.1。

我們自己定的那套規格再疊上去,成為第五層的本地擴充層。

畫這張圖最重要的一課,其實跟 FHIR 沒關係:先看機器可讀的宣告,再看文件的敘述。 兩邊不一致的時候,寧可少畫一條線。

明天談一個完全不同的問題。技術都通了,病人要怎麼打開你的 app。