Просмотр исходного кода

feat: add task hint api contract

jimmylee 2 недель назад
Родитель
Сommit
73da85bee5

+ 15 - 0
src/types/englishSpeaking.ts

@@ -271,11 +271,26 @@ export interface DialogueReport {
   evaluation: OverallEvaluation
 }
 
+export interface TaskHint {
+  practice_level: string
+  conversation_topic: string
+  current_question: string
+  example_sentences: {
+    english: string
+    chinese: string
+  }[]
+  key_vocabulary: {
+    word: string
+    meaning: string
+  }[]
+}
+
 // 对话 API 接口
 export interface DialogueAPI {
   createSession(config: SessionConfig): Promise<SessionInfo>
   /** Throws DOMException('AbortError') on signal abort; throws DialogueApiError on non-OK HTTP. */
   generateGreeting(sessionId: string, signal?: AbortSignal): Promise<GreetingInfo>
+  generateTaskHint(sessionId: string): Promise<TaskHint>
   speak(sessionId: string, audioBlob: Blob, signal: AbortSignal): AsyncGenerator<SSEEvent>
   getReport(sessionId: string): Promise<DialogueReport>
 }

+ 32 - 0
src/views/Editor/EnglishSpeaking/services/llmService.ts

@@ -4,6 +4,7 @@ import type {
   SessionConfig,
   SessionInfo,
   GreetingInfo,
+  TaskHint,
   DialogueReport,
   SentenceEvaluation,
 } from '@/types/englishSpeaking'
@@ -195,6 +196,17 @@ export class RealDialogueAPI implements DialogueAPI {
     return { aiMessage: body.aiMessage }
   }
 
+  async generateTaskHint(sessionId: string): Promise<TaskHint> {
+    const res = await fetch(`${API_BASE}/session/${sessionId}/task-hint`, {
+      method: 'POST',
+      credentials: 'include',
+    })
+    if (!res.ok) {
+      throw new DialogueApiError(`task hint failed: ${res.status}`, res.status)
+    }
+    return await res.json()
+  }
+
   async *speak(sessionId: string, audioBlob: Blob, signal: AbortSignal): AsyncGenerator<SSEEvent> {
     const formData = new FormData()
     formData.append('sessionId', sessionId)
@@ -248,6 +260,26 @@ export class MockDialogueAPI implements DialogueAPI {
     return { aiMessage: "Hi! What's your favorite animal?" }
   }
 
+  async generateTaskHint(_sessionId: string): Promise<TaskHint> {
+    await delay(250)
+    return {
+      practice_level: 'grade5-1',
+      conversation_topic: '我最喜欢的动物',
+      current_question: '和 Tom 聊一聊「我最喜欢的动物」,试着用今天的重点词汇和句型表达你的想法。',
+      example_sentences: [
+        { english: 'I like pandas best because they are very cute.', chinese: '我最喜欢大熊猫,因为它们非常可爱。' },
+        { english: "My favorite animal is the elephant. It's really smart!", chinese: '我最喜欢的动物是大象,它真的很聪明!' },
+        { english: 'I enjoy watching animals at the zoo with my family.', chinese: '我喜欢和家人一起在动物园看动物。' },
+      ],
+      key_vocabulary: [
+        { word: 'favorite', meaning: '最喜欢的' },
+        { word: 'adorable', meaning: '可爱的' },
+        { word: 'bamboo', meaning: '竹子' },
+        { word: 'habitat', meaning: '栖息地' },
+      ],
+    }
+  }
+
   async *speak(_sessionId: string, _audioBlob: Blob, signal: AbortSignal): AsyncGenerator<SSEEvent> {
     const mockStudentTexts = [
       'I like pandas. They are very cute!',