| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- <?php
- namespace Tests\Feature;
- use Tests\TestCase;
- use Illuminate\Support\Facades\Http;
- use App\Models\OCRRecord;
- use App\Models\OCRQuestionResult;
- class OcrQuestionAnalysisTest extends TestCase
- {
- /**
- * 不使用数据库事务,使用真实数据库
- */
- protected $connectionsToTransact = [];
- /**
- * 测试OCR题目分析API
- *
- * 从数据库获取已OCR识别的题目,发送到题库API进行分析
- */
- public function test_ocr_question_analysis()
- {
- // 强制使用MySQL连接
- config(['database.default' => 'mysql']);
- echo "\n" . str_repeat("=", 80) . "\n";
- echo "🧪 OCR题目分析测试\n";
- echo str_repeat("=", 80) . "\n\n";
- // 1. 从数据库获取OCR题目
- $recordId = 12;
- echo "📚 从数据库读取OCR记录 #{$recordId} 的题目...\n";
- $ocrQuestions = OCRQuestionResult::where('ocr_record_id', $recordId)
- ->orderBy('question_number')
- ->get();
- if ($ocrQuestions->isEmpty()) {
- echo "❌ 未找到OCR记录 {$recordId} 的题目数据\n";
- $this->fail("No OCR questions found for record {$recordId}");
- return;
- }
- echo "✅ 获取到 {$ocrQuestions->count()} 道题目\n\n";
- // 2. 构建请求数据
- $questions = [];
- foreach ($ocrQuestions as $oq) {
- // 使用校准后的答案,如果没有则使用OCR识别的答案
- $studentAnswer = !empty($oq->manual_answer) ? $oq->manual_answer : $oq->student_answer;
- $questions[] = [
- 'question_number' => $oq->question_number,
- 'question_text' => $oq->question_text ?? '',
- 'student_answer' => $studentAnswer ?? ''
- ];
- }
- // 3. 调用题库API
- echo "📤 发送请求到题库API: http://localhost:5015/api/questions/analyze-ocr\n";
- echo "题目数量: " . count($questions) . "\n\n";
- echo "题目列表:\n";
- foreach ($questions as $i => $q) {
- $preview = mb_substr($q['question_text'], 0, 50);
- echo " " . ($i + 1) . ". {$preview}...\n";
- echo " 学生答案: {$q['student_answer']}\n";
- }
- echo "\n";
- echo "🤖 调用AI分析中,请稍候...\n\n";
- $response = Http::timeout(120)->post('http://localhost:5015/api/questions/analyze-ocr', [
- 'questions' => $questions,
- 'grade_level' => '高一',
- 'subject' => '数学'
- ]);
- // 4. 检查响应
- if (!$response->successful()) {
- echo "❌ API调用失败\n";
- echo "状态码: {$response->status()}\n";
- echo "响应: " . $response->body() . "\n";
- $this->fail("API call failed with status " . $response->status());
- return;
- }
- $result = $response->json();
- if ($result['status'] !== 'success') {
- echo "❌ 分析失败: " . ($result['message'] ?? 'Unknown error') . "\n";
- $this->fail("Analysis failed: " . ($result['message'] ?? 'Unknown error'));
- return;
- }
- // 5. 显示分析结果
- echo str_repeat("=", 80) . "\n";
- echo "📊 分析结果\n";
- echo str_repeat("=", 80) . "\n\n";
- echo "✅ 分析成功,使用模型: " . ($result['model_used'] ?? 'unknown') . "\n\n";
- $analyzedQuestions = $result['questions'] ?? [];
- foreach ($ocrQuestions as $index => $original) {
- if (!isset($analyzedQuestions[$index])) {
- continue;
- }
- $analyzed = $analyzedQuestions[$index];
- echo str_repeat("=", 60) . "\n";
- echo "题目 " . ($index + 1) . "\n";
- echo str_repeat("=", 60) . "\n\n";
- // 原始题目
- echo "📝 原始题目:\n";
- $questionText = $original->question_text ?? '';
- $preview = mb_substr($questionText, 0, 100);
- echo " {$preview}...\n\n";
- // 学生答案vs标准答案
- $studentAnswer = !empty($original->manual_answer) ? $original->manual_answer : $original->student_answer;
- echo "👤 学生答案: {$studentAnswer}\n";
- echo "✓ 标准答案: " . ($analyzed['answer'] ?? 'N/A') . "\n";
- $isCorrect = $analyzed['is_correct'] ?? false;
- echo " 判断结果: " . ($isCorrect ? '✓ 正确' : '✗ 错误') . "\n\n";
- // 知识点匹配
- echo "🎯 知识点匹配:\n";
- echo " 主知识点: " . ($analyzed['kp_code'] ?? 'N/A') . "\n";
- echo " 全部知识点: " . implode(', ', $analyzed['kp_codes'] ?? []) . "\n";
- echo " 匹配度: " . ($analyzed['kp_similarity'] ?? 'N/A') . "\n\n";
- // 题目属性
- echo "📊 题目属性:\n";
- echo " 题型: " . ($analyzed['question_type'] ?? 'N/A') . "\n";
- echo " 难度: " . ($analyzed['difficulty'] ?? 'N/A') . "\n\n";
- // 解析
- echo "💡 解析:\n";
- $solution = $analyzed['solution'] ?? 'N/A';
- $solutionPreview = mb_substr($solution, 0, 150);
- echo " {$solutionPreview}" . (mb_strlen($solution) > 150 ? '...' : '') . "\n\n";
- // 错误说明
- if (!$isCorrect && !empty($analyzed['explanation'])) {
- echo "⚠️ 错误说明:\n";
- $explanation = $analyzed['explanation'];
- $explanationPreview = mb_substr($explanation, 0, 150);
- echo " {$explanationPreview}" . (mb_strlen($explanation) > 150 ? '...' : '') . "\n\n";
- }
- // 题库状态
- echo "💾 题库状态:\n";
- echo " 题目ID: " . ($analyzed['question_bank_id'] ?? 'N/A') . "\n";
- echo " 已保存: " . ($analyzed['saved_to_db'] ? '是' : '否(已存在)') . "\n\n";
- }
- echo str_repeat("=", 80) . "\n";
- echo "✅ 测试完成\n";
- echo str_repeat("=", 80) . "\n\n";
- // 断言:确保所有题目都得到了分析
- $this->assertEquals(count($questions), count($analyzedQuestions), "分析的题目数量应该与输入相同");
- // 断言:每道题都有标准答案
- foreach ($analyzedQuestions as $q) {
- $this->assertNotEmpty($q['answer'], "题目 {$q['question_number']} 应该有标准答案");
- $this->assertNotEmpty($q['kp_code'], "题目 {$q['question_number']} 应该有知识点");
- }
- }
- }
|