| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- <?php
- namespace App\Services;
- use Illuminate\Support\Facades\Http;
- use Illuminate\Support\Facades\Log;
- use Illuminate\Support\Facades\DB;
- class ChatGPTAnalysisService
- {
- protected string $learningAnalyticsUrl;
- protected int $timeout;
- public function __construct()
- {
- $this->learningAnalyticsUrl = config('services.learning_analytics.base_url', env('LEARNING_ANALYTICS_URL', 'http://localhost:5016'));
- $this->timeout = 180; // ChatGPT分析超时
- }
- /**
- * 使用ChatGPT分析试卷图片
- *
- * @param string $paperId 试卷ID
- * @param string $imageUrl 试卷图片URL
- * @return array 分析结果
- */
- public function analyzeExamPaper(string $paperId, string $imageUrl): array
- {
- try {
- Log::info('开始ChatGPT分析', [
- 'paper_id' => $paperId,
- 'image_url' => $imageUrl
- ]);
- // 获取题目数据
- $questionsData = $this->getPaperQuestions($paperId);
- if (empty($questionsData)) {
- throw new \Exception('未找到试卷题目');
- }
- // 调用LearningAnalytics的ChatGPT分析API
- $requestData = [
- 'paper_id' => $paperId,
- 'questions' => $questionsData,
- 'image_url' => $imageUrl,
- 'student_id' => $this->getStudentId($paperId),
- ];
- Log::info('调用LearningAnalytics ChatGPT分析API', [
- 'url' => $this->learningAnalyticsUrl . '/api/v1/chatgpt/analyze',
- 'question_count' => count($questionsData)
- ]);
- $response = Http::timeout($this->timeout)
- ->post($this->learningAnalyticsUrl . '/api/v1/chatgpt/analyze', $requestData);
- if (!$response->successful()) {
- throw new \Exception('LearningAnalytics API调用失败: ' . $response->body());
- }
- $responseData = $response->json();
- Log::info('ChatGPT分析完成', [
- 'paper_id' => $paperId,
- 'questions_count' => count($responseData['questions'] ?? []),
- 'success' => true
- ]);
- return [
- 'success' => true,
- 'data' => $responseData,
- ];
- } catch (\Exception $e) {
- Log::error('ChatGPT分析失败', [
- 'paper_id' => $paperId,
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString()
- ]);
- return [
- 'success' => false,
- 'error' => $e->getMessage(),
- 'data' => null
- ];
- }
- }
- /**
- * 获取试卷题目
- */
- private function getPaperQuestions(string $paperId): array
- {
- try {
- // 处理OCR记录
- if (str_starts_with($paperId, 'ocr_')) {
- $recordId = substr($paperId, 4);
- $ocrQuestions = DB::table('ocr_question_results')
- ->where('ocr_record_id', $recordId)
- ->orderBy('question_number')
- ->get()
- ->map(function ($q) {
- // 优先使用人工校准的答案
- $studentAnswer = !empty(trim($q->manual_answer ?? ''))
- ? trim($q->manual_answer)
- : trim($q->student_answer ?? '');
- return [
- 'question_number' => $q->question_number,
- 'question_id' => $q->question_number,
- 'content' => $q->question_text,
- 'correct_answer' => '', // ChatGPT会从图片识别
- 'knowledge_point' => $q->kp_code,
- 'question_type' => 'unknown',
- 'score' => $q->score_total ?? 5
- ];
- })
- ->toArray();
- return $ocrQuestions;
- }
- // 处理系统生成卷子
- $questions = DB::table('paper_questions')
- ->where('paper_id', $paperId)
- ->orderBy('question_number')
- ->get()
- ->map(function ($q) {
- return [
- 'question_number' => $q->question_number,
- 'question_id' => $q->question_bank_id,
- 'content' => $q->question_text,
- 'correct_answer' => '', // ChatGPT会从图片识别
- 'knowledge_point' => $q->knowledge_point,
- 'question_type' => $q->question_type,
- 'score' => $q->score
- ];
- })
- ->toArray();
- return $questions;
- } catch (\Exception $e) {
- Log::error('获取试卷题目失败', [
- 'paper_id' => $paperId,
- 'error' => $e->getMessage()
- ]);
- return [];
- }
- }
- /**
- * 获取学生ID
- */
- private function getStudentId(string $paperId): ?string
- {
- try {
- // 处理OCR记录
- if (str_starts_with($paperId, 'ocr_')) {
- $recordId = substr($paperId, 4);
- $record = DB::table('ocr_records')->where('id', $recordId)->first();
- return $record->student_id ?? null;
- }
- // 处理系统生成卷子
- $paper = DB::table('papers')->where('paper_id', $paperId)->first();
- return $paper->student_id ?? null;
- } catch (\Exception $e) {
- Log::error('获取学生ID失败', [
- 'paper_id' => $paperId,
- 'error' => $e->getMessage()
- ]);
- return null;
- }
- }
- /**
- * 保存ChatGPT分析结果到数据库
- */
- public function saveAnalysisResult(string $paperId, array $analysisData): bool
- {
- try {
- return DB::transaction(function () use ($paperId, $analysisData) {
- // 更新papers表的analysis_id
- DB::table('papers')
- ->where('paper_id', $paperId)
- ->update([
- 'analysis_id' => $analysisData['analysis_id'] ?? ('chatgpt_' . uniqid()),
- 'updated_at' => now()
- ]);
- // 保存详细分析结果到answer_analysis表
- if (isset($analysisData['questions'])) {
- foreach ($analysisData['questions'] as $questionData) {
- $questionNumber = $questionData['q'] ?? null;
- if (!$questionNumber) continue;
- // 查找对应的paper_question记录
- $paperQuestion = null;
- if (str_starts_with($paperId, 'ocr_')) {
- // OCR记录使用question_number作为ID
- $paperQuestion = (object)[
- 'question_bank_id' => 'ocr_q' . $questionNumber,
- 'score' => 5
- ];
- } else {
- $paperQuestion = DB::table('paper_questions')
- ->where('paper_id', $paperId)
- ->where('question_number', $questionNumber)
- ->first();
- }
- if ($paperQuestion) {
- DB::table('answer_analysis')->updateOrInsert(
- [
- 'paper_id' => $paperId,
- 'question_id' => $paperQuestion->question_bank_id,
- 'question_number' => $questionNumber,
- ],
- [
- 'student_answer' => $questionData['student_answer'] ?? null,
- 'correct_answer' => $questionData['correct_answer'] ?? null,
- 'is_correct' => $questionData['is_correct'] ?? false,
- 'score_obtained' => $questionData['is_correct'] ? ($paperQuestion->score ?? 0) : 0,
- 'max_score' => $paperQuestion->score ?? 0,
- 'analysis_result' => json_encode($questionData, JSON_UNESCAPED_UNICODE),
- 'updated_at' => now()
- ]
- );
- }
- }
- }
- Log::info('ChatGPT分析结果保存成功', [
- 'paper_id' => $paperId,
- 'questions_count' => count($analysisData['questions'] ?? [])
- ]);
- return true;
- });
- } catch (\Exception $e) {
- Log::error('保存ChatGPT分析结果失败', [
- 'paper_id' => $paperId,
- 'error' => $e->getMessage()
- ]);
- return false;
- }
- }
- }
|