fix: improve OCR indexing and evidence review

This commit is contained in:
2026-09-25 19:03:19 +08:00
parent ac1f0ff46d
commit df5fcb4bda
12 changed files with 185 additions and 36 deletions
+25 -4
View File
@@ -8,7 +8,7 @@ from .llm import ConsistencyResult, FactResult, ModelError, ScoreResult, validat
from .models import (CriterionScore, KnowledgeDocument, Project, ScoreEvidence, ScoringBatch,
SubmissionFile, now)
from .parsing import parse_document
from .rag import ingest, retrieve
from .rag import INDEX_VERSION, ingest, retrieve
from .storage import secure_path, sha256
from .settings_store import client_for_batch
@@ -20,6 +20,18 @@ def parse_submission(db, file: SubmissionFile, *, embedder=None):
db.commit()
raise ValueError(file.parse_error)
if file.parse_status == "ready" and file.parsed:
document = db.scalar(select(KnowledgeDocument).where(KnowledgeDocument.submission_file_id == file.id))
if not document or document.source_hash != file.sha256 or document.index_version != INDEX_VERSION or document.status != "ready":
project = db.get(Project, file.project_id)
kwargs = {"embedder": embedder} if embedder else {}
try:
ingest(db, course_version_id=project.course_version_id, project_id=project.id,
submission_file_id=file.id, title=path.name, category=file.category,
source_hash=file.sha256, pages=file.parsed["pages"], **kwargs)
except Exception as exc:
file.parse_status, file.parse_error = "failed", str(exc)[:1000]
db.commit()
raise
return file.parsed
settings = get_settings()
try:
@@ -99,7 +111,16 @@ def _score_criterion(db, batch, project, criterion, client, *, retriever):
"required_output": {"criterion_id": "string", "score": "number", "max_score": "number", "reason": "string",
"evidence": [{"chunk_id": "integer", "page": "integer", "quote": "exact substring"}],
"missing_evidence": ["string"], "suggestion": "string", "confidence": "0..1"}}
result = validate_score(client.json_call(batch.course_snapshot["prompts"]["score"], payload, ScoreResult, images=images), criterion, chunks)
prompt = (batch.course_snapshot["prompts"]["score"] +
" 证据quote必须从所引用chunk_id的text逐字复制连续片段,保留原文标点和换行;page必须等于该片段的page。不要改写、缩写或拼接引文。")
for attempt in range(2):
try:
result = validate_score(client.json_call(prompt, payload, ScoreResult, images=images), criterion, chunks)
break
except ModelError:
if attempt:
raise
prompt += " 上次回答的证据未通过原文和页码校验;请重新选择片段并逐字复制quote。"
score.model_score, score.model_comment, score.confidence = result.score, result.reason, result.confidence
score.missing_evidence, score.suggestion, score.status, score.error = result.missing_evidence, result.suggestion, "scored", ""
for evidence in db.scalars(select(ScoreEvidence).where(ScoreEvidence.score_id == score.id)).all():
@@ -122,7 +143,7 @@ def _run_project(batch_id, project_id, session_factory, client_factory, embedder
client = client_factory(db, batch)
files = db.scalars(select(SubmissionFile).where(SubmissionFile.project_id == project.id)).all()
for file in files:
if file.recognition_status == "recognized" and file.parse_status != "ready":
if file.recognition_status == "recognized":
try:
parse_submission(db, file, embedder=embedder)
except Exception:
@@ -159,7 +180,7 @@ def run_batch(batch_id: int, *, session_factory=SessionLocal, client_factory=cli
raise ValueError("评分批次不存在")
project_ids = db.scalars(select(Project.id).where(Project.course_version_id == batch.course_version_id).order_by(Project.id)).all()
criteria = batch.rubric_snapshot["criteria"]
batch.status, batch.progress_total, batch.progress_done = "running", len(project_ids) * len(criteria), 0
batch.status, batch.progress_total, batch.progress_done, batch.finished_at = "running", len(project_ids) * len(criteria), 0, None
db.commit()
try:
client_factory(db, batch)