815 lines
21 KiB
Markdown
815 lines
21 KiB
Markdown
# AI分析API技術實現規格
|
||
|
||
## 📋 **文件資訊**
|
||
|
||
- **文件名稱**: AI分析API技術實現規格
|
||
- **版本**: v2.0
|
||
- **建立日期**: 2025-01-25
|
||
- **最後更新**: 2025-01-25
|
||
- **負責團隊**: DramaLing後端技術團隊
|
||
- **對應產品需求**: 《AI句子分析功能產品需求規格》
|
||
|
||
---
|
||
|
||
## 🛠 **技術架構概述**
|
||
|
||
### **系統架構設計**
|
||
```yaml
|
||
分層架構:
|
||
- 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**
|
||
**功能**: 智能英文句子分析
|
||
|
||
**請求格式**:
|
||
```json
|
||
{
|
||
"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
|
||
}
|
||
}
|
||
```
|
||
|
||
**回應格式**:
|
||
```json
|
||
{
|
||
"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**
|
||
**功能**: 服務健康檢查
|
||
|
||
**回應格式**:
|
||
```json
|
||
{
|
||
"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模板**
|
||
```text
|
||
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配置**
|
||
```yaml
|
||
模型配置:
|
||
- 模型: gemini-1.5-flash
|
||
- 溫度: 0.7 (平衡創造性和準確性)
|
||
- 最大輸出: 2000 tokens
|
||
- 超時: 30秒
|
||
|
||
重試策略:
|
||
- 最大重試: 3次
|
||
- 退避策略: 指數退避 (1s, 2s, 4s)
|
||
- 重試條件: 網路錯誤、超時、5xx錯誤
|
||
- 熔斷條件: 連續失敗 > 5次
|
||
|
||
降級策略:
|
||
- 備用回應: 基礎翻譯和詞性分析
|
||
- 快取回退: 相似句子的歷史分析結果
|
||
- 服務狀態: 實時監控和告警
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 **數據模型設計**
|
||
|
||
### **請求模型**
|
||
|
||
#### **SentenceAnalysisRequest**
|
||
```csharp
|
||
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;
|
||
}
|
||
```
|
||
|
||
### **回應模型**
|
||
|
||
#### **核心資料模型**
|
||
```csharp
|
||
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();
|
||
}
|
||
```
|
||
|
||
#### **詳細模型定義**
|
||
```csharp
|
||
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介面**
|
||
```csharp
|
||
public interface IGeminiService
|
||
{
|
||
Task<SentenceAnalysisData> AnalyzeSentenceAsync(string inputText, AnalysisOptions options);
|
||
Task<bool> HealthCheckAsync();
|
||
Task<string> GetModelVersionAsync();
|
||
}
|
||
```
|
||
|
||
#### **服務實現重點**
|
||
```csharp
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### **配置管理架構**
|
||
|
||
#### **強型別配置**
|
||
```csharp
|
||
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;
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🛡️ **錯誤處理與穩定性**
|
||
|
||
### **異常層次結構**
|
||
```csharp
|
||
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;
|
||
}
|
||
}
|
||
```
|
||
|
||
### **錯誤回應標準**
|
||
```json
|
||
{
|
||
"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"
|
||
}
|
||
```
|
||
|
||
### **重試與熔斷機制**
|
||
```csharp
|
||
// 使用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);
|
||
});
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 **性能優化設計**
|
||
|
||
### **快取策略**
|
||
```yaml
|
||
多層快取架構:
|
||
L1: 應用程序記憶體快取 (5分鐘)
|
||
L2: Redis分散式快取 (1小時)
|
||
L3: 資料庫持久快取 (24小時)
|
||
|
||
快取鍵設計:
|
||
- 格式: "analysis:{hash(inputText)}"
|
||
- 過期: 基於內容複雜度動態調整
|
||
- 清理: 背景服務定期清理過期快取
|
||
|
||
快取命中率目標: > 70%
|
||
```
|
||
|
||
### **資料庫優化**
|
||
```csharp
|
||
// 查詢優化範例
|
||
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安全**
|
||
```yaml
|
||
認證機制:
|
||
- JWT Bearer Token認證
|
||
- Token過期時間: 24小時
|
||
- 刷新機制: Refresh Token
|
||
|
||
授權控制:
|
||
- 角色基礎存取控制 (RBAC)
|
||
- 資源級別權限
|
||
- API速率限制
|
||
|
||
輸入驗證:
|
||
- 參數類型檢查
|
||
- 字符長度限制
|
||
- XSS防護過濾
|
||
- SQL注入防護
|
||
```
|
||
|
||
### **資料安全**
|
||
```yaml
|
||
傳輸安全:
|
||
- TLS 1.3強制加密
|
||
- HSTS標頭
|
||
- 安全標頭 (CSP, X-Frame-Options)
|
||
|
||
存儲安全:
|
||
- 敏感資料加密
|
||
- API金鑰安全管理
|
||
- 個人資料匿名化
|
||
- 定期安全掃描
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 **測試策略**
|
||
|
||
### **測試金字塔**
|
||
```yaml
|
||
單元測試 (70%):
|
||
- 服務邏輯測試
|
||
- 配置驗證測試
|
||
- 錯誤處理測試
|
||
- Mock外部依賴
|
||
|
||
整合測試 (20%):
|
||
- API端點測試
|
||
- 資料庫整合測試
|
||
- 快取系統測試
|
||
- 健康檢查測試
|
||
|
||
E2E測試 (10%):
|
||
- 完整分析流程測試
|
||
- 真實AI API測試
|
||
- 性能基準測試
|
||
- 安全滲透測試
|
||
```
|
||
|
||
### **測試案例設計**
|
||
```csharp
|
||
[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服務故障時的錯誤處理
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 **監控與可觀測性**
|
||
|
||
### **日誌標準**
|
||
```csharp
|
||
// 結構化日誌擴展
|
||
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);
|
||
}
|
||
}
|
||
```
|
||
|
||
### **健康檢查**
|
||
```csharp
|
||
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");
|
||
}
|
||
}
|
||
```
|
||
|
||
### **性能指標**
|
||
```yaml
|
||
關鍵指標:
|
||
- API回應時間分佈 (P50, P95, P99)
|
||
- AI API調用成功率
|
||
- 快取命中率
|
||
- 記憶體和CPU使用率
|
||
- 錯誤率和異常分佈
|
||
|
||
告警閾值:
|
||
- 回應時間P95 > 5秒
|
||
- 錯誤率 > 5%
|
||
- AI API失敗率 > 10%
|
||
- 記憶體使用 > 80%
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 **部署與配置**
|
||
|
||
### **環境配置**
|
||
```yaml
|
||
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配置**
|
||
```dockerfile
|
||
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"]
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 **開發指導**
|
||
|
||
### **程式碼規範**
|
||
```yaml
|
||
命名規範:
|
||
- 類別: PascalCase (UserService)
|
||
- 方法: PascalCase (AnalyzeAsync)
|
||
- 參數: camelCase (inputText)
|
||
- 常數: UPPER_CASE (MAX_LENGTH)
|
||
|
||
註釋規範:
|
||
- 公開API: 完整XML註釋
|
||
- 複雜邏輯: 行內註釋解釋
|
||
- 業務邏輯: 意圖說明註釋
|
||
- TODO: 使用標準格式
|
||
|
||
錯誤處理:
|
||
- 自訂異常類型
|
||
- 結構化錯誤回應
|
||
- 日誌記錄完整
|
||
- 用戶友善訊息
|
||
```
|
||
|
||
### **API設計原則**
|
||
```yaml
|
||
RESTful設計:
|
||
- 使用標準HTTP動詞
|
||
- 資源導向URL設計
|
||
- 狀態碼語義明確
|
||
- 一致的回應格式
|
||
|
||
版本管理:
|
||
- URL版本控制 (/api/v1/)
|
||
- 向下相容保證
|
||
- 淘汰策略明確
|
||
- 版本變更文檔
|
||
|
||
安全實踐:
|
||
- 最小權限原則
|
||
- 輸入驗證完整
|
||
- 輸出編碼安全
|
||
- 審計日誌記錄
|
||
```
|
||
|
||
---
|
||
|
||
## 🔄 **變更管理**
|
||
|
||
### **API版本演進**
|
||
- **v1.0**: 基礎分析功能 (2025-01-20)
|
||
- **v1.1**: 移除userLevel,簡化API (2025-01-25)
|
||
- **v2.0**: 重構技術規格,標準化設計 (2025-01-25)
|
||
|
||
### **技術債務管理**
|
||
```yaml
|
||
已解決:
|
||
- 硬編碼配置移除
|
||
- 強型別配置實施
|
||
- API規格標準化
|
||
|
||
待解決:
|
||
- 重試機制實施
|
||
- 健康檢查完善
|
||
- 監控指標實施
|
||
- 性能優化
|
||
```
|
||
|
||
---
|
||
|
||
**文件版本**: v2.0
|
||
**技術負責人**: DramaLing後端技術團隊
|
||
**最後更新**: 2025-01-25
|
||
**下次審查**: 2025-02-25
|
||
|
||
**關聯文件**:
|
||
- 《AI句子分析功能產品需求規格》- 業務需求和用戶故事
|
||
- 《系統整合與部署規格》- 整合和部署細節
|
||
- 《AI驅動產品後端技術架構指南》- 架構設計指導原則 |