docs: 新增智能填空題系統設計規格書
建立完整的系統重構規格,解決當前填空題挖空邏輯的限制: ## 核心設計 - 將挖空邏輯從前端移至後端統一處理 - 新增 FilledQuestionText 欄位儲存挖空後的題目 - 建立程式碼挖空 + AI輔助的雙重回退機制 ## 解決問題 - 支援詞彙變形挖空 (eat/ate, go/went 等) - 處理複數、比較級、過去分詞等語法變化 - 提供AI輔助確保挖空準確性 ## 系統架構 - 後端: BlankGenerationService + API端點強化 - 前端: 簡化SentenceFillTest組件邏輯 - 資料庫: Migration添加新欄位 ## 實施計劃 分4個階段: 資料庫結構 → 後端服務 → 前端優化 → 測試優化 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5a9e7f727c
commit
491f184c4e
|
|
@ -115,7 +115,6 @@ export const SentenceFillTest: React.FC<SentenceFillTestProps> = ({
|
||||||
{exampleImage && (
|
{exampleImage && (
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<div className="bg-gray-50 rounded-lg p-4">
|
<div className="bg-gray-50 rounded-lg p-4">
|
||||||
<h3 className="font-semibold text-gray-900 mb-2 text-left">圖片提示</h3>
|
|
||||||
<img
|
<img
|
||||||
src={exampleImage}
|
src={exampleImage}
|
||||||
alt="Example illustration"
|
alt="Example illustration"
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,6 @@ export const SentenceListeningTest: React.FC<SentenceListeningTestProps> = ({
|
||||||
<div className="text-center mb-8">
|
<div className="text-center mb-8">
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<AudioPlayer text={example} />
|
<AudioPlayer text={example} />
|
||||||
<p className="text-sm text-gray-500 mt-2">
|
|
||||||
點擊播放聽例句
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -78,7 +75,6 @@ export const SentenceListeningTest: React.FC<SentenceListeningTestProps> = ({
|
||||||
{exampleImage && (
|
{exampleImage && (
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<div className="bg-gray-50 rounded-lg p-4">
|
<div className="bg-gray-50 rounded-lg p-4">
|
||||||
<h3 className="font-semibold text-gray-900 mb-2 text-left">圖片提示</h3>
|
|
||||||
<img
|
<img
|
||||||
src={exampleImage}
|
src={exampleImage}
|
||||||
alt="Example illustration"
|
alt="Example illustration"
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,6 @@ export const SentenceReorderTest: React.FC<SentenceReorderTestProps> = ({
|
||||||
{exampleImage && (
|
{exampleImage && (
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<div className="bg-gray-50 rounded-lg p-4">
|
<div className="bg-gray-50 rounded-lg p-4">
|
||||||
<h3 className="font-semibold text-gray-900 mb-2 text-left">圖片提示</h3>
|
|
||||||
<img
|
<img
|
||||||
src={exampleImage}
|
src={exampleImage}
|
||||||
alt="Example illustration"
|
alt="Example illustration"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,187 @@
|
||||||
|
# 智能填空題系統設計規格書
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
將填空題的挖空邏輯從前端移至後端,建立智能的例句處理系統,支援詞彙變形識別和AI輔助挖空。
|
||||||
|
|
||||||
|
## 問題分析
|
||||||
|
|
||||||
|
### 當前問題
|
||||||
|
- 前端使用簡單正則 `\b${word}\b` 進行挖空
|
||||||
|
- 無法處理詞彙變形:`eat` vs `ate`、`go` vs `went`
|
||||||
|
- 挖空失敗時無替代方案,導致題目無法正常顯示
|
||||||
|
|
||||||
|
### 影響範圍
|
||||||
|
- 動詞變形:eat/ate、go/went、run/ran
|
||||||
|
- 名詞複數:cat/cats、child/children
|
||||||
|
- 形容詞比較級:good/better、bad/worse
|
||||||
|
- 過去分詞:break/broken、speak/spoken
|
||||||
|
|
||||||
|
## 系統架構設計
|
||||||
|
|
||||||
|
### 資料庫結構調整
|
||||||
|
|
||||||
|
#### Flashcard 實體新增欄位
|
||||||
|
```csharp
|
||||||
|
[MaxLength(1000)]
|
||||||
|
public string? FilledQuestionText { get; set; } // 挖空後的題目文字
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 範例資料
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"word": "ate",
|
||||||
|
"example": "She ate an apple yesterday.",
|
||||||
|
"filledQuestionText": "She ____ an apple yesterday."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 後端服務架構
|
||||||
|
|
||||||
|
#### 1. BlankGenerationService 服務
|
||||||
|
```csharp
|
||||||
|
public interface IBlankGenerationService
|
||||||
|
{
|
||||||
|
Task<string?> GenerateBlankQuestionAsync(string word, string example);
|
||||||
|
string? TryProgrammaticBlank(string word, string example);
|
||||||
|
Task<string?> GenerateAIBlankAsync(string word, string example);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 智能挖空處理流程
|
||||||
|
|
||||||
|
##### Step 1: 程式碼挖空 (快速處理)
|
||||||
|
```csharp
|
||||||
|
// 1. 完全匹配
|
||||||
|
var regex1 = new Regex($@"\b{Regex.Escape(word)}\b", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
// 2. 常見變形規則
|
||||||
|
var variations = GetCommonVariations(word);
|
||||||
|
foreach(var variation in variations)
|
||||||
|
{
|
||||||
|
var regex2 = new Regex($@"\b{Regex.Escape(variation)}\b", RegexOptions.IgnoreCase);
|
||||||
|
// 嘗試替換
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Step 2: AI 輔助挖空 (處理複雜變形)
|
||||||
|
```csharp
|
||||||
|
var prompt = $@"
|
||||||
|
請將以下例句中與詞彙「{word}」相關的詞挖空,用____替代:
|
||||||
|
|
||||||
|
詞彙: {word}
|
||||||
|
例句: {example}
|
||||||
|
|
||||||
|
規則:
|
||||||
|
1. 只挖空與目標詞彙相關的詞(包含變形、時態、複數等)
|
||||||
|
2. 用____替代被挖空的詞
|
||||||
|
3. 保持句子其他部分不變
|
||||||
|
4. 直接返回挖空後的句子,不要額外說明
|
||||||
|
|
||||||
|
挖空後的句子:";
|
||||||
|
|
||||||
|
await _geminiService.GenerateTextAsync(prompt);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. API 端點調整
|
||||||
|
|
||||||
|
##### GET /api/flashcards/due 強化邏輯
|
||||||
|
```csharp
|
||||||
|
foreach(var flashcard in dueCards)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(flashcard.FilledQuestionText))
|
||||||
|
{
|
||||||
|
var blankQuestion = await _blankGenerationService.GenerateBlankQuestionAsync(
|
||||||
|
flashcard.Word, flashcard.Example);
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(blankQuestion))
|
||||||
|
{
|
||||||
|
flashcard.FilledQuestionText = blankQuestion;
|
||||||
|
// 更新資料庫
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 新增重新生成端點
|
||||||
|
```csharp
|
||||||
|
[HttpPost("{id}/regenerate-blank")]
|
||||||
|
public async Task<ActionResult> RegenerateBlankQuestion(Guid id)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端架構簡化
|
||||||
|
|
||||||
|
#### SentenceFillTest 組件調整
|
||||||
|
```typescript
|
||||||
|
// 移除複雜的 renderSentenceWithInput() 邏輯
|
||||||
|
// 改為簡單的模板渲染
|
||||||
|
|
||||||
|
interface SentenceFillTestProps {
|
||||||
|
word: string;
|
||||||
|
definition: string;
|
||||||
|
example: string; // 原始例句
|
||||||
|
filledQuestionText: string; // 挖空後的題目
|
||||||
|
// ... 其他屬性
|
||||||
|
}
|
||||||
|
|
||||||
|
// 簡化的渲染邏輯
|
||||||
|
const renderFilledSentence = () => {
|
||||||
|
return filledQuestionText.replace('____',
|
||||||
|
`<input value="${fillAnswer}" ... />`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 實施計劃
|
||||||
|
|
||||||
|
### Phase 1: 資料庫結構
|
||||||
|
1. 創建 Migration 添加 `FilledQuestionText` 欄位
|
||||||
|
2. 更新 Flashcard 實體模型
|
||||||
|
|
||||||
|
### Phase 2: 後端服務開發
|
||||||
|
1. 實作 `BlankGenerationService`
|
||||||
|
2. 建立常見詞彙變形對應表
|
||||||
|
3. 整合 AI 挖空功能
|
||||||
|
4. 修改 FlashcardsController
|
||||||
|
|
||||||
|
### Phase 3: 前端優化
|
||||||
|
1. 簡化 SentenceFillTest 組件
|
||||||
|
2. 更新 Props 介面
|
||||||
|
3. 測試新的渲染邏輯
|
||||||
|
|
||||||
|
### Phase 4: 測試與優化
|
||||||
|
1. 測試各種詞彙變形情況
|
||||||
|
2. 驗證 AI 挖空品質
|
||||||
|
3. 效能優化和錯誤處理
|
||||||
|
|
||||||
|
## 預期效果
|
||||||
|
|
||||||
|
### 功能提升
|
||||||
|
- ✅ 支援所有詞彙變形挖空
|
||||||
|
- ✅ AI 輔助處理複雜情況
|
||||||
|
- ✅ 一次生成,多次使用
|
||||||
|
- ✅ 統一的挖空品質
|
||||||
|
|
||||||
|
### 技術優勢
|
||||||
|
- 🚀 前端邏輯簡化
|
||||||
|
- 🎯 後端統一處理
|
||||||
|
- 💾 結果快取提升效能
|
||||||
|
- 🤖 AI 確保準確性
|
||||||
|
|
||||||
|
### 維護性
|
||||||
|
- 📦 挖空邏輯集中管理
|
||||||
|
- 🔧 易於調整和優化
|
||||||
|
- 📊 可監控挖空成功率
|
||||||
|
- 🐛 錯誤處理更完善
|
||||||
|
|
||||||
|
## 風險評估
|
||||||
|
|
||||||
|
### 技術風險
|
||||||
|
- AI 調用可能失敗 → 提供降級策略
|
||||||
|
- 資料庫遷移 → 確保現有資料相容
|
||||||
|
- 效能影響 → 批次處理優化
|
||||||
|
|
||||||
|
### 緩解措施
|
||||||
|
- 多層回退機制 (程式碼 → AI → 手動)
|
||||||
|
- 非同步處理避免阻塞
|
||||||
|
- 詳細日誌記錄便於除錯
|
||||||
Loading…
Reference in New Issue