🚀 InsightForge 專案簡介:用務實態度打造 AI 數據分析平台
今天想跟大家介紹我的專案 InsightForge
,這是一個結合了 Laravel 和 FastAPI 的 AI 數據分析平台。我們在這次實作過程中,將系統功能進行了務實的分層:將需要「跟人互動」和「管理業務」的這部分交給 Laravel,而那些需要「跑 AI 模型」和「做大量計算」的重活,則交給 FastAPI 來處理。中間還用了 Redis 幫忙傳話和加速。這樣分工合作,目的就是讓整個系統更穩、更快、更好管理。
🌟 專案亮點:我們做了哪些考量?
在開發 InsightForge
時,我們特別注重以下幾個點:
- 微服務解耦,分工合作: 把網頁介面和業務邏輯交給 Laravel 處理,而 AI 模型推論這種計算密集型的工作則由 FastAPI 負責。這樣各自獨立開發和部署,誰也不會拖累誰。
- 異步高效,不塞車: 透過 Redis 佇列,可以有效「削峰填谷」,即使短時間內湧入大量任務,系統也能依序處理,不會一下子就卡住。
- 即時快取,反應快: 用 Redis 暫存任務狀態和分析結果,並設定 TTL(Time To Live)讓過期資料自動清理。這樣能大幅減少資料庫壓力,讓使用者查詢結果時更快有回應。
- 安全保障,有簽名有隔離: 服務間的 Webhook 回調會透過 HMAC 簽名來驗證資料來源和完整性。同時,Docker 內部網路隔離也確保了各服務之間的通訊安全。
- 容器化部署,環境一致: 使用 Docker Compose 來管理所有服務的容器化部署,確保開發、測試到生產環境的配置都能保持一致,減少「我的電腦跑得動,你的就不行」這種情況。
- 自動化 CI/CD,省心省力: 結合 GitHub Actions,讓程式碼測試和部署流程自動化,加速我們的開發和迭代速度。
🧱 系統架構圖:藍圖長這樣
簡單來說,整個系統的資料流和控制流大概是這樣跑的:
graph TD
A[用戶] -->|POST /api/upload| B[Nginx]
B --> C[Laravel Web/API]
C -->|儲存任務| D[MySQL]
C -->|推至佇列| E[Redis 佇列]
E --> F[Laravel Worker]
F -->|HTTP 請求| G[FastAPI]
G -->|儲存結果| E
G -->|Webhook 回調| C
C -->|查詢結果| A
⚙️ 關鍵技術與設計決策:為什麼選它們?
在技術選型上,我們都是有過一番考量的:
- Laravel 10: 負責處理對外提供的 RESTful API、任務管理、以及將資料持久化到 MySQL。它是整個平台的業務邏輯核心。
- FastAPI: 專責高效能的異步 AI 推論,並透過 Pydantic 模型來進行資料驗證。完成任務後,會以 Webhook 形式回調 Laravel。
- Redis: 扮演雙重角色,既是 Laravel 的佇列後端來處理異步任務,也是 FastAPI 的快取,用於暫存任務狀態和結果,並設定 100 秒的 TTL。這大大提升了系統的反應速度和承載能力。
- MySQL: 作為主要資料庫,儲存所有任務、結果和日誌,方便追蹤與查詢。
- Nginx: 擔任反向代理的角色,統一所有外部流量的入口,並能提供基本的安全防護,同時為未來擴展預留空間。
- Docker Compose: 用來編排多個容器服務,確保開發與部署環境的一致性,省去了一堆環境配置的麻煩。
- GitHub Actions: 實現自動化測試與 Docker 映像推送,確保每次程式碼提交都能經過品質檢查。
技術選型細說:
- Laravel + FastAPI 的組合: 選擇這兩者的主要原因在於 Laravel 擅長快速構建 Web 應用和處理傳統業務邏輯,而 FastAPI 則與 Python 龐大的 AI 生態系統高度相容,非常適合執行計算密集型的 AI 推論任務。這種分工讓各自發揮專長,但也帶來跨語言通訊和運維複雜度增加的挑戰。
- 引入 Redis 的必要性: Redis 以其高性能的記憶體操作,成為佇列和快取的理想選擇。如果沒有 Redis,Laravel 將不得不同步調用 FastAPI,這會導致 API 響應時間增加,在高併發情境下,MySQL 也可能成為性能瓶頸。
- Docker 的優勢: Docker 確保了開發、測試、生產環境的一致性,解決了「環境問題」。同時,容器化也提供了服務間的良好隔離,簡化了部署和管理流程。
角色分工細說:
- Laravel: 扮演平台的 API 入口,負責接收使用者請求、創建分析任務、將任務推入佇列、將結果持久化到 MySQL,並接收來自 FastAPI 的 Webhook 回調。
- FastAPI: 專注於接收任務請求、執行 AI 模型推論、將任務狀態與結果快取到 Redis,並在完成後透過 Webhook 回調 Laravel。
- 協作機制: 兩者主要透過 Redis 佇列和 Webhook 實現異步通訊,確保任務能被高效處理。HMAC 簽名機制則保障了服務間通訊的安全性。
🚀 業界應用場景:這個平台能做什麼?
這個平台的設計彈性很高,可以應用在多種實際的業界場景:
- 數據分析: 自動處理銷售數據、用戶行為,生成洞察報告。
- 智能客服: 結合 NLP 模型,支援意圖識別與自動問答。
- 推薦系統: 根據用戶偏好或行為,實時生成個性化商品或內容推薦。
- 圖像分析: 執行物體檢測、人臉識別等圖像相關的 AI 推論。
- 金融風控: 分析交易模式,及時識別潛在的詐騙行為。
- IoT 維護: 預測設備可能出現的故障,並自動觸發工單進行維護。
🚀 快速啟動:動手試試看
想親身體驗 InsightForge
專案嗎?請依照以下步驟手動設置環境並啟動服務:
前置需求
在開始之前,請確保您的系統上已經安裝了這些基本工具:
- Docker & Docker Compose
- Composer
- Python 3.9+
- Git
手動設置
-
克隆專案:
Bashgit clone https://github.com/BpsEason/InsightForge.git cd InsightForge
-
初始化 Laravel 環境:
Bashcd laravel-app composer install cp .env.example .env php artisan key:generate
-
初始化 FastAPI 環境:
Bashcd ../ai-service python -m venv venv source venv/bin/activate # Windows 環境請用:venv\Scripts\activate pip install -r requirements.txt
-
配置環境變數:
- 編輯
laravel-app/.env
和ai-service/.env
:APP_KEY
:請執行php artisan key:generate
後貼入。LARAVEL_WEBHOOK_SECRET
:請確保兩邊的 Webhook 密鑰設定一致。yourusername
:替換成您自己的 Docker Hub 用戶名(如果需要推送到 Docker Hub)。- 請確認
REDIS_HOST=redis
和DB_HOST=db
,確保容器間可以互相連線。
- 編輯
-
啟動容器:
Bashcd .. docker-compose build docker-compose up -d
-
執行資料庫遷移:
Bashdocker-compose exec laravel-app php artisan migrate
-
訪問服務:
- API 健康檢查:
http://localhost/api/health
- FastAPI 文檔 (Swagger UI):
http://localhost/fastapi/docs
- API 健康檢查:
📁 目錄結構:一目瞭然
專案的結構設計得很直觀,方便您快速找到需要的檔案:
InsightForge/
├── laravel-app/ # Laravel 應用程式核心
│ ├── app/Controllers/Api/DataUploadController.php # 處理資料上傳的 API
│ ├── app/Jobs/ProcessAnalysisTask.php # 處理 AI 分析任務的 Job
│ ├── database/migrations/ # 資料庫遷移檔案
│ ├── routes/api.php # API 路由定義
│ ├── .env.example # 環境變數範例
│ └── Dockerfile # Laravel 服務的 Dockerfile
├── ai-service/ # FastAPI AI 服務核心
│ ├── main.py # FastAPI 主應用程式
│ ├── model/your_model.py # 模擬 AI 模型或真實模型載入邏輯
│ ├── tests/ # FastAPI 測試檔案
│ ├── .env.example # 環境變數範例
│ └── Dockerfile # FastAPI 服務的 Dockerfile
├── bin/ # 實用腳本 (此處不再包含 setup.sh,若有其他腳本可保留)
├── nginx/nginx.conf # Nginx 配置檔案
├── docker-compose.yml # Docker Compose 配置檔案
└── .github/workflows/ci.yml # GitHub Actions CI/CD 配置
🔑 關鍵程式碼:看看怎麼寫的
這裡我們挑選了 Laravel 和 FastAPI 中最核心的幾個片段,讓您了解它們是如何協同工作的。
Laravel:資料上傳與任務分發
這個控制器負責接收用戶上傳的資料,進行基本驗證,然後創建一個新的分析任務,並將它推送到 Redis 佇列,讓後台的 Worker 去處理。
// laravel-app/app/Http/Controllers/Api/DataUploadController.php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\AnalysisTask;
use App\Jobs\ProcessAnalysisTask;
use Illuminate\Support\Str;
class DataUploadController extends Controller
{
// 處理用戶上傳,創建任務並推至佇列
public function upload(Request $request)
{
// 驗證輸入資料與任務類型
$request->validate([
'data' => 'required|json',
'task_type' => 'required|string|in:sentiment_analysis,named_entity_recognition',
'model_version' => 'required|string',
]);
// 創建任務,生成唯一 UUID 作為 task_id
$task = AnalysisTask::create([
'task_id' => (string) Str::uuid(),
'task_type' => $request->task_type,
'data_payload' => $request->data,
'model_version' => $request->model_version,
'status' => 'pending',
]);
// 分發任務至 Redis 佇列,由 ProcessAnalysisTask Job 異步處理
ProcessAnalysisTask::dispatch($task);
// 返回成功訊息和任務 ID,狀態碼 202 表示請求已接受但尚未完成
return response()->json(['message' => '任務已接收', 'task_id' => $task->task_id], 202);
}
}
FastAPI:任務處理與結果回調
FastAPI 這邊接收到來自 Laravel 的任務後,會進行 AI 推論,並將結果回報。
# ai-service/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import redis, json, requests, hmac, hashlib, asyncio
from dotenv import load_dotenv
import os, logging
# 配置日誌與環境變數
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
load_dotenv()
app = FastAPI()
# 初始化 Redis 客戶端,用於任務狀態快取
redis_client = redis.StrictRedis(host=os.getenv('REDIS_HOST', 'redis'), port=6379, decode_responses=True)
# 模擬 AI 模型,執行推論
class MockAIModel:
async def predict(self, data_payload: dict, task_type: str) -> dict:
# 這裡模擬情感分析,根據文本中的關鍵字判斷情感
text = data_payload.get('text', '')
if task_type == 'sentiment_analysis':
sentiment = 'Positive' if '好' in text else 'Neutral'
return {'sentiment': sentiment, 'score': 0.95}
# 如果有其他任務類型,可以繼續擴展
return {}
# 定義請求資料模型,FastAPI 會自動驗證
class AnalyzeRequest(BaseModel):
task_id: str
data: str
task_type: str
model_version: str
webhook_url: str
webhook_secret: str | None # Webhook 密鑰用於 HMAC 簽名驗證
mock_model = MockAIModel() # 實例化模擬模型
# 處理分析任務的 API 端點
@app.post("/analyze")
async def analyze_task(request: AnalyzeRequest):
# 將任務狀態設定為 'processing' 並儲存至 Redis,設定 100 秒過期
redis_client.hmset(f"task:{request.task_id}", {'status': 'processing', 'data': request.data})
redis_client.expire(f"task:{request.task_id}", 100)
try:
# 解析輸入資料並執行 AI 推論
data_json = json.loads(request.data)
result = await mock_model.predict(data_json, request.task_type)
# 推論完成後,更新 Redis 中的任務狀態和結果
redis_client.hmset(f"task:{request.task_id}", {'status': 'completed', 'result': json.dumps(result)})
# 準備 Webhook 回調 payload
payload = {'task_id': request.task_id, 'status': 'completed', 'result': result}
headers = {'Content-Type': 'application/json'}
# 如果有設定 webhook_secret,則生成 HMAC 簽名並加入到 Header 中
if request.webhook_secret:
signature = hmac.new(request.webhook_secret.encode(), json.dumps(payload).encode(), hashlib.sha256).hexdigest()
headers['X-Webhook-Signature'] = signature
# 發送 POST 請求回調 Laravel
requests.post(request.webhook_url, json=payload, headers=headers)
except Exception as e:
# 如果處理過程中出錯,記錄錯誤狀態至 Redis 和日誌
redis_client.hmset(f"task:{request.task_id}", {'status': 'failed', 'error': str(e)})
logger.error(f"Task {request.task_id} failed: {e}")
# 回應 Laravel 任務正在處理中
return {'message': '任務處理中', 'task_id': request.task_id}
📜 API 文件與測試指南
為了方便開發和測試,我們提供了以下 API 訪問方式:
Swagger 文檔
FastAPI 內建了 Swagger UI,您可以直接透過瀏覽器訪問 http://localhost/fastapi/docs
來查看 /analyze
端點的詳細說明和試用界面。
- POST /analyze: 接收任務資料,執行 AI 推論,並返回任務 ID。
Postman 測試示例
您可以使用 Postman 或類似的工具來測試 API。
-
上傳任務:
向 http://localhost/localhost/api/data/upload 發送 POST 請求,並帶上 JSON 格式的數據。
Bashcurl -X POST http://localhost/api/data/upload \ -H "Content-Type: application/json" \ -d '{"data":"{\"text\":\"好消息!\"}","task_type":"sentiment_analysis","model_version":"v1.0"}'
正常情況下,您會收到類似以下的成功回應:
JSON{"message":"任務已接收","task_id":"uuid"}
-
查詢結果:
目前用戶端查詢任務狀態和結果的方式,主要透過 FastAPI Webhook 回調自動更新到 MySQL。未來可以考慮提供一個 /api/result/{task_id} 的 API 讓用戶直接查詢。
測試流程建議:
- 發送
/api/data/upload
請求後,您可以觀察laravel-worker
的 Docker 日誌 (docker-compose logs laravel-worker
),看任務是否被取出並處理。 - 接著檢查
ai-service
的 Docker 日誌 (docker-compose logs ai-service
),確認 AI 推論是否完成。 - 最後,您可以登入 MySQL 資料庫,查看
analysis_tasks
表格,確認任務狀態是否已更新,以及analysis_results
表格是否有新的結果數據。
📈 性能、擴展與優化策略
為了使 InsightForge
能應對實際的流量和變化,我們在性能、擴展和優化方面採取了多種策略:
11. 應對分析任務量激增與水平擴展
當分析任務量激增時,InsightForge
透過以下策略進行應對和擴展:
- 佇列削峰: Redis 佇列作為緩衝區,能有效「削峰填谷」,避免瞬間流量高峰壓垮 Laravel API 服務,確保服務響應的穩定性。
- 服務水平擴展:
- Laravel Worker: 當佇列任務積壓時,可透過增加
laravel-worker
容器實例數量(例如docker-compose scale laravel-worker=3
)來並行處理任務。 - FastAPI AI 服務: 當 AI 推論負載過高時,可增加
ai-service
容器實例。Nginx 作為反向代理可配置負載均衡,將請求均勻分發給多個 FastAPI 實例。 - 基礎設施擴展: 必要時可擴展 Redis(集群)和 MySQL(主從複製)來分擔壓力。
- Laravel Worker: 當佇列任務積壓時,可透過增加
- 容器化優勢: Docker 容器化的特性使得各服務能夠非常方便地進行水平擴展,無論是在本地 Docker Compose 環境還是雲端容器編排平台(如 Kubernetes)。
12. AI 模型更新時的無停機部署
AI 模型不斷演進,實現無停機部署是關鍵。我們計劃採用以下策略:
- 藍綠部署/金絲雀部署:
- 藍綠部署: 新舊模型版本服務同時運行。待新版本穩定後,透過更新 Nginx 配置,將流量一次性或逐步從舊版本切換到新版本。舊版本服務在切換完成並確認無問題後才停止。
- 金絲雀部署: 更為保守,新版本服務部署後,只將少量(例如 10%)流量路由到新版本,嚴密監控其錯誤率和性能。確認穩定後,再逐步增加新版本流量比例。
- 模型版本管理:
AnalysisTask
中包含model_version
欄位,這使得即使在部署過渡期,舊任務仍可由舊模型處理,新任務由新模型處理。FastAPI 內部可維護多模型實例,根據請求的model_version
動態路由。
13. 系統運行狀況監控
為確保系統穩定運行,我們將實施全面的監控策略:
- 監控工具: 結合 Prometheus (指標收集)、Grafana (視覺化儀表板) 和 ELK Stack (Logstash, Elasticsearch, Kibana, 用於日誌分析)。
- 日誌收集: 所有服務日誌(Laravel logs, FastAPI logs)將被統一收集並集中分析。
- 告警機制: 設定關鍵指標的閾值,一旦觸發(如 CPU 使用率過高、佇列長度異常),即透過 Alertmanager 發出告警通知。
- 關鍵監控指標:
- 服務健康: Docker
healthcheck
狀態、API 響應時間、錯誤率。 - 任務處理: Redis 佇列長度、任務處理時間、任務失敗率。
- 資源使用: 容器 CPU/記憶體使用率、Redis 記憶體、MySQL 查詢性能。
- 網路狀況: Nginx 請求量、Webhook 延遲與失敗率。
- 服務健康: Docker
14. 異常處理與資料一致性保障
系統異常難以避免,我們重視其處理與資料一致性:
- 異常處理:
- Laravel Job 重試:
ProcessAnalysisTask
Job 配置 3 次重試,超時 120 秒,失敗時記錄詳細日誌。 - FastAPI 回調重試: (待實現) FastAPI 發送 Webhook 時應具備重試機制,確保結果送達。
- 服務自動恢復: Docker Compose 的
healthcheck
可自動重啟不健康的容器。 - 死信佇列: 失敗的任務可進入死信佇列,以便後續分析與手動介入。
- Laravel Job 重試:
- 資料一致性:
- 冪等性:
task_id
(UUID) 確保即使重複請求或回調,每個任務只被唯一處理,避免數據重複。 - 資料庫事務: Laravel 在接收 Webhook 並更新資料庫時,將使用
DB::transaction
,確保多個數據庫操作的原子性(要嘛全成功,要嘛全失敗)。 - 最終一致性: Redis 作為快取可能與 MySQL 存在短暫不一致,但透過回調重試與資料庫事務,最終會達成數據一致。
- 冪等性:
15. 除了 Webhook Secret
,其他安全措施
除了服務間通訊的 HMAC 簽名,我們還實施多層次安全防護:
- API 認證: 對外提供的 API 將採用 OAuth2 或 JWT 等標準認證機制,確保只有合法用戶或服務能訪問。
- 輸入驗證: Laravel
Request::validate()
和 FastAPI Pydantic 模型對所有輸入資料進行嚴格驗證,防止惡意數據注入。 - 網路安全: 啟用 HTTPS (TLS/SSL) 加密所有傳輸數據。Docker 內部網路隔離限制了外部對 FastAPI 的直接訪問。
- 權限控制: (待實現) 針對管理後台和特定資源,將實施基於角色的訪問控制(RBAC)。
- 防禦常見攻擊: Nginx 配置常見 HTTP Headers (如
X-Frame-Options
) 和請求速率限制,防範點擊劫持、XSS 及 DDoS 攻擊。 - 敏感資料保護: 所有敏感資訊(API 金鑰、資料庫密碼)儲存於環境變數中(
.env
),不直接寫入程式碼,並考慮對資料庫中的敏感欄位進行加密。
📈 未來展望與進階計畫
InsightForge
還有很大的成長空間,我們規劃了以下主要方向:
- 功能擴展:
- 即時狀態通知: 引入 WebSocket (如 Laravel Reverb) 實現任務狀態的即時更新,提升用戶體驗。
- 視覺化儀表板: 開發一個更完善的 Vue.js 和 ECharts 儀表板,將分析結果以更直觀的方式呈現出來。
- 雲端部署:
- 規劃將平台部署至 AWS (ECS/EKS) 或 GCP (Cloud Run/GKE) 等雲端平台。
- 利用雲端託管服務 (如 AWS RDS/ElastiCache, GCP Cloud SQL/Memorystore) 和 Auto Scaling,確保高可用性與彈性擴展。
- 結合 GitHub Actions 自動化 CI/CD 流程,推送到雲端容器註冊表 (ECR, Artifact Registry)。
- 模型生命週期管理:
- 實現 A/B 測試,比較不同 AI 模型版本的實際效果。
- 考慮整合 MLflow 或 Kubeflow Pipelines 等 MLOps 工具,管理 AI 模型的訓練、版本、部署與監控的整個生命週期。
- 優化模型的動態載入與卸載機制,減少記憶體開銷。
- 新增 AI 模型分析功能開發:
- 當需要新增新的分析功能(例如文本分類)時,開發流程將涵蓋:
- 在
ai-service/model/your_model.py
中實現新的模型邏輯,並更新requirements.txt
。 - 修改 FastAPI
main.py
中的task_type
判斷邏輯並調用新模型。 - 更新 Laravel API 的驗證規則,並處理可能的資料庫或日誌調整。
- 進行全面的單元測試和端到端整合測試。
- 透過藍綠部署等策略安全地發布新功能。
- 在
- 當需要新增新的分析功能(例如文本分類)時,開發流程將涵蓋:
沒有留言:
張貼留言