知識與實務

商業實務・AI 應用・人才發展

AI 工作實務

FastAPI 入門實作:用報價 API 看懂型別驗證、錯誤回應與非同步邊界

FastAPI 能把 Python 函式整理成有明確輸入、輸出與文件的 API,但不會自動完成業務授權或讓模型推論加速。這份教學建立一個可在本機重跑的報價檢查服務,用金額邊界、非法請求與回應欄位測試,驗證介面是否符合約定。

FastAPI 介面連接多個 API 路徑

FastAPI 能把 Python 函式整理成有明確輸入、輸出與文件的 API,但不會自動完成業務授權或讓模型推論加速。這份教學建立一個可在本機重跑的報價檢查服務,用金額邊界、非法請求與回應欄位測試,驗證介面是否符合約定。

專題編輯:Derek Chou|AI 技術與架構編輯 · 文件核對 2026.11.09

FastAPI 介面連接多個 API 路徑

先把「模型會回答」改成可交接的介面

資料團隊在 Notebook 呼叫模型成功,與另一套系統能穩定使用它,是不同的成果。接手者至少需要知道必填欄位、資料型別、失敗狀態與輸出格式。如果 API 有時回傳文字、有時回傳物件,或把「需要人工覆核」混成「已核准」,前端即使收到 HTTP 200,也可能做出錯誤動作。

FastAPI 可依 Pydantic 模型讀取與驗證請求,並生成 OpenAPI 規格。本文把練習範圍限定在介面契約:建立 POST /quotes/review,接收合成客戶代碼、幣別與金額,回傳是否超過教學門檻。沒有呼叫 AI 模型、查詢真實客戶、儲存報價或執行核准。這樣可以先驗證最容易被忽略的交接條件,再決定是否接上外部系統。

這個範例究竟保證什麼?

欄位或行為本次約定驗收方式
customer_id去除首尾空白後,長度為 1 至 40 字元空白或過長回傳 422
currency必填,僅接受 TWDUSD 或缺值回傳 422
amount正值,整數最多 10 位、小數最多 2 位(不計尾端零)零、負數、超出精度或範圍回傳 422
教學門檻大於 100,000 才標示需覆核分別測試 99,999.99、100,000.00、100,000.01
回應只有 review_required 與 reason內部診斷欄位不能出現在 JSON

金額以 Decimal 表達,請求範例使用字串傳遞十進位數值,避免先經用戶端浮點計算而失去精度。max_digits=12 搭配 decimal_places=2,在本例限制整數最多 10 位、小數最多 2 位,計算小數位時不計尾端零:"10.000" 可接受,"10.001" 則不合格。這是教學契約,不是宣稱所有新台幣業務都需要相同精度。幣別換算、稅額、四捨五入與真正授權門檻,都需要另外定義。

review_required=false 僅表示沒有超過這條示範規則;程式故意回傳「未代表核准」,避免接手者把檢查結果當成實際批准。

步驟一:建立隔離環境並確認版本

本次於 2026 年 11 月 9 日,在 macOS 13.7.8、Python 3.12.14 的獨立虛擬環境執行。使用 FastAPI 0.162.2、Pydantic 2.14.3、Starlette 1.10.0、Uvicorn 0.54.0、HTTPX 0.28.1 與 pytest 9.2.0。這是本次測試組合,不是所有平台或未來版本的相容性保證。

先下載並解壓 FastAPI 教學專案,在包含 main.py 的資料夾執行:

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements-lock.txt
python -V

檔案包括 main.py、test_main.py、精確版本清單及 README。上面是 macOS/Linux 的啟用方式;Windows 可用 .venv\Scripts\Activate.ps1,但本輪未執行 Windows 驗證。若安裝出現版本或網路錯誤,先確認啟用的是這個 .venv,不要改動共用 Python 或忽略安裝失敗。

步驟二:用資料模型界定輸入與輸出

main.py 的核心如下;可直接在範例檔中對照與修改。

from decimal import Decimal
from typing import Literal
from fastapi import FastAPI
from pydantic import BaseModel, ConfigDict, Field

app = FastAPI(title="Quote Review Lab", version="1.0.0")

class QuoteInput(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")
    customer_id: str = Field(min_length=1, max_length=40)
    currency: Literal["TWD"]
    amount: Decimal = Field(gt=0, max_digits=12, decimal_places=2)

class QuoteResult(BaseModel):
    review_required: bool
    reason: str

@app.get("/health")
def health():
    return {"status": "ok"}

@app.post("/quotes/review", response_model=QuoteResult)
def review_quote(payload: QuoteInput):
    needs_review = payload.amount > Decimal("100000.00")
    return {
        "review_required": needs_review,
        "reason": "超過教學門檻,須人工覆核" if needs_review else "未超過教學門檻,未代表核准",
        "internal_rule": "LAB_ONLY_100000_TWD",
    }

extra="forbid" 會拒絕契約外欄位,適合本次要及早發現拼字錯誤的練習;正式 API 是否允許未知欄位,則是版本相容性選擇。response_model 依對外模型驗證與過濾輸出,因此刻意放入的 internal_rule 不會傳給呼叫者。這不表示敏感資料可以任意塞進回應:日誌、例外訊息與其他端點仍須另外審查。

步驟三:先測邊界,再啟動伺服器

執行:

python -m pytest -q

範例測試直接透過 FastAPI 的 TestClient 執行 ASGI 應用,不需要連外。它不只確認正常請求有 200,也測試以下容易造成介面誤判的情況:

  • 三個門檻值是否依大於關係分類,而不是不小心改成大於等於。
  • 零、負數、扣除尾端零後仍超過兩位小數、11 位整數與 NaN 是否被拒絕。
  • "10.000" 是否可接受,以及 "9999999999.99" 是否仍在 10 位整數與 2 位小數的合法邊界內。
  • 空白客戶代碼、過長代碼、錯誤或缺少幣別、多餘欄位是否回傳 422。
  • 正常回應是否只有兩個公開欄位,OpenAPI 是否列出三個必填欄位。

本次結果為 16 項測試通過。測試環境另出現 Starlette 對 HTTPX TestClient 的棄用提示;它沒有造成測試失敗,紀錄已保留。未來調整測試用戶端或升級依賴時,仍應重跑這些案例,不能只移除警告文字就當成相容。

想知道測試是否真的能擋錯,可以在自己的練習副本把門檻比較改為 >= 再執行;100000.00 這個案例應失敗。還原後必須恢復全部通過。這是讀者可做的故障練習,不能把未執行的改動當成本文已測結果。

步驟四:在本機呼叫並檢視文件

啟動只綁定本機的伺服器:

python -m uvicorn main:app --host 127.0.0.1 --port 8000

開啟 http://127.0.0.1:8000/docs 可檢視互動文件;/openapi.json 是機器可讀的契約。在另一個終端機送出:

curl -i http://127.0.0.1:8000/quotes/review \
  -H 'Content-Type: application/json' \
  -d '{"customer_id":"SYNTHETIC-001","currency":"TWD","amount":"100000.01"}'

預期為 HTTP 200,review_required 是 true,且沒有 internal_rule。把金額改成 "0",應得到 HTTP 422 與欄位驗證錯誤。注意 422 是這個請求不符合模型的訊號,不代表框架當機;應修正輸入,而不是把驗證關掉。

本輪自動驗證涵蓋 TestClient 的請求、回應與文件路徑;上面的 Uvicorn/curl 是可重跑的本機呼叫方式,不能據此推論已完成對外部署、瀏覽器互動或壓力測試。練習結束以 Ctrl+C 停止伺服器。

步驟五:決定同步、非同步與長任務的界線

本例只做短時間的條件比較,所以使用一般 def,目的是讓新手先看懂契約。FastAPI 會把它呼叫的一般同步路由函式放到執行緒池處理;但你在 async def 裡直接呼叫的普通工具函式,不會因此自動搬到背景。若其中執行阻塞式 SDK 或耗時運算,就可能拖住事件迴圈。

接上模型時,先查 SDK 是否提供真正的非同步 I/O,再安排逾時、併發上限與取消。CPU 密集推論需要評估程序或獨立服務;很長的文件解析則可考慮工作佇列,回傳任務 ID,讓用戶查詢狀態。這些是後續架構選擇,本文沒有做模型延遲、排隊容量或效能排名的實驗。

重試也不能只靠「失敗就再送」。若端點可能新增訂單或扣款,先設計冪等識別與重複請求處理;否則網路逾時可能只是回應遺失,服務端其實已經完成動作。本例沒有副作用,仍不能當成所有 API 都可安全重試的證明。

常見失敗要對應哪個修正?

現象優先確認恢復方式
No module named fastapi終端機是否使用正確 .venv啟用環境,再以 python -m pip 安裝
Could not import module main執行位置是否包含 main.py切回範例根目錄
8000 埠無法啟動是否已有自己的練習服務停止原服務或改用其他本機埠,並同步改請求網址
正常業務資料回傳 422契約是否只接受 TWD、兩位小數及正值檢查 detail,由 API 設計者決定是否修改契約
所有測試通過卻無法給同事用是否只有本機介面測試另驗證認證、授權、部署網路及實際整合

從教學 API 到服務交付,還差哪些證據?

這個專案沒有登入、資料庫、配額或機密管理,因此只應使用合成資料並保留在本機。/health 也只表示程式能回覆,沒有證明模型、資料庫或下游服務已就緒。正式化時需要依真實用途補上使用者與租戶權限、請求大小限制、稽核日誌、監控告警及回復流程。

交接時,最有用的成果是讓另一位工程師用相同版本重跑範例,說清楚 200、422 與業務核准之間的差別,並能指出尚未實作的能力。框架解決的是介面開發的一部分;讓資料、決策與責任對得起來,仍要靠具體測試與流程設計。

官方資料與素材說明

本文程式、測試與情境為教學用途,資料均為合成資料。封面沿用提供之原創概念圖,不是產品操作截圖;本文未宣稱真實企業核准成效或對外部署結果。

內容提供:TARAISG。本文由 AI 協助整理與查核;專題編輯為天地人 AI 編輯計畫的策展角色,未宣稱經具名人工或專家審核。

AI 生成內容

本文由 TARAISG(TIANDIREN AI SOLUTION GROUP)使用 AI 模型產生正文、整理來源並設計實務工具。方法依據與限制列於文末;案例為明確標示的教學假設。未有具名紀錄時,不宣稱經人工或專家審核。

查看內容製作與更正說明

立即領!558元學習投資折抵金

能力投資季。立即領取 558 元學習金!全站線上課立即折抵。只需填寫 Email,即可輕鬆獲得,先領起來,不要錯過!

立即領!559元學習投資折抵金

能力投資季。立即領取 559 元學習金!全站線上課立即折抵。只需填寫 Email,即可輕鬆獲得,先領起來,不要錯過!

立即領!579 元學習金

學習,看見新可能。 10/14 前領取 579 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!599 元學習金

學習,帶來新可能。 09/09 前領取 558 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!558 元學習金

學習,發現新大陸。 8/29 前領取 558 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!559 元學習金

學習,連結新亮點。 8/14 前領取 559 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!555 元學習金

學習,發現更多視角。 6/14 前領取 555 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!556 元學習金

學習,累積無限可能。 5/29 前領取 556 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!557 元學習金

學習,讓我們發現未曾想像的可能!5/14 前領取 557 元折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

立即領!579 元折抵金

知識就是力量,專業成就未來!3/18 前領取 579 元課程折抵金,解鎖數百堂高品質線上課程,提升職場競爭力與專業技能。只需填寫Email,即可輕鬆獲得,投資自己從現在開始!

年終學習金

年終之餘用學習投資自己!填入 Email ,立即領取 588 元年終學習金!數百堂線上課程立即折抵,先領取收藏起來!