fix: 修正学习流程中的证据、复习与进度问题
- 独立尝试按课程要求校验内容,不再任意输入即算独立成功 - 复习节点改为学后第 1/3/7/14 天,之后每 30 天抽查;复习轮换情境 - 掌握状态按作答记录推导:需认识、可回忆、跨情境使用及最近两次无帮助 - 课程证据按实际用到的目标记录;跟读与课程对话只算辅助练习 - 复习成功不再降低已有状态 - 学完课程后进入下一节未完成课程;全部学完后引导巩固与阶段评估 - 新增 3 题基础定位,按结果设置起始课程 - 新增按课程开放的对话场景,首页推荐最少练习的场景 - 切换课程时清空上一课的步骤进度 - AI 返回 JSON 格式并按 JSON 回放历史;拼写校验忽略大小写与连字符;移除学习目标选择 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,7 @@ void main() {
|
||||
final body = await captureBody('https://api.deepseek.com');
|
||||
|
||||
expect(body['thinking'], {'type': 'disabled'});
|
||||
expect(body['response_format'], {'type': 'json_object'});
|
||||
expect(body.containsKey('reasoning_effort'), isFalse);
|
||||
expect(body['max_tokens'], 200);
|
||||
});
|
||||
@@ -51,6 +52,9 @@ void main() {
|
||||
final body = await captureBody('https://api.deepseek.com/v1/responses');
|
||||
|
||||
expect(body['reasoning'], {'effort': 'none'});
|
||||
expect(body['text'], {
|
||||
'format': {'type': 'json_object'},
|
||||
});
|
||||
expect(body.containsKey('reasoning_effort'), isFalse);
|
||||
expect(body.containsKey('thinking'), isFalse);
|
||||
});
|
||||
@@ -59,6 +63,48 @@ void main() {
|
||||
final body = await captureBody('https://example.test/v1');
|
||||
|
||||
expect(body.containsKey('thinking'), isFalse);
|
||||
expect(body.containsKey('response_format'), isFalse);
|
||||
expect(body['reasoning_effort'], 'low');
|
||||
});
|
||||
|
||||
test('dialogue history replays earlier AI lines as JSON', () async {
|
||||
AiService.instance.setFallbackApiKey('test-key');
|
||||
List<dynamic>? messages;
|
||||
final reply = await http.runWithClient(
|
||||
() => AiService.instance.dialogueReply(
|
||||
provider: AiProviderType.compatible,
|
||||
endpoint: 'https://api.deepseek.com',
|
||||
model: 'deepseek-flash',
|
||||
aiGoal: 'Ask where the learner is from.',
|
||||
learnerTask: 'say where they are from',
|
||||
history: const [
|
||||
{'role': 'assistant', 'content': "Hi! What's your name?"},
|
||||
{'role': 'user', 'content': 'My name is Alex.'},
|
||||
],
|
||||
),
|
||||
() => MockClient((request) async {
|
||||
final body = jsonDecode(request.body) as Map<String, dynamic>;
|
||||
messages = body['messages'] as List<dynamic>;
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'choices': [
|
||||
{
|
||||
'message': {'content': '{"reply":"Where are you from?"}'},
|
||||
},
|
||||
],
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
expect(reply?.reply, 'Where are you from?');
|
||||
expect(messages, hasLength(3));
|
||||
expect(messages![0]['role'], 'system');
|
||||
expect(jsonDecode(messages![1]['content'] as String), {
|
||||
'reply': "Hi! What's your name?",
|
||||
});
|
||||
expect(messages![2], {'role': 'user', 'content': 'My name is Alex.'});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user