dramaling-vocab-learning/docs/03_development/api/gemini-integration.md

302 lines
6.7 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.

# Gemini AI API 整合文檔
## 概述
本文檔說明如何整合 Google Gemini API 來實現 AI 詞卡生成功能。
## API 設置
### 1. 取得 API Key
1. 訪問 [Google AI Studio](https://makersuite.google.com/app/apikey)
2. 點擊 "Create API Key"
3. 選擇專案或建立新專案
4. 複製生成的 API Key
### 2. 安裝 SDK
```bash
npm install @google/generative-ai
```
### 3. 環境變數配置
```env
GEMINI_API_KEY=your_api_key_here
```
## API 實作
### 基礎設置
```typescript
// lib/gemini.ts
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
export const geminiModel = genAI.getGenerativeModel({
model: "gemini-pro"
});
```
### 詞卡生成功能
```typescript
// app/api/ai/generate-flashcard/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { geminiModel } from '@/lib/gemini';
export async function POST(request: NextRequest) {
try {
const { text, type } = await request.json();
const prompt = createPrompt(text, type);
const result = await geminiModel.generateContent(prompt);
const response = await result.response;
const generatedText = response.text();
const flashcards = parseFlashcards(generatedText);
return NextResponse.json({ flashcards });
} catch (error) {
console.error('Gemini API error:', error);
return NextResponse.json(
{ error: 'Failed to generate flashcards' },
{ status: 500 }
);
}
}
```
## Prompt 工程
### 基礎 Prompt 模板
```typescript
const FLASHCARD_PROMPT = `
你是一個專業的英語教學助手,專門幫助台灣學生透過美劇學習英文。
請根據以下內容生成詞卡:
輸入文本:{input_text}
請生成5個最重要的詞彙學習卡片每個卡片包含
1. 英文單字或片語
2. 中文翻譯
3. 詞性和用法說明
4. 原文例句(從輸入文本中提取)
5. 額外例句(創造一個相似情境的例句)
6. 使用情境說明(什麼場合使用)
7. 難度等級1-51最簡單
請以 JSON 格式回覆,格式如下:
{
"flashcards": [
{
"word": "英文單字或片語",
"translation": "中文翻譯",
"partOfSpeech": "詞性",
"usage": "用法說明",
"originalExample": "原文例句",
"additionalExample": "額外例句",
"context": "使用情境",
"difficulty": 難度數字
}
]
}
`;
```
### 不同類型的 Prompt
#### 1. 美劇對話分析
```typescript
const DRAMA_DIALOGUE_PROMPT = `
分析以下美劇對話,提取日常對話中的重要表達:
- 重點關注俚語、慣用語、口語表達
- 解釋文化背景和使用場合
- 標註正式程度(非常口語/口語/中性/正式)
`;
```
#### 2. 主題學習
```typescript
const TOPIC_LEARNING_PROMPT = `
生成關於「{topic}」主題的詞彙卡片:
- 包含該主題最常用的詞彙
- 提供實用的搭配詞和片語
- 給出真實對話場景的例句
`;
```
#### 3. 語法重點
```typescript
const GRAMMAR_FOCUS_PROMPT = `
分析文本中的語法結構:
- 識別重要的語法模式
- 解釋語法規則和例外
- 提供類似結構的變化練習
`;
```
## 回應解析
### JSON 解析函數
```typescript
function parseFlashcards(responseText: string) {
try {
// 清理回應文本(移除可能的 markdown 標記)
const cleanedText = responseText
.replace(/```json\n?/g, '')
.replace(/```\n?/g, '')
.trim();
const parsed = JSON.parse(cleanedText);
return parsed.flashcards;
} catch (error) {
console.error('Parse error:', error);
// 備用解析邏輯
return extractFlashcardsManually(responseText);
}
}
```
### 錯誤處理與重試
```typescript
async function generateWithRetry(prompt: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const result = await geminiModel.generateContent(prompt);
return result;
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
```
## Rate Limiting 與配額管理
### 請求限制
```typescript
import { RateLimiter } from '@/lib/rate-limiter';
const limiter = new RateLimiter({
tokensPerInterval: 60, // Gemini Free: 60 QPM
interval: 'minute',
});
export async function checkRateLimit(userId: string) {
const isAllowed = await limiter.check(userId);
if (!isAllowed) {
throw new Error('Rate limit exceeded');
}
}
```
### 配額追蹤
```typescript
// 記錄用戶使用量
async function trackUsage(userId: string, tokensUsed: number) {
await supabase
.from('user_usage')
.upsert({
user_id: userId,
date: new Date().toISOString().split('T')[0],
gemini_tokens: tokensUsed,
});
}
```
## 最佳實踐
### 1. Prompt 優化
- 使用具體、清晰的指示
- 提供輸出格式範例
- 設定合適的 temperature (0.7-0.9)
### 2. 成本控制
- 限制每個請求的 token 數量
- 實施用戶配額系統
- 快取常見請求結果
### 3. 錯誤處理
- 實施重試機制
- 提供降級方案
- 記錄錯誤日誌
### 4. 安全考量
- 不在前端暴露 API Key
- 實施內容過濾
- 驗證用戶輸入
## 測試範例
### 單元測試
```typescript
describe('Gemini Integration', () => {
it('should generate flashcards from text', async () => {
const input = "I'm gonna grab a coffee, wanna come?";
const result = await generateFlashcards(input);
expect(result).toHaveLength(5);
expect(result[0]).toHaveProperty('word');
expect(result[0]).toHaveProperty('translation');
});
it('should handle rate limiting', async () => {
// 測試超過限制的請求
});
});
```
### 整合測試
```typescript
describe('API Endpoint', () => {
it('should return flashcards via API', async () => {
const response = await fetch('/api/ai/generate-flashcard', {
method: 'POST',
body: JSON.stringify({ text: 'test input' }),
});
expect(response.status).toBe(200);
const data = await response.json();
expect(data.flashcards).toBeDefined();
});
});
```
## 監控與日誌
### 關鍵指標
- API 回應時間
- 成功/失敗率
- Token 使用量
- 用戶滿意度
### 日誌記錄
```typescript
import { logger } from '@/lib/logger';
logger.info('Gemini API called', {
userId,
promptLength: prompt.length,
responseTime: Date.now() - startTime,
});
```
## 故障排除
### 常見問題
1. **API Key 無效**
- 確認環境變數設置正確
- 檢查 API Key 是否啟用
2. **Rate Limit 錯誤**
- 實施請求隊列
- 升級到付費方案
3. **回應解析失敗**
- 改進 prompt 明確性
- 實施備用解析邏輯
4. **生成品質不佳**
- 調整 temperature 參數
- 優化 prompt 內容
- 提供更多範例