dramaling-vocab-learning/docs/archive/AI句子分析規格/系統整合與部署規格.md

887 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 系統整合與部署規格
## 📋 **文件資訊**
- **文件名稱**: 系統整合與部署規格
- **版本**: v2.0
- **建立日期**: 2025-01-25
- **最後更新**: 2025-01-25
- **負責團隊**: DramaLing DevOps團隊
- **適用系統**: AI句子分析功能全棧系統
---
## 🏗️ **系統架構圖**
### **整體架構**
```
┌─────────────────┐ HTTP/JSON ┌──────────────────┐ Gemini API ┌─────────────────┐
│ │ Request │ │ Request │ │
│ Frontend │ ──────────────► │ Backend API │ ──────────────► │ Google Gemini │
│ (Next.js) │ │ (.NET Core) │ │ AI Service │
│ Port 3000 │ ◄────────────── │ Port 5008 │ ◄────────────── │ │
│ │ Response │ │ Response │ │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Local Storage │ │ SQLite Database │
│ - user_level │ │ - Cache Data │
│ - auth_token │ │ - Usage Stats │
└─────────────────┘ └──────────────────┘
```
### **數據流向**
```mermaid
sequenceDiagram
participant U as 用戶
participant F as 前端(3000)
participant B as 後端(5008)
participant G as Gemini API
participant D as 資料庫
U->>F: 1. 輸入英文句子
U->>F: 2. 點擊「分析句子」
F->>F: 3. 驗證輸入(≤300字符)
F->>F: 4. 讀取userLevel (localStorage)
F->>B: 5. POST /api/ai/analyze-sentence
B->>B: 6. 輸入驗證和處理
B->>G: 7. 調用Gemini API
G->>B: 8. 返回AI分析結果
B->>B: 9. 解析和格式化數據
B->>D: 10. 記錄使用統計 (可選)
B->>F: 11. 返回結構化分析結果
F->>F: 12. 計算個人化統計
F->>F: 13. 渲染詞彙標記和統計卡片
F->>U: 14. 顯示完整分析結果
```
---
## 🔄 **前後端整合規格**
### **API整合詳細設計**
#### **前端請求實現**
```typescript
// 位置: frontend/app/generate/page.tsx
const handleAnalyzeSentence = async () => {
try {
const response = await fetch('http://localhost:5008/api/ai/analyze-sentence', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getAuthToken()}` // 可選
},
body: JSON.stringify({
inputText: textInput,
analysisMode: 'full',
options: {
includeGrammarCheck: true,
includeVocabularyAnalysis: true,
includeTranslation: true,
includeIdiomDetection: true,
includeExamples: true
}
})
});
if (!response.ok) {
throw new Error(`API請求失敗: ${response.status}`);
}
const result = await response.json();
handleAnalysisResult(result.data);
} catch (error) {
handleAnalysisError(error);
}
};
```
#### **數據處理邏輯**
```typescript
// 前端個人化統計計算
const calculateVocabularyStats = (vocabularyAnalysis, idioms, userLevel) => {
const userIndex = CEFR_LEVELS.indexOf(userLevel);
let simple = 0, moderate = 0, difficult = 0;
Object.values(vocabularyAnalysis).forEach(word => {
const wordIndex = CEFR_LEVELS.indexOf(word.difficultyLevel);
if (userIndex > wordIndex) simple++;
else if (userIndex === wordIndex) moderate++;
else difficult++;
});
return {
simpleCount: simple,
moderateCount: moderate,
difficultCount: difficult,
idiomCount: idioms.length
};
};
```
### **錯誤處理整合**
#### **前端錯誤處理**
```typescript
const handleAnalysisError = (error) => {
console.error('Analysis error:', error);
// 顯示用戶友善的錯誤訊息
if (error.message.includes('timeout')) {
setErrorMessage('分析服務繁忙,請稍後再試');
} else if (error.message.includes('network')) {
setErrorMessage('網路連接問題,請檢查網路狀態');
} else {
setErrorMessage('分析過程中發生錯誤,請稍後再試');
}
// 提供降級體驗
setFallbackAnalysisView(textInput);
};
```
#### **後端錯誤映射**
```csharp
// 位置: backend/Controllers/AIController.cs
private ApiErrorResponse CreateErrorResponse(string code, string message, object? details, string requestId)
{
var userFriendlyMessage = code switch
{
"INVALID_INPUT" => "輸入格式不正確,請檢查文本內容",
"AI_SERVICE_ERROR" => "AI分析服務暫時不可用請稍後重試",
"RATE_LIMIT_EXCEEDED" => "請求過於頻繁,請稍候再試",
"TIMEOUT" => "分析超時,請嘗試較短的句子",
_ => "系統暫時不可用,請稍後重試"
};
return new ApiErrorResponse
{
Success = false,
Error = new ApiError
{
Code = code,
Message = userFriendlyMessage,
Details = details,
Suggestions = GetSuggestionsForError(code)
},
RequestId = requestId,
Timestamp = DateTime.UtcNow
};
}
```
---
## 🔧 **開發環境配置**
### **環境準備**
#### **必要軟體**
```yaml
開發工具:
- Node.js: >= 18.0.0
- .NET SDK: >= 8.0.0
- Git: >= 2.40.0
- VSCode: 最新版本
瀏覽器支援:
- Chrome: >= 90 (開發調試用)
- Safari: >= 14 (測試用)
- Firefox: >= 88 (測試用)
可選工具:
- Docker: >= 20.0 (容器化部署)
- Redis: >= 6.0 (本地快取測試)
- Postman: API測試
```
#### **環境變數配置**
```bash
# 後端環境變數
export GEMINI_API_KEY="your-gemini-api-key"
export ASPNETCORE_ENVIRONMENT="Development"
export DRAMALING_DB_CONNECTION="Data Source=dramaling_test.db"
# 前端環境變數 (可選)
export NEXT_PUBLIC_API_URL="http://localhost:5008"
export NEXT_PUBLIC_ENVIRONMENT="development"
```
### **啟動流程**
#### **開發環境啟動腳本**
```bash
#!/bin/bash
# 位置: start-development.sh
echo "🚀 啟動 DramaLing 開發環境..."
# 1. 檢查必要軟體
check_prerequisites() {
command -v node >/dev/null 2>&1 || { echo "需要安裝 Node.js"; exit 1; }
command -v dotnet >/dev/null 2>&1 || { echo "需要安裝 .NET SDK"; exit 1; }
}
# 2. 啟動後端 API (Port 5008)
start_backend() {
echo "🔧 啟動後端 API..."
cd backend/DramaLing.Api
dotnet restore
dotnet run &
BACKEND_PID=$!
echo "後端 PID: $BACKEND_PID"
}
# 3. 啟動前端 (Port 3000)
start_frontend() {
echo "🎨 啟動前端..."
cd ../../frontend
npm install
npm run dev &
FRONTEND_PID=$!
echo "前端 PID: $FRONTEND_PID"
}
# 4. 健康檢查
health_check() {
echo "🏥 執行健康檢查..."
sleep 10
# 檢查後端
if curl -f http://localhost:5008/health >/dev/null 2>&1; then
echo "✅ 後端服務正常"
else
echo "❌ 後端服務異常"
fi
# 檢查前端
if curl -f http://localhost:3000 >/dev/null 2>&1; then
echo "✅ 前端服務正常"
else
echo "❌ 前端服務異常"
fi
}
# 執行啟動流程
check_prerequisites
start_backend
start_frontend
health_check
echo "🎉 開發環境啟動完成!"
echo "前端: http://localhost:3000"
echo "後端API: http://localhost:5008"
echo "API文檔: http://localhost:5008/swagger"
```
---
## 🧪 **測試整合策略**
### **整合測試架構**
#### **API整合測試**
```csharp
[TestFixture]
public class AIAnalysisIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly WebApplicationFactory<Program> _factory;
private readonly HttpClient _client;
[SetUp]
public void Setup()
{
_client = _factory.CreateClient();
}
[Test]
public async Task AnalyzeSentence_EndToEnd_ReturnsValidResponse()
{
// Arrange
var request = new
{
inputText = "She just join the team, so let's cut her some slack.",
analysisMode = "full"
};
// Act
var response = await _client.PostAsJsonAsync("/api/ai/analyze-sentence", request);
// Assert
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<AnalysisResponse>();
Assert.That(result.Success, Is.True);
Assert.That(result.Data.VocabularyAnalysis.Count, Is.GreaterThan(0));
Assert.That(result.Data.SentenceMeaning, Is.Not.Empty);
Assert.That(result.Data.Idioms.Count, Is.GreaterThan(0));
}
}
```
#### **前端E2E測試**
```typescript
// 使用 Playwright 或 Cypress
describe('AI Analysis E2E Flow', () => {
test('complete analysis workflow', async ({ page }) => {
// 1. 導航到分析頁面
await page.goto('http://localhost:3000/generate');
// 2. 輸入測試句子
await page.fill('[data-testid="text-input"]',
'She just join the team, so let\'s cut her some slack.');
// 3. 點擊分析按鈕
await page.click('[data-testid="analyze-button"]');
// 4. 等待分析完成
await page.waitForSelector('[data-testid="analysis-result"]', { timeout: 10000 });
// 5. 驗證結果
await expect(page.locator('[data-testid="grammar-correction"]')).toBeVisible();
await expect(page.locator('[data-testid="vocabulary-analysis"]')).toBeVisible();
await expect(page.locator('[data-testid="idioms-section"]')).toBeVisible();
await expect(page.locator('[data-testid="statistics-cards"]')).toBeVisible();
// 6. 測試詞彙點擊
await page.click('[data-testid="word-she"]');
await expect(page.locator('[data-testid="vocab-popup"]')).toBeVisible();
});
});
```
### **性能測試整合**
#### **負載測試配置**
```yaml
# 使用 k6 或 JMeter
負載測試場景:
- 正常負載: 100 用戶,持續 10 分鐘
- 壓力測試: 500 用戶,持續 5 分鐘
- 尖峰測試: 1000 用戶,持續 2 分鐘
性能指標:
- 回應時間P95: < 5秒
- 錯誤率: < 1%
- 吞吐量: > 100 RPS
- 資源使用: CPU < 80%, Memory < 70%
```
---
## 🚀 **部署架構**
### **環境配置**
#### **開發環境 (Development)**
```yaml
基礎設施:
- 本地開發機器
- SQLite 資料庫
- In-Memory 快取
- Gemini API (測試金鑰)
配置特點:
- 詳細日誌輸出
- 熱重載支援
- Swagger API 文檔
- CORS 寬鬆政策
```
#### **測試環境 (Staging)**
```yaml
基礎設施:
- 雲端虛擬機 或 Docker 容器
- PostgreSQL 資料庫
- Redis 快取
- Gemini API (測試金鑰)
配置特點:
- 生產環境模擬
- 效能監控啟用
- 自動化測試整合
- 安全掃描
```
#### **生產環境 (Production)**
```yaml
基礎設施:
- Kubernetes 叢集 或 雲端服務
- PostgreSQL 高可用性叢集
- Redis 叢集
- Gemini API (生產金鑰)
- CDN 和負載均衡
配置特點:
- 高可用性 (99.9%+)
- 自動擴容
- 全面監控和告警
- 災難恢復機制
```
### **容器化部署**
#### **Docker Compose 配置**
```yaml
# docker-compose.yml
version: '3.8'
services:
# 後端 API 服務
backend:
build:
context: ./backend/DramaLing.Api
dockerfile: Dockerfile
ports:
- "5008:5008"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- GEMINI_API_KEY=${GEMINI_API_KEY}
- ConnectionStrings__DefaultConnection=${DB_CONNECTION}
depends_on:
- database
- redis
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5008/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# 前端服務
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://backend:5008
depends_on:
- backend
# 資料庫服務
database:
image: postgres:15-alpine
environment:
- POSTGRES_DB=dramaling
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
# 快取服務
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
```
#### **Kubernetes 部署配置**
```yaml
# k8s-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dramaling-backend
spec:
replicas: 3
selector:
matchLabels:
app: dramaling-backend
template:
metadata:
labels:
app: dramaling-backend
spec:
containers:
- name: backend
image: dramaling/backend:latest
ports:
- containerPort: 5008
env:
- name: GEMINI_API_KEY
valueFrom:
secretKeyRef:
name: ai-secrets
key: gemini-api-key
- name: ConnectionStrings__DefaultConnection
valueFrom:
configMapKeyRef:
name: app-config
key: db-connection
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 5008
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 5008
initialDelaySeconds: 5
periodSeconds: 5
```
---
## 📊 **監控與可觀測性**
### **日誌整合**
#### **結構化日誌配置**
```json
// appsettings.Production.json
{
"Serilog": {
"Using": ["Serilog.Sinks.Console", "Serilog.Sinks.ApplicationInsights"],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"DramaLing": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"
}
},
{
"Name": "ApplicationInsights",
"Args": {
"instrumentationKey": "{ApplicationInsights:InstrumentationKey}"
}
}
],
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"]
}
}
```
#### **前端錯誤追蹤**
```typescript
// 錯誤邊界和監控
class ErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
// 發送錯誤到監控服務
console.error('React Error Boundary:', error, errorInfo);
// 可選:整合 Sentry 或其他錯誤追蹤服務
if (typeof window !== 'undefined' && window.gtag) {
window.gtag('event', 'exception', {
description: error.toString(),
fatal: false
});
}
}
}
```
### **健康檢查系統**
#### **深度健康檢查**
```csharp
public class SystemHealthCheck : IHealthCheck
{
private readonly IGeminiService _geminiService;
private readonly DramaLingDbContext _dbContext;
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var checks = new Dictionary<string, HealthStatus>();
// 檢查資料庫連接
try
{
await _dbContext.Database.CanConnectAsync(cancellationToken);
checks["database"] = HealthStatus.Healthy;
}
catch (Exception ex)
{
checks["database"] = HealthStatus.Unhealthy;
}
// 檢查 AI 服務
try
{
var isHealthy = await _geminiService.HealthCheckAsync();
checks["gemini_api"] = isHealthy ? HealthStatus.Healthy : HealthStatus.Degraded;
}
catch (Exception ex)
{
checks["gemini_api"] = HealthStatus.Unhealthy;
}
// 檢查記憶體使用
var memoryUsage = GC.GetTotalMemory(false);
checks["memory"] = memoryUsage < 500_000_000 ? HealthStatus.Healthy : HealthStatus.Degraded;
var overallStatus = checks.Values.All(s => s == HealthStatus.Healthy)
? HealthStatus.Healthy
: checks.Values.Any(s => s == HealthStatus.Unhealthy)
? HealthStatus.Unhealthy
: HealthStatus.Degraded;
return new HealthCheckResult(overallStatus,
description: $"System health: {string.Join(", ", checks.Select(c => $"{c.Key}:{c.Value}"))}",
data: checks.ToDictionary(c => c.Key, c => (object)c.Value.ToString()));
}
}
```
---
## 🔒 **安全整合**
### **HTTPS 配置**
```yaml
開發環境:
- HTTP: localhost:3000, localhost:5008
- 自簽證書: dotnet dev-certs https --trust
生產環境:
- HTTPS: 強制重定向
- TLS 1.3: 最低版本要求
- HSTS: 嚴格傳輸安全
- 證書: Let's Encrypt 或企業CA
```
### **CORS 政策**
```csharp
// 開發環境 CORS 配置
services.AddCors(options =>
{
options.AddPolicy("Development", policy =>
{
policy.WithOrigins("http://localhost:3000", "http://localhost:3001")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
options.AddPolicy("Production", policy =>
{
policy.WithOrigins("https://dramaling.com", "https://app.dramaling.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
```
---
## 📈 **監控整合**
### **應用程式監控**
#### **關鍵指標儀表板**
```yaml
業務指標:
- 每日分析次數
- 用戶活躍度
- 功能使用分佈
- AI分析成功率
技術指標:
- API回應時間分佈
- 資料庫查詢性能
- 記憶體和CPU使用
- 錯誤率和異常統計
用戶體驗指標:
- 頁面載入時間
- 首次內容繪製 (FCP)
- 最大內容繪製 (LCP)
- 累積佈局偏移 (CLS)
```
#### **告警配置**
```yaml
嚴重告警:
- API 錯誤率 > 5% (5分鐘內)
- 回應時間P95 > 10秒 (5分鐘內)
- 服務不可用 > 2分鐘
- 資料庫連接失敗
警告告警:
- CPU 使用率 > 80% (10分鐘內)
- 記憶體使用率 > 85% (10分鐘內)
- AI API 調用失敗率 > 10%
- 磁碟空間不足 < 10%
```
---
## 🔧 **故障排除指南**
### **常見問題和解決方案**
#### **連接問題**
```yaml
問題: CORS 錯誤
症狀: "Access to fetch blocked by CORS policy"
解決: 檢查後端 CORS 設定,確認前端域名在允許清單
問題: 連接被拒絕
症狀: "Connection refused" 或 "ECONNREFUSED"
解決: 確認後端服務正在運行,檢查埠號是否正確
問題: 超時錯誤
症狀: "Request timeout" 或響應超過 30 秒
解決: 檢查 AI API 金鑰,網路連接,增加超時設定
```
#### **資料問題**
```yaml
問題: AI 回應格式錯誤
症狀: "Cannot read property 'vocabularyAnalysis' of undefined"
解決: 檢查 Gemini API 回應格式,更新錯誤處理邏輯
問題: 詞彙分析為空
症狀: 分析結果不包含詞彙資訊
解決: 檢查 AI Prompt 設計,確認輸入文本有效
問題: 統計數字不一致
症狀: 統計卡片數字與實際標記不符
解決: 檢查前端統計計算邏輯,確認分類算法正確
```
### **調試工具**
#### **開發調試指令**
```bash
# 檢查服務狀態
curl -I http://localhost:5008/health
curl -I http://localhost:3000
# 測試 API 端點
curl -X POST http://localhost:5008/api/ai/analyze-sentence \
-H "Content-Type: application/json" \
-d '{"inputText":"Test sentence","analysisMode":"full"}'
# 檢查日誌
docker logs dramaling-backend
docker logs dramaling-frontend
# 檢查資源使用
docker stats
top -p $(pgrep dotnet)
```
#### **生產監控指令**
```bash
# 健康檢查
kubectl get pods -l app=dramaling
kubectl describe pod dramaling-backend-xxx
# 查看日誌
kubectl logs -f deployment/dramaling-backend
kubectl logs -f deployment/dramaling-frontend
# 性能監控
kubectl top pods
kubectl top nodes
```
---
## 📋 **部署檢查清單**
### **部署前檢查**
- [ ] 所有測試通過 (單元、整合、E2E)
- [ ] 安全掃描無嚴重漏洞
- [ ] 性能基準測試達標
- [ ] 配置檔案正確設定
- [ ] 環境變數和金鑰配置完成
- [ ] 資料庫遷移腳本準備
- [ ] 監控和告警配置完成
- [ ] 回滾計劃準備
### **部署後驗證**
- [ ] 健康檢查端點回應正常
- [ ] API 功能端到端測試通過
- [ ] 前端頁面載入和功能正常
- [ ] 監控指標顯示正常
- [ ] 日誌記錄正確產生
- [ ] 告警機制測試正常
- [ ] 負載測試驗證性能
- [ ] 安全掃描確認無新漏洞
---
## 🔄 **CI/CD 流程**
### **持續整合流程**
```yaml
觸發條件:
- 主分支推送 (main)
- Pull Request 建立
- 標籤建立 (v*.*.*)
建置步驟:
1. 程式碼檢出
2. 依賴安裝
3. 靜態分析 (ESLint, SonarQube)
4. 單元測試執行
5. 測試覆蓋率檢查
6. 安全掃描
7. 建置 Docker 映像
8. 整合測試執行
部署條件:
- 所有測試通過
- 程式碼覆蓋率 > 80%
- 安全掃描通過
- 人工審核批准 (生產部署)
```
### **持續部署流程**
```yaml
測試環境自動部署:
- 主分支每次推送自動部署
- 自動執行煙霧測試
- 通知團隊部署狀態
生產環境部署:
- 手動觸發或定期發布
- 藍綠部署或滾動更新
- 自動回滾機制
- 部署後監控和驗證
```
---
**文件版本**: v2.0
**DevOps負責人**: DramaLing DevOps團隊
**最後更新**: 2025-01-25
**下次審查**: 2025-02-25
**關聯文件**:
- 《AI句子分析功能產品需求規格》- 產品需求和用戶故事
- 《AI分析API技術實現規格》- API設計和技術實現
- 《AI驅動產品後端技術架構指南》- 架構設計指導原則