dramaling-vocab-learning/docs/03_development/api/AI分析API技術實現規格.md

21 KiB
Raw Blame History

AI分析API技術實現規格

📋 文件資訊

  • 文件名稱: AI分析API技術實現規格
  • 版本: v2.0
  • 建立日期: 2025-01-25
  • 最後更新: 2025-01-25
  • 負責團隊: DramaLing後端技術團隊
  • 對應產品需求: 《AI句子分析功能產品需求規格》

🛠 技術架構概述

系統架構設計

分層架構:
  - API Gateway: 認證、限流、路由
  - Controllers: HTTP請求處理、參數驗證
  - Services: 業務邏輯、AI整合
  - Data Access: 資料庫操作、快取管理
  - External APIs: AI服務、第三方整合

技術棧:
  - 語言: C# / .NET 8
  - 框架: ASP.NET Core Web API
  - AI服務: Google Gemini 1.5 Flash
  - 資料庫: SQLite (開發) / PostgreSQL (生產)
  - 快取: Redis (生產) / In-Memory (開發)
  - 監控: Application Insights

核心設計原則

  • 單一職責: 每個服務類別職責明確
  • 依賴注入: 基於介面的鬆耦合設計
  • 配置外部化: 強型別配置管理
  • 錯誤恢復: 重試機制和降級策略
  • 可觀測性: 結構化日誌和健康檢查

📡 API端點設計

核心分析端點

POST /api/ai/analyze-sentence

功能: 智能英文句子分析

請求格式:

{
  "inputText": "She just join the team, so let's cut her some slack until she get used to the workflow.",
  "analysisMode": "full",
  "options": {
    "includeGrammarCheck": true,
    "includeVocabularyAnalysis": true,
    "includeTranslation": true,
    "includeIdiomDetection": true,
    "includeExamples": true
  }
}

回應格式:

{
  "success": true,
  "processingTime": 2.34,
  "data": {
    "analysisId": "uuid-string",
    "originalText": "原始輸入文本",
    "grammarCorrection": {
      "hasErrors": true,
      "correctedText": "修正後文本",
      "corrections": [
        {
          "position": { "start": 9, "end": 13 },
          "error": "join",
          "correction": "joined",
          "type": "時態錯誤",
          "explanation": "第三人稱單數過去式應使用 'joined'",
          "severity": "high"
        }
      ]
    },
    "sentenceMeaning": "中文翻譯",
    "vocabularyAnalysis": {
      "word": {
        "word": "詞彙",
        "translation": "中文翻譯",
        "definition": "英文定義",
        "partOfSpeech": "詞性",
        "pronunciation": "/IPA發音/",
        "difficultyLevel": "A1-C2",
        "frequency": "high/medium/low",
        "synonyms": ["同義詞陣列"],
        "example": "例句",
        "exampleTranslation": "例句翻譯"
      }
    },
    "idioms": [
      {
        "idiom": "cut someone some slack",
        "translation": "對某人寬容一點",
        "definition": "to be more lenient or forgiving",
        "pronunciation": "/發音/",
        "difficultyLevel": "B2",
        "frequency": "medium",
        "synonyms": ["be lenient", "give leeway"],
        "example": "例句",
        "exampleTranslation": "例句翻譯"
      }
    ],
    "metadata": {
      "analysisModel": "gemini-1.5-flash",
      "analysisVersion": "2.0",
      "processingDate": "2025-01-25T10:30:00Z"
    }
  }
}

GET /api/ai/health

功能: 服務健康檢查

回應格式:

{
  "status": "Healthy",
  "service": "AI Analysis Service",
  "timestamp": "2025-01-25T10:30:00Z",
  "version": "2.0",
  "dependencies": {
    "geminiApi": "healthy",
    "database": "healthy",
    "cache": "healthy"
  }
}

🤖 AI集成架構

Prompt工程設計

核心Prompt模板

You are an English learning assistant. Analyze this sentence and return ONLY a valid JSON response.

**Input Sentence**: "{inputText}"

**Required JSON Structure:**
{
  "sentenceTranslation": "Traditional Chinese translation of the entire sentence",
  "hasGrammarErrors": true/false,
  "grammarCorrections": [
    {
      "original": "incorrect text",
      "corrected": "correct text",
      "type": "error type (tense/subject-verb/preposition/word-order)",
      "explanation": "brief explanation in Traditional Chinese"
    }
  ],
  "vocabularyAnalysis": {
    "word1": {
      "word": "the word",
      "translation": "Traditional Chinese translation",
      "definition": "English definition",
      "partOfSpeech": "noun/verb/adjective/etc",
      "pronunciation": "/phonetic/",
      "difficultyLevel": "A1/A2/B1/B2/C1/C2",
      "frequency": "high/medium/low",
      "synonyms": ["synonym1", "synonym2"],
      "example": "example sentence",
      "exampleTranslation": "Traditional Chinese example translation"
    }
  },
  "idioms": [
    {
      "idiom": "idiomatic expression",
      "translation": "Traditional Chinese meaning",
      "definition": "English explanation",
      "pronunciation": "/phonetic notation/",
      "difficultyLevel": "A1/A2/B1/B2/C1/C2",
      "frequency": "high/medium/low",
      "synonyms": ["synonym1", "synonym2"],
      "example": "usage example",
      "exampleTranslation": "Traditional Chinese example"
    }
  ]
}

**Analysis Guidelines:**
1. **Grammar Check**: Detect tense errors, subject-verb agreement, preposition usage, word order
2. **Vocabulary Analysis**: Include ALL significant words (exclude articles: a, an, the)
3. **CEFR Levels**: Assign accurate A1-C2 levels for each word
4. **Idioms**: Identify any idiomatic expressions or phrasal verbs
5. **Translations**: Use Traditional Chinese (Taiwan standard)

**IMPORTANT**: Return ONLY the JSON object, no additional text or explanation.

AI服務配置

Gemini API配置

模型配置:
  - 模型: gemini-1.5-flash
  - 溫度: 0.7 (平衡創造性和準確性)
  - 最大輸出: 2000 tokens
  - 超時: 30秒

重試策略:
  - 最大重試: 3次
  - 退避策略: 指數退避 (1s, 2s, 4s)
  - 重試條件: 網路錯誤、超時、5xx錯誤
  - 熔斷條件: 連續失敗 > 5次

降級策略:
  - 備用回應: 基礎翻譯和詞性分析
  - 快取回退: 相似句子的歷史分析結果
  - 服務狀態: 實時監控和告警

🔧 數據模型設計

請求模型

SentenceAnalysisRequest

public class SentenceAnalysisRequest
{
    [Required]
    [StringLength(300, MinimumLength = 1)]
    public string InputText { get; set; } = string.Empty;

    public string AnalysisMode { get; set; } = "full";

    public AnalysisOptions? Options { get; set; }
}

public class AnalysisOptions
{
    public bool IncludeGrammarCheck { get; set; } = true;
    public bool IncludeVocabularyAnalysis { get; set; } = true;
    public bool IncludeTranslation { get; set; } = true;
    public bool IncludeIdiomDetection { get; set; } = true;
    public bool IncludeExamples { get; set; } = true;
}

回應模型

核心資料模型

public class SentenceAnalysisResponse
{
    public bool Success { get; set; } = true;
    public double ProcessingTime { get; set; }
    public SentenceAnalysisData? Data { get; set; }
    public string? Message { get; set; }
}

public class SentenceAnalysisData
{
    public string AnalysisId { get; set; } = Guid.NewGuid().ToString();
    public string OriginalText { get; set; } = string.Empty;
    public GrammarCorrectionDto? GrammarCorrection { get; set; }
    public string SentenceMeaning { get; set; } = string.Empty;
    public Dictionary<string, VocabularyAnalysisDto> VocabularyAnalysis { get; set; } = new();
    public List<IdiomDto> Idioms { get; set; } = new();
    public AnalysisMetadata Metadata { get; set; } = new();
}

詳細模型定義

public class VocabularyAnalysisDto
{
    public string Word { get; set; } = string.Empty;
    public string Translation { get; set; } = string.Empty;
    public string Definition { get; set; } = string.Empty;
    public string PartOfSpeech { get; set; } = string.Empty;
    public string Pronunciation { get; set; } = string.Empty;
    public string DifficultyLevel { get; set; } = string.Empty;
    public string Frequency { get; set; } = string.Empty;
    public List<string> Synonyms { get; set; } = new();
    public string? Example { get; set; }
    public string? ExampleTranslation { get; set; }
}

public class IdiomDto
{
    public string Idiom { get; set; } = string.Empty;
    public string Translation { get; set; } = string.Empty;
    public string Definition { get; set; } = string.Empty;
    public string Pronunciation { get; set; } = string.Empty;
    public string DifficultyLevel { get; set; } = string.Empty;
    public string Frequency { get; set; } = string.Empty;
    public List<string> Synonyms { get; set; } = new();
    public string? Example { get; set; }
    public string? ExampleTranslation { get; set; }
}

public class GrammarCorrectionDto
{
    public bool HasErrors { get; set; }
    public string CorrectedText { get; set; } = string.Empty;
    public List<GrammarErrorDto> Corrections { get; set; } = new();
}

public class GrammarErrorDto
{
    public ErrorPosition Position { get; set; } = new();
    public string Error { get; set; } = string.Empty;
    public string Correction { get; set; } = string.Empty;
    public string Type { get; set; } = string.Empty;
    public string Explanation { get; set; } = string.Empty;
    public string Severity { get; set; } = "medium";
}

🔧 服務層架構

核心服務設計

IGeminiService介面

public interface IGeminiService
{
    Task<SentenceAnalysisData> AnalyzeSentenceAsync(string inputText, AnalysisOptions options);
    Task<bool> HealthCheckAsync();
    Task<string> GetModelVersionAsync();
}

服務實現重點

public class GeminiService : IGeminiService
{
    private readonly HttpClient _httpClient;
    private readonly IOptions<GeminiOptions> _options;
    private readonly ILogger<GeminiService> _logger;

    // ✅ 強型別配置注入
    public GeminiService(HttpClient httpClient, IOptions<GeminiOptions> options, ILogger<GeminiService> logger)
    {
        _httpClient = httpClient;
        _options = options;
        _logger = logger;

        ConfigureHttpClient();
    }

    // ✅ 結構化錯誤處理
    public async Task<SentenceAnalysisData> AnalyzeSentenceAsync(string inputText, AnalysisOptions options)
    {
        try
        {
            var prompt = BuildPrompt(inputText, options);
            var aiResponse = await CallGeminiAPIWithRetry(prompt);
            return ParseResponse(inputText, aiResponse);
        }
        catch (HttpRequestException ex)
        {
            throw new AIServiceException("Gemini", "Network error", ex);
        }
        catch (JsonException ex)
        {
            throw new AIServiceException("Gemini", "Invalid response format", ex);
        }
    }
}

配置管理架構

強型別配置

public class GeminiOptions
{
    public const string SectionName = "Gemini";

    [Required]
    public string ApiKey { get; set; } = string.Empty;

    [Range(1, 120)]
    public int TimeoutSeconds { get; set; } = 30;

    [Range(1, 10)]
    public int MaxRetries { get; set; } = 3;

    public string Model { get; set; } = "gemini-1.5-flash";
    public double Temperature { get; set; } = 0.7;
    public int MaxOutputTokens { get; set; } = 2000;
}

// 配置驗證器
public class GeminiOptionsValidator : IValidateOptions<GeminiOptions>
{
    public ValidateOptionsResult Validate(string name, GeminiOptions options)
    {
        var failures = new List<string>();

        if (string.IsNullOrWhiteSpace(options.ApiKey))
            failures.Add("Gemini API key is required");

        if (!IsValidApiKey(options.ApiKey))
            failures.Add("Invalid Gemini API key format");

        return failures.Any()
            ? ValidateOptionsResult.Fail(failures)
            : ValidateOptionsResult.Success;
    }
}

🛡️ 錯誤處理與穩定性

異常層次結構

public abstract class DramaLingException : Exception
{
    public string ErrorCode { get; }
    public Dictionary<string, object> Context { get; }

    protected DramaLingException(string errorCode, string message) : base(message)
    {
        ErrorCode = errorCode;
        Context = new Dictionary<string, object>();
    }
}

public class AIServiceException : DramaLingException
{
    public AIServiceException(string provider, string details)
        : base("AI_SERVICE_ERROR", $"AI service '{provider}' failed: {details}")
    {
        Context["Provider"] = provider;
        Context["Details"] = details;
    }
}

public class ValidationException : DramaLingException
{
    public ValidationException(string field, string message)
        : base("VALIDATION_ERROR", $"Validation failed for {field}: {message}")
    {
        Context["Field"] = field;
    }
}

錯誤回應標準

{
  "success": false,
  "error": {
    "code": "AI_SERVICE_ERROR",
    "message": "AI服務暫時不可用",
    "details": {
      "provider": "gemini",
      "originalError": "Network timeout"
    },
    "suggestions": [
      "請稍後重試",
      "如果問題持續,請聯繫客服"
    ]
  },
  "timestamp": "2025-01-25T10:30:00Z",
  "requestId": "uuid-string"
}

重試與熔斷機制

// 使用Polly實現重試策略
services.AddHttpClient<IGeminiService, GeminiService>()
    .AddPolicyHandler(GetRetryPolicy())
    .AddPolicyHandler(GetCircuitBreakerPolicy());

private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .WaitAndRetryAsync(
            retryCount: 3,
            sleepDurationProvider: retryAttempt =>
                TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
            onRetry: (outcome, timespan, retryCount, context) =>
            {
                logger.LogWarning("Retry {RetryCount} after {Delay}ms",
                    retryCount, timespan.TotalMilliseconds);
            });
}

📊 性能優化設計

快取策略

多層快取架構:
  L1: 應用程序記憶體快取 (5分鐘)
  L2: Redis分散式快取 (1小時)
  L3: 資料庫持久快取 (24小時)

快取鍵設計:
  - 格式: "analysis:{hash(inputText)}"
  - 過期: 基於內容複雜度動態調整
  - 清理: 背景服務定期清理過期快取

快取命中率目標: > 70%

資料庫優化

// 查詢優化範例
public async Task<AnalysisCache> GetCachedAnalysisAsync(string inputText)
{
    var textHash = ComputeHash(inputText);

    return await _context.AnalysisCache
        .AsNoTracking()  // 只讀查詢優化
        .Where(c => c.InputTextHash == textHash && c.ExpiresAt > DateTime.UtcNow)
        .Select(c => new AnalysisCache  // 投影查詢,只選需要的欄位
        {
            Id = c.Id,
            CachedData = c.CachedData,
            CreatedAt = c.CreatedAt
        })
        .FirstOrDefaultAsync();
}

🔒 安全架構設計

API安全

認證機制:
  - JWT Bearer Token認證
  - Token過期時間: 24小時
  - 刷新機制: Refresh Token

授權控制:
  - 角色基礎存取控制 (RBAC)
  - 資源級別權限
  - API速率限制

輸入驗證:
  - 參數類型檢查
  - 字符長度限制
  - XSS防護過濾
  - SQL注入防護

資料安全

傳輸安全:
  - TLS 1.3強制加密
  - HSTS標頭
  - 安全標頭 (CSP, X-Frame-Options)

存儲安全:
  - 敏感資料加密
  - API金鑰安全管理
  - 個人資料匿名化
  - 定期安全掃描

🧪 測試策略

測試金字塔

單元測試 (70%):
  - 服務邏輯測試
  - 配置驗證測試
  - 錯誤處理測試
  - Mock外部依賴

整合測試 (20%):
  - API端點測試
  - 資料庫整合測試
  - 快取系統測試
  - 健康檢查測試

E2E測試 (10%):
  - 完整分析流程測試
  - 真實AI API測試
  - 性能基準測試
  - 安全滲透測試

測試案例設計

[TestFixture]
public class AIAnalysisServiceTests
{
    [Test]
    public async Task AnalyzeAsync_WithValidInput_ReturnsAnalysisResult()
    {
        // Arrange
        var request = new AnalysisRequest { InputText = "She just joined the team." };

        // Act
        var result = await _service.AnalyzeAsync(request);

        // Assert
        Assert.That(result.VocabularyAnalysis.Count, Is.GreaterThan(0));
        Assert.That(result.SentenceMeaning, Is.Not.Empty);
    }

    [Test]
    public async Task AnalyzeAsync_WhenAIServiceFails_ThrowsAIServiceException()
    {
        // 測試AI服務故障時的錯誤處理
    }
}

📈 監控與可觀測性

日誌標準

// 結構化日誌擴展
public static class LoggerExtensions
{
    public static void LogAIRequest(this ILogger logger, string requestId,
        string inputText, string provider, double processingTime)
    {
        logger.LogInformation("AI Request: {RequestId} Provider: {Provider} " +
            "Length: {Length} Time: {Time}ms",
            requestId, provider, inputText.Length, processingTime);
    }
}

健康檢查

public class AIServiceHealthCheck : IHealthCheck
{
    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        var checks = new Dictionary<string, bool>
        {
            ["gemini_api"] = await CheckGeminiHealthAsync(),
            ["database"] = await CheckDatabaseHealthAsync(),
            ["cache"] = await CheckCacheHealthAsync()
        };

        var failedChecks = checks.Where(c => !c.Value).Select(c => c.Key).ToList();

        return failedChecks.Any()
            ? HealthCheckResult.Unhealthy($"Failed: {string.Join(", ", failedChecks)}")
            : HealthCheckResult.Healthy("All systems operational");
    }
}

性能指標

關鍵指標:
  - API回應時間分佈 (P50, P95, P99)
  - AI API調用成功率
  - 快取命中率
  - 記憶體和CPU使用率
  - 錯誤率和異常分佈

告警閾值:
  - 回應時間P95 > 5秒
  - 錯誤率 > 5%
  - AI API失敗率 > 10%
  - 記憶體使用 > 80%

🚀 部署與配置

環境配置

Development:
  - Database: SQLite
  - Cache: In-Memory
  - AI Provider: Gemini (測試Key)
  - Logging: Debug Level

Production:
  - Database: PostgreSQL (HA)
  - Cache: Redis Cluster
  - AI Provider: Gemini (生產Key)
  - Logging: Information Level
  - Monitoring: Application Insights

Docker配置

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 5008

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["DramaLing.Api.csproj", "."]
RUN dotnet restore

COPY . .
RUN dotnet publish -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:5008/health || exit 1

ENTRYPOINT ["dotnet", "DramaLing.Api.dll"]

📋 開發指導

程式碼規範

命名規範:
  - 類別: PascalCase (UserService)
  - 方法: PascalCase (AnalyzeAsync)
  - 參數: camelCase (inputText)
  - 常數: UPPER_CASE (MAX_LENGTH)

註釋規範:
  - 公開API: 完整XML註釋
  - 複雜邏輯: 行內註釋解釋
  - 業務邏輯: 意圖說明註釋
  - TODO: 使用標準格式

錯誤處理:
  - 自訂異常類型
  - 結構化錯誤回應
  - 日誌記錄完整
  - 用戶友善訊息

API設計原則

RESTful設計:
  - 使用標準HTTP動詞
  - 資源導向URL設計
  - 狀態碼語義明確
  - 一致的回應格式

版本管理:
  - URL版本控制 (/api/v1/)
  - 向下相容保證
  - 淘汰策略明確
  - 版本變更文檔

安全實踐:
  - 最小權限原則
  - 輸入驗證完整
  - 輸出編碼安全
  - 審計日誌記錄

🔄 變更管理

API版本演進

  • v1.0: 基礎分析功能 (2025-01-20)
  • v1.1: 移除userLevel簡化API (2025-01-25)
  • v2.0: 重構技術規格,標準化設計 (2025-01-25)

技術債務管理

已解決:
  - 硬編碼配置移除
  - 強型別配置實施
  - API規格標準化

待解決:
  - 重試機制實施
  - 健康檢查完善
  - 監控指標實施
  - 性能優化

文件版本: v2.0 技術負責人: DramaLing後端技術團隊 最後更新: 2025-01-25 下次審查: 2025-02-25

關聯文件:

  • 《AI句子分析功能產品需求規格》- 業務需求和用戶故事
  • 《系統整合與部署規格》- 整合和部署細節
  • 《AI驅動產品後端技術架構指南》- 架構設計指導原則