From 758eee8ac6215b65cbb172c88c1957936a3e96c6 Mon Sep 17 00:00:00 2001 From: jeremygan2021 Date: Wed, 11 Mar 2026 22:10:17 +0800 Subject: [PATCH] tingwu_new --- backend/ai_services/bailian_service.py | 101 ++++++++++++++++++ .../0006_transcriptiontask_project.py | 20 ++++ backend/ai_services/models.py | 9 ++ 3 files changed, 130 insertions(+) create mode 100644 backend/ai_services/migrations/0006_transcriptiontask_project.py diff --git a/backend/ai_services/bailian_service.py b/backend/ai_services/bailian_service.py index bb9ce53..62dc8f3 100644 --- a/backend/ai_services/bailian_service.py +++ b/backend/ai_services/bailian_service.py @@ -127,6 +127,10 @@ class BailianService: evaluation.reasoning = response_content evaluation.save() + + # 同步结果到参赛项目 (如果关联了) + self._sync_evaluation_to_project(evaluation) + return evaluation except Exception as e: @@ -136,6 +140,103 @@ class BailianService: evaluation.save() return evaluation + def _sync_evaluation_to_project(self, evaluation: AIEvaluation): + """ + 将AI评估结果同步到关联的参赛项目(评分和评语) + """ + try: + task = evaluation.task + if not task.project: + return + + project = task.project + competition = project.competition + + # 1. 确定评委身份 (Based on Template) + # 用户要求:评委显示的是模板名称 + template_name = evaluation.template.name if evaluation.template else "AI智能评委" + # 使用固定前缀 + template_id 确保唯一性,这样同一个模板在不同项目里是同一个评委 + openid = f"ai_judge_{evaluation.template.id}" if evaluation.template else "ai_judge_default" + + # 延迟导入以避免循环依赖 + from shop.models import WeChatUser + from competition.models import CompetitionEnrollment, Score, Comment, ScoreDimension + + # 获取或创建虚拟评委用户 + user, created = WeChatUser.objects.get_or_create( + openid=openid, + defaults={ + 'nickname': template_name, + 'avatar_url': 'https://ui-avatars.com/api/?name=AI&background=random&color=fff' + } + ) + + # 如果名字不匹配(比如模板改名了),更新它 + if user.nickname != template_name: + user.nickname = template_name + user.save(update_fields=['nickname']) + + # 2. 确保评委已报名 (Enrollment) + enrollment, _ = CompetitionEnrollment.objects.get_or_create( + competition=competition, + user=user, + defaults={ + 'role': 'judge', + 'status': 'approved' + } + ) + + # 3. 同步评分 (Score) + if evaluation.score is not None: + # 尝试找到匹配的维度 + # 优先级:完全匹配模板名称 > 包含"AI"的维度 > 第一个维度 + dimensions = competition.score_dimensions.all() + target_dimension = None + + for dim in dimensions: + if dim.name == template_name: + target_dimension = dim + break + + if not target_dimension: + for dim in dimensions: + if "AI" in dim.name.upper(): + target_dimension = dim + break + + # 如果还是没找到,尝试创建一个默认的 "AI评分" 维度? + # 或者使用第一个维度。考虑到用户说"对应的AI评分",如果没有对应的,可能需要创建一个? + # 为了安全起见,如果找不到明确的AI维度,且存在维度,就用第一个;否则不评分。 + if not target_dimension and dimensions.exists(): + target_dimension = dimensions.first() + + if target_dimension: + Score.objects.update_or_create( + project=project, + judge=enrollment, + dimension=target_dimension, + defaults={'score': evaluation.score} + ) + logger.info(f"Synced AI score {evaluation.score} to project {project.id} dimension {target_dimension.name}") + + # 4. 同步评语 (Comment) + if evaluation.evaluation: + # 检查是否已存在该评委的评语,避免重复 + comment = Comment.objects.filter(project=project, judge=enrollment).first() + if comment: + comment.content = evaluation.evaluation + comment.save() + else: + Comment.objects.create( + project=project, + judge=enrollment, + content=evaluation.evaluation + ) + logger.info(f"Synced AI comment to project {project.id}") + + except Exception as e: + logger.error(f"Failed to sync evaluation to project: {e}") + def summarize_task(self, task): """ 对转写任务进行总结 diff --git a/backend/ai_services/migrations/0006_transcriptiontask_project.py b/backend/ai_services/migrations/0006_transcriptiontask_project.py new file mode 100644 index 0000000..3f34830 --- /dev/null +++ b/backend/ai_services/migrations/0006_transcriptiontask_project.py @@ -0,0 +1,20 @@ +# Generated by Django 6.0.1 on 2026-03-11 14:10 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ai_services', '0005_aievaluationtemplate_alter_aievaluation_options_and_more'), + ('competition', '0003_competition_project_visibility'), + ] + + operations = [ + migrations.AddField( + model_name='transcriptiontask', + name='project', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='transcription_tasks', to='competition.project', verbose_name='关联参赛项目'), + ), + ] diff --git a/backend/ai_services/models.py b/backend/ai_services/models.py index 296c451..c2d253b 100644 --- a/backend/ai_services/models.py +++ b/backend/ai_services/models.py @@ -23,6 +23,15 @@ class TranscriptionTask(models.Model): summary_data = models.JSONField(verbose_name=_('总结原始数据'), blank=True, null=True, help_text=_('阿里云返回的Summarization完整JSON')) auto_chapters_data = models.JSONField(verbose_name=_('章节原始数据'), blank=True, null=True, help_text=_('阿里云返回的AutoChapters完整JSON')) + project = models.ForeignKey( + 'competition.Project', + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='transcription_tasks', + verbose_name=_('关联参赛项目') + ) + transcription = models.TextField(verbose_name=_('逐字稿'), blank=True, null=True) summary = models.TextField(verbose_name=_('AI总结'), blank=True, null=True)