161 lines
6.2 KiB
Python
161 lines
6.2 KiB
Python
from django.utils import timezone
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
from django.urls import reverse
|
|
|
|
from agent_core.orchestrator import run_agent
|
|
from agent_core.results import AgentResult
|
|
from apps.audit.services import create_audit_log, create_notification_record
|
|
from apps.documents.models import SubmissionBatch, UploadedDocument
|
|
from apps.scenarios.services import get_scenario
|
|
|
|
from .forms import ChatForm
|
|
from .models import Conversation
|
|
|
|
|
|
def index(request):
|
|
conversations = Conversation.objects.all()
|
|
if conversations.exists():
|
|
return redirect("chat:detail", conversation_id=conversations.first().conversation_id)
|
|
return render(
|
|
request,
|
|
"chat/index.html",
|
|
{
|
|
"conversation": None,
|
|
"conversations": [],
|
|
"form": ChatForm(),
|
|
"documents": [],
|
|
"result": None,
|
|
"audit_log": None,
|
|
"node_results": [],
|
|
"active_node": None,
|
|
},
|
|
)
|
|
|
|
|
|
def detail(request, conversation_id: str):
|
|
conversation = get_object_or_404(Conversation, conversation_id=conversation_id)
|
|
batch = SubmissionBatch.objects.filter(batch_id=conversation.batch_id).first()
|
|
documents = UploadedDocument.objects.filter(batch=batch)
|
|
form = ChatForm(request.POST or None, documents=documents)
|
|
result = None
|
|
audit_log = None
|
|
active_node = None
|
|
task_modes = [
|
|
{"name": "目录汇总", "description": "汇总文件、页数、章节点和目录型文档。"},
|
|
{"name": "完整性检查", "description": "对照法规模板检查齐套性、缺失项和错放项。"},
|
|
{"name": "字段抽取", "description": "抽取产品名称、规格、适用范围、储存条件等核心字段。"},
|
|
{"name": "一致性核查", "description": "比较申请表、说明书和产品列表的字段一致性。"},
|
|
{"name": "综合风险报告", "description": "形成高优先级问题、建议动作和责任人通知。"},
|
|
]
|
|
if request.method == "POST" and form.is_valid():
|
|
scenario = get_scenario("document_review")
|
|
message = form.cleaned_data["message"]
|
|
try:
|
|
result = run_agent(
|
|
scenario,
|
|
message,
|
|
options={
|
|
"conversation_id": conversation.conversation_id,
|
|
"batch_id": conversation.batch_id,
|
|
"product_name": conversation.product_name,
|
|
"document_ids": form.cleaned_data["document_ids"],
|
|
},
|
|
)
|
|
except Exception as exc:
|
|
result = AgentResult(status="failed", error=str(exc), answer="")
|
|
audit_log = create_audit_log(
|
|
"document_review",
|
|
"注册审核智能体",
|
|
message,
|
|
result,
|
|
batch_id=conversation.batch_id,
|
|
conversation_id=conversation.conversation_id,
|
|
product_name=conversation.product_name,
|
|
)
|
|
_apply_agent_result_to_conversation(conversation, result)
|
|
_persist_notification_records(
|
|
result,
|
|
web_detail_url=reverse("audit:detail", args=[audit_log.id]),
|
|
)
|
|
active_node = "risk"
|
|
conversation.refresh_from_db()
|
|
workspace_summary = _build_workspace_summary(conversation, batch)
|
|
|
|
return render(
|
|
request,
|
|
"chat/index.html",
|
|
{
|
|
"conversation": conversation,
|
|
"conversations": Conversation.objects.all(),
|
|
"batch": batch,
|
|
"form": form,
|
|
"documents": documents,
|
|
"document_count": documents.count(),
|
|
"result": result,
|
|
"audit_log": audit_log,
|
|
"task_modes": task_modes,
|
|
"node_results": conversation.node_results,
|
|
"active_node": active_node,
|
|
"workspace_summary": workspace_summary,
|
|
},
|
|
)
|
|
|
|
|
|
def _persist_notification_records(result: AgentResult, *, web_detail_url: str = "") -> None:
|
|
payload = result.notification_payload or {}
|
|
owners = payload.get("owners") or []
|
|
if not owners:
|
|
return
|
|
for owner in owners:
|
|
create_notification_record(
|
|
batch_id=payload.get("batch_id", ""),
|
|
conversation_id=payload.get("conversation_id", ""),
|
|
product_name=payload.get("product_name", ""),
|
|
trigger_source="agent_execution",
|
|
notify_reason=payload.get("notify_reason", "task_completed"),
|
|
owner_role=owner.get("owner_role", ""),
|
|
feishu_user_id=owner.get("feishu_user_id", ""),
|
|
message_status="sent" if result.status == "success" else "failed",
|
|
web_detail_url=web_detail_url,
|
|
receipt={"status": result.status},
|
|
)
|
|
|
|
|
|
def _build_workspace_summary(conversation: Conversation, batch: SubmissionBatch | None) -> dict:
|
|
node_status_map = {node.get("label"): node.get("status", "") for node in conversation.node_results}
|
|
risk_status = node_status_map.get("风险预警", "待处理")
|
|
notify_status = node_status_map.get("飞书通知", "待处理")
|
|
export_status = node_status_map.get("Word 回填导出", "待处理")
|
|
highest_risk_level = "高" if risk_status in {"已阻断", "待复核"} else "中"
|
|
export_allowed = "否" if risk_status in {"已阻断", "待复核"} else "是"
|
|
return {
|
|
"highest_risk_level": highest_risk_level,
|
|
"export_allowed": export_allowed,
|
|
"notify_status": notify_status,
|
|
"export_status": export_status,
|
|
"file_count": batch.file_count if batch else 0,
|
|
"page_count": batch.page_count if batch else 0,
|
|
}
|
|
|
|
|
|
def _apply_agent_result_to_conversation(conversation: Conversation, result: AgentResult) -> None:
|
|
conversation.task_status = result.status
|
|
if result.node_results:
|
|
conversation.node_results = result.node_results
|
|
conversation.latest_summary = {
|
|
"answer": result.answer,
|
|
"status": result.status,
|
|
"error": result.error,
|
|
"notification_payload": result.notification_payload,
|
|
}
|
|
conversation.last_run_at = timezone.now()
|
|
conversation.save(
|
|
update_fields=[
|
|
"task_status",
|
|
"node_results",
|
|
"latest_summary",
|
|
"last_run_at",
|
|
"updated_at",
|
|
]
|
|
)
|