dramaling-app/docs/04_technical/api/dialogue-practice.md

15 KiB
Raw Blame History

對話練習 API

📋 概述

Drama Ling 的核心功能 - 情境對話練習系統包含場景對話、AI分析、回覆輔助等功能。

🎭 核心功能

對話系統特色

  • 情境化對話: 真實場景模擬(餐廳、機場、購物等)
  • AI智能回應: OpenAI GPT-4o-mini 驅動的自然對話
  • 即時分析: 語法、語義、流暢度多維度評分
  • 學習輔助: 智能提示和回覆建議
  • 進度追蹤: 對話目標和完成度監控

📌 API 端點

1. 開始對話練習

POST /api/v1/dialogues/start
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "scenario_id": "SC_Restaurant_01",
  "difficulty_override": "A2",
  "target_vocabulary": ["reservation", "menu", "order"],
  "practice_mode": "guided" // guided, free_form, challenge
}

回應範例

Response 201 Created
{
  "success": true,
  "data": {
    "dialogue_id": "DLG_20240907_001",
    "scenario_id": "SC_Restaurant_01",
    "session_token": "session_eyJhbGciOiJIUzI1NiIs...",
    "dialogue_config": {
      "max_turns": 12,
      "time_limit": 600, // seconds
      "difficulty_level": "A2",
      "practice_mode": "guided"
    },
    "scenario_context": {
      "setting": "高級義大利餐廳內部晚上8點",
      "location": "Milano Restaurant, 市中心",
      "your_role": "顧客",
      "ai_role": "餐廳服務員",
      "objective": "成功預約座位並完成點餐",
      "background_info": "這是一家需要預約的高檔餐廳,服務正式"
    },
    "initial_state": {
      "life_points_cost": 1,
      "remaining_life_points": 4,
      "objectives": [
        "確認預約",
        "選擇餐桌",
        "點餐主菜",
        "完成付款"
      ]
    },
    "ai_opening": {
      "message": "Good evening! Welcome to Milano Restaurant. Do you have a reservation with us tonight?",
      "audio_url": "https://cdn.dramaling.com/audio/dialogues/DLG_20240907_001_001.mp3",
      "audio_duration": 4.2,
      "emotion": "polite_welcoming",
      "formality_level": "formal",
      "suggestions": [
        "Yes, I have a reservation under Chen.",
        "No, but could we get a table for two?",
        "I'd like to check if you have any available tables."
      ]
    }
  },
  "message": "Dialogue session started successfully"
}

場景類型

  • SC_Restaurant_*: 餐廳相關場景
  • SC_Airport_*: 機場/旅行場景
  • SC_Shopping_*: 購物場景
  • SC_Business_*: 商務場景
  • SC_Medical_*: 醫療場景
  • SC_Education_*: 教育場景

2. 發送對話訊息

POST /api/v1/dialogues/{dialogue_id}/message
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "message": "Yes, I have a reservation under Chen for 8 PM for two people.",
  "message_type": "text",
  "audio_data": {
    "audio_url": "https://cdn.dramaling.com/user_audio/msg001.mp3",
    "duration": 3.5
  },
  "metadata": {
    "input_method": "voice", // voice, keyboard
    "confidence_level": 4, // 1-5, user's confidence
    "time_taken": 15.2 // seconds to compose
  }
}

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "turn_id": "TURN_002",
    "dialogue_status": "active",
    "ai_response": {
      "message": "Excellent! Mr. Chen, party of two at 8 PM. Your table is ready. Would you prefer a window seat or would you like to sit in our main dining area?",
      "audio_url": "https://cdn.dramaling.com/audio/dialogues/DLG_20240907_001_002.mp3",
      "audio_duration": 6.8,
      "emotion": "friendly_professional",
      "formality_level": "formal",
      "context_hints": {
        "next_expected": "table_preference",
        "vocabulary_focus": ["window seat", "dining area", "prefer"]
      }
    },
    "user_analysis": {
      "grammar_score": 90,
      "semantic_score": 95,
      "fluency_score": 85,
      "pronunciation_score": 88,
      "overall_score": 90,
      "detailed_feedback": {
        "strengths": [
          "Perfect use of formal language",
          "Appropriate information included",
          "Natural sentence structure"
        ],
        "improvements": [
          "Consider adding 'please' for extra politeness"
        ],
        "vocabulary_analysis": [
          {
            "word": "reservation",
            "usage": "perfect",
            "level": "A2",
            "context_appropriateness": 5
          }
        ]
      }
    },
    "dialogue_progress": {
      "turns_completed": 2,
      "estimated_turns_remaining": 6,
      "progress_percentage": 25,
      "objectives_status": {
        "confirmed_reservation": true,
        "selected_table": false,
        "ordered_food": false,
        "completed_payment": false
      },
      "current_phase": "table_selection"
    },
    "suggestions": [
      "I'd love a window seat if available.",
      "The main dining area sounds great.",
      "Could we see both options first?"
    ]
  }
}

3. 請求回覆輔助

POST /api/v1/dialogues/{dialogue_id}/assistance
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "assistance_type": "reply_guidance",
  "context": {
    "partner_message": "Would you prefer a window seat or would you like to sit in our main dining area?",
    "scenario_context": "choosing table at restaurant",
    "user_language_level": "A2",
    "stuck_reason": "vocabulary", // vocabulary, grammar, context
    "partial_response": "I would like..." // user's partial input
  }
}

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "assistance_id": "AST_20240907_001",
    "assistance_type": "reply_guidance",
    "guidance": {
      "intent_analysis": "對方在詢問你的座位偏好,這是餐廳服務的常見情況",
      "response_strategy": "表達你的偏好並保持禮貌",
      "key_phrases": [
        {
          "phrase": "I'd prefer...",
          "meaning": "我比較喜歡...",
          "usage": "表達偏好的禮貌方式"
        },
        {
          "phrase": "window seat",
          "meaning": "靠窗座位",
          "usage": "餐廳座位類型"
        }
      ],
      "sample_responses": [
        {
          "response": "I'd prefer a window seat, please.",
          "level": "A2",
          "politeness": "appropriate",
          "explanation": "簡單直接地表達偏好"
        },
        {
          "response": "A window seat would be lovely if you have one available.",
          "level": "B1",
          "politeness": "very_polite",
          "explanation": "更加禮貌和委婉的表達方式"
        }
      ]
    },
    "usage_cost": {
      "hints_used": 1,
      "remaining_hints": 4,
      "hint_type": "free" // free, premium
    }
  }
}

4. 中翻英翻譯輔助

POST /api/v1/dialogues/{dialogue_id}/translation
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "chinese_text": "我想要一個靠窗的座位",
  "context": {
    "scenario": "restaurant_dining",
    "formality_level": "formal",
    "target_level": "A2"
  }
}

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "translation_id": "TRANS_20240907_001",
    "translations": [
      {
        "english_text": "I'd like a window seat.",
        "level": "A2",
        "formality": "polite",
        "naturalness": 5,
        "explanation": "最直接和常用的表達方式"
      },
      {
        "english_text": "Could I have a window seat, please?",
        "level": "A2",
        "formality": "very_polite",
        "naturalness": 5,
        "explanation": "更加禮貌的請求方式"
      },
      {
        "english_text": "I would prefer a seat by the window.",
        "level": "B1",
        "formality": "formal",
        "naturalness": 4,
        "explanation": "較正式的表達方式"
      }
    ],
    "grammar_notes": [
      "使用 'I'd like' 比 'I want' 更禮貌",
      "'window seat' 是固定搭配,不需要冠詞"
    ],
    "usage_cost": {
      "translations_used": 1,
      "remaining_translations": 9
    }
  }
}

5. 獲取詳細分析

GET /api/v1/dialogues/{dialogue_id}/analysis
Authorization: Bearer <access_token>

查詢參數

  • turn_id: 特定對話輪次ID (可選)
  • analysis_type: summary | detailed | vocabulary (預設 summary)

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "dialogue_id": "DLG_20240907_001",
    "analysis_summary": {
      "overall_performance": {
        "grammar_score": 88,
        "semantic_score": 92,
        "fluency_score": 85,
        "pronunciation_score": 87,
        "total_score": 88,
        "completion_percentage": 100,
        "is_perfect_score": false
      },
      "interaction_quality": {
        "appropriateness": 95,
        "naturalness": 88,
        "engagement": 90,
        "cultural_sensitivity": 92
      }
    },
    "turn_by_turn_analysis": [
      {
        "turn_number": 1,
        "user_message": "Yes, I have a reservation under Chen for 8 PM for two people.",
        "analysis": {
          "scores": {
            "grammar": 90,
            "semantic": 95,
            "fluency": 85,
            "pronunciation": 88
          },
          "feedback": {
            "positive_aspects": [
              "Perfect use of formal register",
              "All necessary information included",
              "Natural sentence structure"
            ],
            "areas_for_improvement": [
              "Consider using 'please' for extra politeness"
            ],
            "grammar_analysis": {
              "errors": [],
              "complexity_level": "A2",
              "sentence_patterns": ["declarative_affirmative"]
            }
          },
          "vocabulary_usage": [
            {
              "word": "reservation",
              "correctness": "perfect",
              "level": "A2",
              "context_score": 5,
              "frequency": "high"
            }
          ]
        }
      }
    ],
    "learning_outcomes": {
      "vocabulary_progress": {
        "words_practiced": 12,
        "words_used_correctly": 11,
        "new_words_encountered": 4,
        "words_to_review": ["appetizer", "dessert"]
      },
      "skill_development": {
        "improved_areas": ["formal_requests", "restaurant_vocabulary"],
        "mastery_achieved": ["basic_reservation_language"],
        "next_focus": ["ordering_specific_dishes"]
      },
      "achievement_progress": {
        "dialogue_completion": true,
        "perfect_turns": 3,
        "vocabulary_milestone": false,
        "fluency_improvement": true
      }
    },
    "personalized_recommendations": [
      "Practice pronunciation of 'th' sounds in words like 'thank you'",
      "Learn more specific food vocabulary for ordering",
      "Try more complex sentence structures for B1 level"
    ]
  }
}

6. 結束對話

POST /api/v1/dialogues/{dialogue_id}/complete
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "completion_type": "natural", // natural, forced, timeout
  "user_rating": 4, // 1-5, user satisfaction
  "feedback": "Great practice session!"
}

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "completion_summary": {
      "dialogue_id": "DLG_20240907_001",
      "scenario_name": "餐廳預約與點餐",
      "duration_seconds": 420,
      "turns_completed": 8,
      "all_objectives_met": true,
      "completion_type": "natural"
    },
    "performance_summary": {
      "final_score": 88,
      "grade": "B+",
      "is_perfect_dialogue": false,
      "best_turn_score": 95,
      "average_response_time": 12.5,
      "vocabulary_accuracy": 0.92
    },
    "rewards_earned": {
      "experience_points": 150,
      "score_points": 88,
      "diamonds": 10,
      "achievements_unlocked": [
        {
          "achievement_id": "restaurant_master",
          "name": "餐廳對話專家",
          "description": "完成餐廳場景對話"
        }
      ]
    },
    "learning_progress": {
      "vocabulary_advances": [
        {
          "word": "reservation",
          "old_level": "learning",
          "new_level": "familiar"
        }
      ],
      "skill_improvements": [
        "formal_conversation",
        "restaurant_etiquette"
      ]
    },
    "next_recommendations": {
      "suggested_scenarios": [
        "SC_Restaurant_02", // 更高級餐廳場景
        "SC_Shopping_01"    // 購物場景
      ],
      "focus_areas": [
        "complex_sentence_structures",
        "polite_expressions"
      ]
    }
  }
}

7. 暫停/恢復對話

POST /api/v1/dialogues/{dialogue_id}/pause
Authorization: Bearer <access_token>
POST /api/v1/dialogues/{dialogue_id}/resume
Authorization: Bearer <access_token>

8. 獲取對話歷史

GET /api/v1/dialogues/history
Authorization: Bearer <access_token>

查詢參數

  • scenario_id: 特定場景ID (可選)
  • date_from: 開始日期 (可選)
  • date_to: 結束日期 (可選)
  • min_score: 最低分數 (可選)
  • page: 頁碼 (預設 1)
  • limit: 每頁筆數 (預設 20)

🎯 對話評分系統

評分維度

維度 權重 評分標準
Grammar 25% 語法正確性和複雜度
Semantic 30% 語義適切性和理解度
Fluency 25% 流暢度和自然性
Pronunciation 20% 發音準確度 (語音輸入)

分數等級

  • 90-100: A+ (完美) - 滿星對話
  • 80-89: B+ (優秀)
  • 70-79: B (良好)
  • 60-69: C (及格)
  • <60: D (需改進)

🔧 錯誤處理

對話相關錯誤

錯誤碼 HTTP狀態 描述 處理建議
DIALOGUE_NOT_FOUND 404 對話記錄不存在 檢查對話ID或重新開始
SCENARIO_NOT_FOUND 404 場景不存在 檢查場景ID
DIALOGUE_EXPIRED 410 對話已過期 重新開始對話
INSUFFICIENT_LIFE_POINTS 403 命條不足 購買命條或等待恢復
AI_SERVICE_UNAVAILABLE 503 AI服務暫時無法使用 稍後重試
RESPONSE_GENERATION_FAILED 500 回應生成失敗 重新發送訊息
HINT_LIMIT_EXCEEDED 429 提示使用次數超限 購買更多提示或明日重置

🧪 測試範例

開始對話

curl -X POST "https://api.dramaling.com/api/v1/dialogues/start" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"scenario_id": "SC_Restaurant_01", "practice_mode": "guided"}'

發送訊息

curl -X POST "https://api.dramaling.com/api/v1/dialogues/DLG_123/message" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"message": "I have a reservation under Smith.", "message_type": "text"}'

模組負責人: AI團隊 + 後端團隊
最後更新: 2024年9月7日
相關文檔: 用戶管理API, 遊戲化系統API