feat: complete multimodal ticket intake
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from apps.tickets.evaluation import IntakeEvaluationError, import_evaluation_cases
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "导入阶段 2 智能受理脱敏评估案例"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("path")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
try:
|
||||
created, updated = import_evaluation_cases(options["path"])
|
||||
except (IntakeEvaluationError, OSError, ValueError) as error:
|
||||
raise CommandError(str(error)) from error
|
||||
self.stdout.write(self.style.SUCCESS(f"案例导入完成:新增 {created},更新 {updated}"))
|
||||
@@ -0,0 +1,31 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from apps.tickets.evaluation import record_evaluation_result
|
||||
from apps.tickets.models import IntakeEvaluationCase, TicketDraft
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "将一次真实受理结果与脱敏案例基准进行比对"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("--case", required=True, dest="case_key")
|
||||
parser.add_argument("--draft", required=True, dest="draft_public_id")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
case = IntakeEvaluationCase.objects.filter(key=options["case_key"], enabled=True).first()
|
||||
if case is None:
|
||||
raise CommandError("评估案例不存在或已停用")
|
||||
draft = TicketDraft.objects.filter(public_id=options["draft_public_id"]).first()
|
||||
if draft is None:
|
||||
raise CommandError("受理记录不存在")
|
||||
result = record_evaluation_result(case, draft)
|
||||
accuracy = (
|
||||
f"{float(result.field_accuracy) * 100:.1f}%"
|
||||
if result.field_accuracy is not None
|
||||
else "无字段基准"
|
||||
)
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"评估完成:passed={result.passed},field_accuracy={accuracy}"
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from apps.tickets.evaluation import build_stage_2_acceptance_report
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "生成阶段 2 智能受理验收报告,并可用于 CI 阻断未满足的退出条件"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"--include-synthetic",
|
||||
action="store_true",
|
||||
help="包含合成案例,仅用于诊断评估框架,永不判定阶段可退出",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
choices=["text", "json"],
|
||||
default="text",
|
||||
dest="output_format",
|
||||
)
|
||||
parser.add_argument("--output", help="可选 JSON 报告输出路径")
|
||||
parser.add_argument(
|
||||
"--fail-on-not-ready",
|
||||
action="store_true",
|
||||
help="阶段未满足退出条件时返回非零退出码",
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
report = build_stage_2_acceptance_report(
|
||||
include_synthetic=options["include_synthetic"]
|
||||
)
|
||||
report_json = json.dumps(report, ensure_ascii=False, indent=2)
|
||||
output_path = options.get("output")
|
||||
if output_path:
|
||||
path = Path(output_path)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(f"{report_json}\n", encoding="utf-8")
|
||||
|
||||
if options["output_format"] == "json":
|
||||
self.stdout.write(report_json)
|
||||
else:
|
||||
metrics = report["metrics"]["evaluation"]
|
||||
auto_rate = metrics["auto_creation_rate"]
|
||||
field_accuracy = metrics["field_accuracy"]
|
||||
evidence_rate = metrics["evidence_coverage_rate"]
|
||||
self.stdout.write(
|
||||
f"阶段 2 验收状态:{report['status']};"
|
||||
f"案例覆盖 {metrics['reviewed_case_count']}/{metrics['enabled_case_count']};"
|
||||
f"自动建单率 {_percentage(auto_rate)};"
|
||||
f"字段准确率 {_percentage(field_accuracy)};"
|
||||
f"证据覆盖率 {_percentage(evidence_rate)}"
|
||||
)
|
||||
for reason in report["reasons"]:
|
||||
self.stdout.write(self.style.WARNING(f"- {reason['message']}"))
|
||||
if output_path:
|
||||
self.stdout.write(f"JSON 报告:{Path(output_path).resolve()}")
|
||||
|
||||
if options["fail_on_not_ready"] and not report["exit_ready"]:
|
||||
raise CommandError(f"阶段 2 尚不可退出:{report['status']}")
|
||||
|
||||
|
||||
def _percentage(value) -> str:
|
||||
return f"{value * 100:.1f}%" if value is not None else "无证据"
|
||||
@@ -2,7 +2,6 @@ from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from apps.tickets.draft_services import (
|
||||
confirm_draft,
|
||||
create_agent_run_for_draft,
|
||||
execute_draft_analysis,
|
||||
)
|
||||
@@ -29,38 +28,12 @@ class Command(BaseCommand):
|
||||
run = create_agent_run_for_draft(draft)
|
||||
execute_draft_analysis(draft.id, run.id)
|
||||
draft.refresh_from_db()
|
||||
if draft.status != "ready":
|
||||
if draft.status != "ticket_created" or draft.confirmed_ticket_id is None:
|
||||
raise CommandError(f"真实文本分析失败: {draft.error_code} {draft.error_message}")
|
||||
|
||||
fields = {
|
||||
**draft.current_fields,
|
||||
"title": draft.current_fields.get("title") or "生产采集任务未更新",
|
||||
"description": draft.current_fields.get("description") or draft.source_text,
|
||||
"category_code": "technical_issue",
|
||||
"priority": draft.current_fields.get("priority")
|
||||
if draft.current_fields.get("priority") in {"low", "medium", "high", "urgent"}
|
||||
else "high",
|
||||
"problem_performance": draft.current_fields.get("problem_performance")
|
||||
or "采集进度长时间未更新",
|
||||
"problem_object": draft.current_fields.get("problem_object") or "JOB-1024",
|
||||
"submitter_name": draft.current_fields.get("submitter_name") or "验收用户",
|
||||
"submitter_org": draft.current_fields.get("submitter_org") or "验收机构",
|
||||
"environment": draft.current_fields.get("environment") or "生产环境",
|
||||
"impact_scope": draft.current_fields.get("impact_scope") or "单个客户",
|
||||
"related_system": draft.current_fields.get("related_system") or "数据采集平台",
|
||||
}
|
||||
draft.current_fields = fields
|
||||
draft.revision += 1
|
||||
draft.save(update_fields=["current_fields", "revision", "updated_at"])
|
||||
revision = draft.revision
|
||||
first = confirm_draft(draft.public_id, revision, user)
|
||||
second = confirm_draft(draft.public_id, revision, user)
|
||||
if first.confirmed_ticket_id != second.confirmed_ticket_id:
|
||||
raise CommandError("重复确认创建了不同工单")
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
"Ticket intake acceptance passed: "
|
||||
f"draft={draft.public_id} run={run.public_id} "
|
||||
f"ticket={first.confirmed_ticket.ticket_no} decision={first.decision}"
|
||||
f"ticket={draft.confirmed_ticket.ticket_no} decision={draft.decision}"
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user