2025年6月17日 星期二

使用 FastAPI 和 Docker 構建情感分析 API

本教學將引導您使用 Python 的 FastAPI 框架和 Hugging Face 的 transformers 函式庫,建立一個功能完善的情感分析 API,並透過 Docker 實現容器化部署。這個專案結構清晰,不僅適合分享至 GitHub,也便於部落格讀者理解和實作。

為何選擇 FastAPI?

FastAPI 是一個現代化、高效能的 Python Web 框架,用於基於標準 Python 類型提示構建 API。它具有以下顯著優勢:

  • 高效能:基於 Starlette (Web 部分) 和 Pydantic (數據驗證),其效能可媲美 Node.js 和 Go。
  • 自動生成文件:提供互動式的 Swagger UI 和 ReDoc,極大地方便了 API 的測試與文檔維護。
  • 強大驗證:透過 Pydantic 實現穩健的請求/回應數據驗證與自動錯誤處理。
  • 支援異步:充分利用 Python 的 async/await 特性,高效處理並行請求,提升應用程式的響應能力。

專案設計概要

我們的目標是創建一個 API,能夠:

  1. 接收用戶提交的文本。
  2. 使用預訓練的情感分析模型判斷文本的情感(positivenegative)。
  3. 返回情感標籤和置信度。
  4. 提供健康檢查端點。
  5. 支持 Docker 容器化。

技術棧

  • FastAPI:API 框架。
  • Transformers (Hugging Face):AI 模型庫,我們將使用 distilbert-base-uncased-finetuned-sst-2-english 模型。
  • Pydantic:數據驗證和序列化。
  • Uvicorn:ASGI 伺服器。
  • Docker:容器化部署工具。

專案結構

sentiment-analysis-api/
├── app/
│   └── main.py
├── .dockerignore
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── README.md

檔案用途說明:

  • app/main.py:包含 FastAPI 應用程式的核心邏輯,包括 API 端點和情感分析模型初始化。
  • requirements.txt:列出專案所有 Python 依賴庫及其精確版本。
  • .dockerignore:指定 Docker 在構建映像時應忽略的檔案和目錄,有助於減小映像體積。
  • Dockerfile:定義了如何構建 Docker 映像的步驟和指令。
  • docker-compose.yml:用於定義和運行多容器 Docker 應用程式,這裡用於簡化單個服務的啟動與管理。
  • README.md:專案的 GitHub 文件,包含專案說明、設置指南、API 使用示例等。

逐步實作

第一步:建立專案結構

首先,在您的本地環境中創建上述的檔案與資料夾結構。

第二步:定義依賴 (requirements.txt)

在專案的根目錄下創建 requirements.txt 檔案,並填入以下內容。明確指定版本號可以確保不同環境下的依賴一致性。

fastapi==0.111.0 
uvicorn==0.30.1 
transformers==4.41.2 
torch==2.3.1 
pydantic==2.7.4 

注意transformers 函式庫會自動處理其所需的深度學習框架(如 PyTorch 或 TensorFlow)。為確保環境穩定,我們在這裡明確列出了 torch。你可以根據實際情況和偏好進行調整。

第三步:實作 FastAPI 應用程式 (app/main.py)

app/ 資料夾內創建 main.py 檔案,並將以下程式碼複製貼上。此檔案包含了 API 的核心邏輯,包括模型初始化、健康檢查端點和情感分析端點。

Python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from transformers import pipeline
from typing import Dict

# 初始化 FastAPI 應用程式
# 設定應用程式的標題、描述和版本,這些資訊會在 Swagger UI 中顯示
app = FastAPI(
    title="AI 情感分析 API",
    description="使用預訓練模型進行情感分析的簡單 API。",
    version="1.0.0"
)

# 初始化情感分析模型
# 使用 Hugging Face transformers 庫的 pipeline 功能,加載情感分析模型
# "distilbert-base-uncased-finetuned-sst-2-english" 是一個預訓練的、針對英文情感分析的模型
try:
    sentiment_analyzer = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english")
except Exception as e:
    # 如果模型載入失敗,則拋出異常,這有助於在啟動時發現問題
    raise Exception(f"情感分析模型載入失敗:{str(e)}")

# 定義輸入數據模型
# 使用 Pydantic 的 BaseModel 來定義 API 接收的 JSON 數據結構
# 這確保了輸入數據的類型安全和自動驗證
class TextInput(BaseModel):
    text: str # 定義一個字串類型的 "text" 字段

# 健康檢查端點
# 這是一個簡單的 GET 請求端點,用於檢查 API 是否正常運行
@app.get("/health")
async def health_check():
    """
    健康檢查端點,用於確認 API 服務是否健康運行。
    返回一個包含狀態的 JSON 物件。
    """
    return {"status": "healthy"}

# 情感分析端點
# 這是一個 POST 請求端點,接收一個 TextInput 物件作為請求體
@app.post("/analyze-sentiment")
async def analyze_sentiment(input: TextInput) -> Dict[str, str]:
    """
    對輸入的文本執行情感分析。
    
    請求體應為 JSON 格式,包含一個 `text` 字段。
    
    **參數**:
    - `input`: 包含待分析文本的 TextInput 物件。
    
    **回應**:
    - `text`: 原始輸入文本。
    - `sentiment`: 情感分析結果('positive' 或 'negative',小寫)。
    - `confidence`: 模型對結果的置信度分數(四位小數)。
    
    **錯誤處理**:
    - 若輸入文本為空,返回 400 Bad Request。
    - 若情感分析過程中發生其他錯誤,返回 500 Internal Server Error。
    """
    try:
        # 驗證輸入文本是否為空或只包含空白字元
        if not input.text.strip():
            raise HTTPException(status_code=400, detail="輸入文本不能為空")
        
        # 執行情感分析
        # sentiment_analyzer 會返回一個列表,其中包含一個字典,
        # 該字典包含 'label' (情感標籤) 和 'score' (置信度分數)
        result = sentiment_analyzer(input.text)[0]
        label = result['label'] # 獲取情感標籤 (e.g., 'POSITIVE', 'NEGATIVE')
        score = result['score'] # 獲取置信度分數
        
        # 返回情感分析結果
        return {
            "text": input.text,
            "sentiment": label.lower(), # 將標籤轉換為小寫形式
            "confidence": f"{score:.4f}" # 將置信度格式化為四位小數的字串
        }
    except Exception as e:
        # 捕獲並處理情感分析過程中可能發生的任何異常
        # 將錯誤訊息封裝在 HTTPException 中返回給客戶端
        raise HTTPException(status_code=500, detail=f"情感分析錯誤:{str(e)}")

# 本地測試運行指令
# 當這個腳本直接運行時 (例如:`python main.py`),它會啟動 Uvicorn 伺服器
# 如果透過 Docker 運行,則 CMD 指令會直接啟動 Uvicorn,此塊代碼不會執行
if __name__ == "__main__":
    import uvicorn
    # 設置主機為 "0.0.0.0" 允許從任何 IP 訪問,端口為 8000
    uvicorn.run(app, host="0.0.0.0", port=8000)

第四步:設定 Docker 相關檔案

Docker 讓您的應用程式及其所有依賴能夠打包在一個獨立的、輕量的容器中,無論在哪裡運行都能保持一致的行為。

1. .dockerignore

在專案根目錄下創建 .dockerignore 檔案。它告訴 Docker 在構建映像時應忽略哪些檔案和目錄,這有助於減小映像大小並提高構建速度。

.git
.venv
__pycache__
*.pyc
*.log
.DS_Store

2. Dockerfile

在專案根目錄下創建 Dockerfile。這個檔案包含了構建 Docker 映像所需的所有指令。

Dockerfile
# 使用官方 Python 3.9 的精簡版作為基礎映像
FROM python:3.9-slim-buster

# 設定容器內的工作目錄為 /app
WORKDIR /app

# 將本地的 requirements.txt 檔案複製到容器的工作目錄
# 這一步單獨執行是為了利用 Docker 層的快取機制,當 requirements.txt 不變時,
# 下次構建會直接使用快取層,提高構建速度。
COPY requirements.txt .

# 在容器中安裝所有 Python 依賴
# --no-cache-dir 參數可以減少映像層中 pip 緩存的體積
RUN pip install --no-cache-dir -r requirements.txt

# 將本地的 app/ 資料夾的所有內容複製到容器的工作目錄
# 這包含了您的 main.py 應用程式碼
COPY app/ .

# 聲明容器將會監聽 8000 端口
# 這是一個信息性指令,並不會實際發布端口
EXPOSE 8000

# 定義容器啟動時執行的命令
# 使用 uvicorn 運行 FastAPI 應用程式:
# "main:app" 指的是 app/main.py 文件中的名為 "app" 的 FastAPI 實例
# "--host 0.0.0.0" 讓應用程式監聽所有網絡接口
# "--port 8000" 指定應用程式監聽 8000 端口
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

3. docker-compose.yml

在專案根目錄下創建 docker-compose.yml。Docker Compose 是一個用於定義和運行多容器 Docker 應用程式的工具,即使對於單個服務,它也提供了更便捷的啟動和管理方式。

YAML
version: '3.8' # Docker Compose 檔案格式的版本

services:
  sentiment-api: # 服務名稱,您可以自定義
    build: # 構建此服務的配置
      context: . # 指定 Dockerfile 的構建上下文路徑 (這裡指當前專案根目錄)
      dockerfile: Dockerfile # 指定要使用的 Dockerfile 名稱
    ports: # 端口映射,將宿主機的 8000 端口映射到容器的 8000 端口
      - "8000:8000"
    environment: # 可選:設置環境變數,可以在這裡配置模型路徑或其他應用參數
      # MODEL_NAME: "distilbert-base-uncased-finetuned-sst-2-english"
    restart: always # 當容器異常退出時,總是自動重啟,確保服務的可用性

第五步:撰寫 README 檔案 (README.md)

在專案根目錄下創建 README.md 檔案,這將是您的 GitHub 專案首頁,提供專案的完整概覽、設置和使用說明。

Markdown
# AI 情感分析 API

使用 FastAPI 和 Hugging Face `transformers` 函式庫構建的簡單情感分析 API,採用 `distilbert-base-uncased-finetuned-sst-2-english` 模型對文本進行正面或負面情感分類。

## 功能
- **情感分析**:分析文本並回傳情感(正面/負面)及置信度。
- **健康檢查**:提供端點檢查 API 狀態。
- **互動式文件**:自動生成 Swagger UI。
- **Docker 支援**:包含 Dockerfile 和 Docker Compose,方便部署。

## 技術棧
- **FastAPI**:高效能 Web 框架。
- **Transformers**:提供預訓練 AI 模型。
- **Pydantic**:數據驗證。
- **Uvicorn**:ASGI 伺服器。
- **Docker**:容器化技術。

## 環境需求
- Python 3.8+
- Docker(可選,建議用於部署)

## 本地設置

### 1. 克隆倉庫

首先,將專案倉庫克隆到您的本地機器上:

```bash
git clone [https://github.com/](https://github.com/)[您的用戶名]/sentiment-analysis-api.git
cd sentiment-analysis-api

2. 建立並激活虛擬環境 (推薦)

為了管理專案依賴,強烈建議使用 Python 虛擬環境:

Bash
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS/Linux
source .venv/bin/activate

3. 安裝依賴

激活虛擬環境後,安裝 requirements.txt 中列出的所有依賴:

Bash
pip install -r requirements.txt

4. 運行應用程式

您可以在本地直接運行 FastAPI 應用程式:

Bash
# 從專案根目錄運行,Uvicorn 將會尋找 app/main.py 中的 'app' 實例
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

--reload 參數在開發過程中非常有用,它會監聽程式碼變更並自動重載伺服器。

Docker 部署設置 (推薦生產環境)

使用 Docker 可以更輕鬆地部署和管理應用程式,無需擔心環境依賴問題,確保生產環境與開發環境的一致性。

1. 安裝 Docker

確保您的系統上已安裝 Docker 和 Docker Compose。您可以從 Docker 官方網站 下載並安裝 Docker Desktop。

2. 建構 Docker 映像

在專案根目錄下(Dockerfiledocker-compose.yml 所在的目錄)運行以下命令來構建 Docker 映像:

Bash
docker-compose build

首次構建會下載 Python 基礎映像、安裝依賴和模型,可能需要一些時間。

3. 運行 Docker 容器

構建完成後,啟動服務:

Bash
docker-compose up -d

-d 參數表示在後台運行容器,讓您的終端機保持可用。

4. 檢查容器日誌 (可選)

您可以查看容器的實時輸出日誌,以便於監控和調試:

Bash
docker-compose logs -f sentiment-api

5. 停止並移除容器

當您完成測試並想停止服務時,執行:

Bash
docker-compose down

這將停止並移除由 docker-compose.yml 定義的所有服務的容器和網絡。

API 端點

API 應用程式將在 http://localhost:8000 上運行。

1. 健康檢查

  • GET /health

    用於檢查 API 服務是否正常運行。

    請求示例:

    Bash
    curl http://localhost:8000/health
    

    回應示例:

    JSON
    {"status": "healthy"}
    

2. 情感分析

  • POST /analyze-sentiment

  • Content-Type: application/json

    接受文本輸入並返回其情感分析結果。

    請求體 (JSON):

    JSON
    {
      "text": "這部電影真是太棒了!我強烈推薦它。"
    }
    

    請求示例 (使用 curl):

    Bash
    curl -X POST http://localhost:8000/analyze-sentiment \
         -H "Content-Type: application/json" \
         -d '{"text": "我愛這個產品!"}'
    

    回應示例:

    JSON
    {
      "text": "我愛這個產品!",
      "sentiment": "positive",
      "confidence": "0.9998"
    }
    

    錯誤回應 (空文本):

    JSON
    {
      "detail": "輸入文本不能為空"
    }
    

3. 互動式 API 文檔 (Swagger UI)

訪問 http://localhost:8000/docs 即可查看由 FastAPI 自動生成的交互式 API 文檔,並可以直接在頁面上測試您的 API 端點。

擴展建議

這個專案為您提供了一個堅實的基礎,您可以在此基礎上進行更多複雜的開發和優化:

  • 添加更多 AI 模型:根據業務需求,集成其他 Hugging Face 模型,例如文本摘要、翻譯、命名實體識別等,每個模型可以作為一個獨立的 API 端點。
  • 異步處理:對於耗時較長的 AI 推理任務,考慮使用 FastAPI 的後台任務 (background_tasks) 或整合像 Celery 這樣的任務佇列來實現異步處理,避免阻塞主線程,提高 API 的響應能力。
  • 身份驗證與授權:為您的 API 添加安全性,例如使用 API 鍵、OAuth2 或 JWT 等機制來驗證和授權用戶請求。
  • 性能優化
    • 模型量化/蒸餾:對於部署到資源有限的環境,可以對 AI 模型進行量化或蒸餾,以減小模型大小和計算量。
    • GPU 加速:如果您的伺服器配備了 GPU,配置 transformers 庫使用 GPU 進行推理可以顯著提高性能。
  • 日誌記錄:集成更詳細和結構化的日誌記錄框架(如 Python 內置的 logging 模組或第三方庫 loguru),以便於監控和排查生產環境中的問題。
  • 資料庫整合:如果您需要保存分析結果、用戶數據或進行模型版本管理,可以整合 PostgreSQL、MongoDB 或 SQLite 等資料庫。
  • CI/CD 流水線:將應用程式的測試、構建和部署過程自動化,例如使用 GitHub Actions, GitLab CI/CD 或 Jenkins。

專案 GitHub 連結: https://github.com/BpsEason/sentiment-analysis-api.git

沒有留言:

張貼留言

網誌存檔