dramaling-vocab-learning/智能填空題系統設計規格.md

4.6 KiB
Raw Blame History

智能填空題系統設計規格書

概述

將填空題的挖空邏輯從前端移至後端建立智能的例句處理系統支援詞彙變形識別和AI輔助挖空。

問題分析

當前問題

  • 前端使用簡單正則 \b${word}\b 進行挖空
  • 無法處理詞彙變形:eat vs atego vs went
  • 挖空失敗時無替代方案,導致題目無法正常顯示

影響範圍

  • 動詞變形eat/ate、go/went、run/ran
  • 名詞複數cat/cats、child/children
  • 形容詞比較級good/better、bad/worse
  • 過去分詞break/broken、speak/spoken

系統架構設計

資料庫結構調整

Flashcard 實體新增欄位

[MaxLength(1000)]
public string? FilledQuestionText { get; set; }  // 挖空後的題目文字

範例資料

{
  "word": "ate",
  "example": "She ate an apple yesterday.",
  "filledQuestionText": "She ____ an apple yesterday."
}

後端服務架構

1. BlankGenerationService 服務

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: 程式碼挖空 (快速處理)
// 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 輔助挖空 (處理複雜變形)
var prompt = $@"
請將以下例句中與詞彙「{word}」相關的詞挖空用____替代

詞彙: {word}
例句: {example}

規則:
1. 只挖空與目標詞彙相關的詞(包含變形、時態、複數等)
2. 用____替代被挖空的詞
3. 保持句子其他部分不變
4. 直接返回挖空後的句子,不要額外說明

挖空後的句子:";

await _geminiService.GenerateTextAsync(prompt);

3. API 端點調整

GET /api/flashcards/due 強化邏輯
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;
            // 更新資料庫
        }
    }
}
新增重新生成端點
[HttpPost("{id}/regenerate-blank")]
public async Task<ActionResult> RegenerateBlankQuestion(Guid id)

前端架構簡化

SentenceFillTest 組件調整

// 移除複雜的 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 → 手動)
  • 非同步處理避免阻塞
  • 詳細日誌記錄便於除錯