Files
medical_training/apps/training/models.py
T

106 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.db import models
from apps.common.models import BaseModel
from apps.user.models import User
from apps.case.models import CaseBase
# ─── 只读镜像(fastapi 属主)────────────────────────────────────────────────────
# 训练相关表(training_record / training_session / training_submission /
# user_learning_profiles 等)的 schema 属主是 fastapi 服务。Django 侧一律 managed=False、
# 只读接入,仅供 CMS 查询训练记录/统计,不写。
# ⚠️ 下方字段为当前最佳镜像,正式接入前应以 `python manage.py inspectdb` 对真实库反向校准
# (真实表清单见《项目架构设计.md》第二节;注意真实库中没有 training_score_detail)。
class TrainingRecord(BaseModel):
"""训练记录表(只读,fastapi 属主,managed=False"""
TRAINING_MODE_CHOICES = [
('novice', '新手'),
('practice', '练习'),
('exam', '考试'),
]
EVALUATION_LEVEL_CHOICES = [
('excellent', '优秀'),
('good', '良好'),
('average', '一般'),
('poor', '较差'),
]
STATUS_CHOICES = [
('in_progress', '进行中'),
('completed', '已完成'),
('aborted', '已中断'),
]
id = models.BigAutoField(primary_key=True)
user = models.ForeignKey(
User, on_delete=models.CASCADE,
related_name='training_records', verbose_name='用户'
)
case = models.ForeignKey(
CaseBase, on_delete=models.CASCADE,
related_name='training_records', verbose_name='病例'
)
training_mode = models.CharField('训练模式', max_length=50, choices=TRAINING_MODE_CHOICES)
case_type = models.CharField('病例类型', max_length=30, blank=True)
teacher = models.ForeignKey(
User, on_delete=models.SET_NULL,
null=True, blank=True, related_name='supervised_records',
verbose_name='带教老师'
)
start_time = models.DateTimeField('开始时间', auto_now_add=True)
end_time = models.DateTimeField('结束时间', null=True, blank=True)
duration_seconds = models.IntegerField('训练时长', null=True, blank=True)
total_score = models.DecimalField('总分', max_digits=5, decimal_places=2, null=True, blank=True)
ai_score = models.DecimalField('AI评分', max_digits=5, decimal_places=2, null=True, blank=True)
teacher_score = models.DecimalField('教师评分', max_digits=5, decimal_places=2, null=True, blank=True)
evaluation_level = models.CharField('评价等级', max_length=20, choices=EVALUATION_LEVEL_CHOICES, blank=True)
status = models.CharField('状态', max_length=30, choices=STATUS_CHOICES, default='in_progress')
feedback = models.TextField('总评', blank=True)
thinking_chain = models.TextField('临床推理链', blank=True)
diagnosis_path = models.TextField('诊断路径', blank=True)
wrong_points = models.JSONField('错误知识点', default=list, blank=True)
missed_questions = models.JSONField('漏问项', default=list, blank=True)
recommendation_result = models.JSONField('AI推荐', default=dict, blank=True)
ai_feedback_structured = models.JSONField('AI结构化反馈', default=dict, blank=True)
osce_station_score = models.JSONField('OSCE各站点成绩', default=dict, blank=True)
interruption_count = models.IntegerField('中断次数', default=0)
emotion_analysis = models.JSONField('情绪分析', default=dict, blank=True)
prompt_version = models.CharField('Prompt版本', max_length=50, blank=True)
rag_context_version = models.CharField('知识上下文版本', max_length=50, blank=True)
class Meta:
managed = False
db_table = 'training_record'
verbose_name = '训练记录'
verbose_name_plural = '训练记录'
def __str__(self):
return f"{self.user.username} - {self.case.title}"
class TrainingScoreDetail(BaseModel):
"""评分明细表(只读占位,managed=False;真实 fastapi 库无此表,接入时以真实 schema 为准)"""
id = models.BigAutoField(primary_key=True)
record = models.ForeignKey(
TrainingRecord, on_delete=models.CASCADE,
related_name='score_details', verbose_name='训练记录'
)
rule = models.ForeignKey(
'case.ScoringRule', on_delete=models.CASCADE,
null=True, blank=True, verbose_name='评分规则'
)
dimension = models.CharField('评分维度', max_length=50)
score = models.DecimalField('分数', max_digits=5, decimal_places=2)
deducted_reason = models.TextField('扣分原因', blank=True)
evidence_message_ids = models.JSONField('对应对话证据', default=list, blank=True)
ai_confidence = models.DecimalField('AI评分置信度', max_digits=5, decimal_places=2, null=True, blank=True)
comment = models.TextField('评语', blank=True)
class Meta:
managed = False
db_table = 'training_score_detail'
verbose_name = '评分明细'
verbose_name_plural = '评分明细'
def __str__(self):
return f"{self.record} - {self.dimension}: {self.score}"