feat: separate contents, abstract and body evidence
This commit is contained in:
@@ -9,6 +9,7 @@ from redis import Redis
|
||||
from rq import Queue, Retry
|
||||
from sqlalchemy import delete, func, select
|
||||
from .config import get_settings
|
||||
from .evidence import plan_snapshot
|
||||
from .exports import export_excel, export_project_pdf
|
||||
from .models import (AuditLog, CourseVersion, CriterionScore, IndexTask, KnowledgeChunk, KnowledgeDocument,
|
||||
Project, RubricVersion, ScoringBatch, Student, Submission, SubmissionFile, TeacherRevision)
|
||||
@@ -209,9 +210,12 @@ def create_batch(data, db):
|
||||
if not version.published or not rubric.published or rubric.course_version_id != version.id:
|
||||
raise HTTPException(400, "请选择同一课程版本下已发布的规则")
|
||||
settings = get_settings()
|
||||
# The evidence policy travels with the batch snapshot, so a batch can always be read
|
||||
# back against the rules and page permissions it was actually scored with.
|
||||
batch = ScoringBatch(course_version_id=version.id, rubric_version_id=rubric.id,
|
||||
course_snapshot={key: getattr(version, key) for key in ("version", "title", "objectives", "indicators", "directions", "prompts", "templates")},
|
||||
rubric_snapshot={"version": rubric.version, "criteria": rubric.criteria, "weights": rubric.weights},
|
||||
rubric_snapshot={"version": rubric.version, "criteria": rubric.criteria,
|
||||
"weights": rubric.weights, "evidence_plan": plan_snapshot(rubric.criteria)},
|
||||
model_config_snapshot=model_config(db), embedding_model_name=settings.embedding_model_name,
|
||||
embedding_model_version=settings.embedding_model_version,
|
||||
status="created", project_ids=db.scalars(select(Project.id).where(
|
||||
@@ -226,7 +230,7 @@ def start_batch(batch_id: int, db):
|
||||
batch = db.scalar(select(ScoringBatch).where(ScoringBatch.id == batch_id).with_for_update())
|
||||
if not batch:
|
||||
raise HTTPException(404, "评分批次不存在")
|
||||
if batch.status not in ("created", "failed", "partial"):
|
||||
if batch.status not in ("created", "failed", "partial", "review_required"):
|
||||
db.rollback()
|
||||
raise HTTPException(409, "批次已入队、运行中或已完成")
|
||||
try:
|
||||
@@ -244,15 +248,29 @@ def start_batch(batch_id: int, db):
|
||||
return {"id": batch.id, "status": batch.status}
|
||||
|
||||
def review_score(score_id: int, data, db):
|
||||
"""Record a teacher decision. Model scores, retrieval gaps and history are kept.
|
||||
|
||||
A teacher may review any criterion in any state, including one awaiting review or
|
||||
one whose material is missing: the teacher is the authority on a criterion the
|
||||
retrieval could not support. The gaps from the original retrieval stay on the record
|
||||
after the review, so the reason it reached the teacher remains auditable.
|
||||
"""
|
||||
score = found(db, CriterionScore, score_id)
|
||||
batch = found(db, ScoringBatch, score.batch_id)
|
||||
criterion = next((item for item in batch.rubric_snapshot["criteria"] if item["criterion_id"] == score.criterion_id), None)
|
||||
if not criterion or data.score > criterion["max_score"]:
|
||||
raise HTTPException(400, "教师分数超出规则满分")
|
||||
from_status = score.status
|
||||
db.add(TeacherRevision(score_id=score.id, old_score=score.teacher_score, new_score=data.score,
|
||||
old_comment=score.teacher_comment, new_comment=data.comment, reason=data.reason))
|
||||
score.teacher_score, score.teacher_comment, score.status = data.score, data.comment, "reviewed"
|
||||
audit(db, "review", "criterion_score", score.id, {"reason": data.reason})
|
||||
score.teacher_score, score.teacher_comment = data.score, data.comment
|
||||
# ``evidence_gaps`` is intentionally left untouched: it records why the criterion
|
||||
# reached the teacher, independently of the score the teacher then entered.
|
||||
score.status = "reviewed"
|
||||
audit(db, "review", "criterion_score", score.id,
|
||||
{"reason": data.reason, "from_status": from_status,
|
||||
"came_from_review": bool(score.evidence_gaps)})
|
||||
db.commit()
|
||||
return {"id": score.id, "model_score": score.model_score, "teacher_score": score.teacher_score,
|
||||
"final_score": score.final_score, "teacher_comment": score.teacher_comment}
|
||||
"final_score": score.final_score, "teacher_comment": score.teacher_comment,
|
||||
"status": score.status, "evidence_gaps": score.evidence_gaps or []}
|
||||
|
||||
Reference in New Issue
Block a user