from celery import shared_task from django.contrib.auth import get_user_model from apps.audit.models import OperationAuditLog from apps.knowledge.documents import process_knowledge_document from apps.knowledge.embeddings import KnowledgeEmbeddingError from apps.knowledge.models import KnowledgeDocument from apps.knowledge.services import sync_governed_asset_index, sync_ticket_search_index @shared_task( bind=True, autoretry_for=(KnowledgeEmbeddingError,), retry_backoff=True, retry_jitter=True, max_retries=3, ) def sync_ticket_search_index_task(self, ticket_id: int) -> int: return sync_ticket_search_index(ticket_id) def dispatch_ticket_search_index(ticket_id: int) -> None: try: sync_ticket_search_index_task.delay(ticket_id) except Exception: OperationAuditLog.objects.create( module="knowledge", action="ticket_index_queue_failed", target_type="ticket", target_id=str(ticket_id), request_snapshot={}, result="failure", ) @shared_task( bind=True, autoretry_for=(KnowledgeEmbeddingError,), retry_backoff=True, retry_jitter=True, max_retries=3, ) def sync_governed_asset_index_task( self, asset_type: str, object_id: int, ) -> int: return sync_governed_asset_index(asset_type, object_id) def dispatch_governed_asset_index(asset_type: str, object_id: int) -> None: try: sync_governed_asset_index_task.delay(asset_type, object_id) except Exception: OperationAuditLog.objects.create( module="knowledge", action="asset_index_queue_failed", target_type=asset_type, target_id=str(object_id), request_snapshot={}, result="failure", ) @shared_task(name="apps.knowledge.tasks.process_knowledge_document") def process_knowledge_document_task(document_id: int) -> None: process_knowledge_document(document_id) def dispatch_knowledge_document_processing(document_id: int) -> None: try: result = process_knowledge_document_task.delay(document_id) except Exception as error: document = KnowledgeDocument.objects.filter(id=document_id).first() if document is not None: document.parse_status = "failed" document.parse_error = "文档处理任务入队失败,请重试" document.task_id = "" document.save( update_fields=["parse_status", "parse_error", "task_id", "updated_at"] ) OperationAuditLog.objects.create( module="knowledge", action="document_processing_queue_failed", target_type="knowledge_document", target_id=str(document.public_id) if document else str(document_id), request_snapshot={"error_type": type(error).__name__}, result="failed", ) return KnowledgeDocument.objects.filter(id=document_id).update(task_id=result.id or "") @shared_task(name="apps.knowledge.tasks.start_ticket_knowledge_distillation") def start_ticket_knowledge_distillation_task( ticket_id: int, actor_id: int | None = None, ) -> int | None: from apps.knowledge.distillation import start_ticket_knowledge_distillation from apps.tickets.models import Ticket from apps.workitems.services import sync_knowledge_distillation_work_item ticket = Ticket.objects.filter(id=ticket_id).first() if ticket is None: return None actor = get_user_model().objects.filter(id=actor_id).first() if actor_id else None try: distillation = start_ticket_knowledge_distillation(ticket, created_by=actor) except Exception as error: OperationAuditLog.objects.create( user=actor, module="knowledge", action="knowledge_distillation_start_failed", target_type="ticket", target_id=str(ticket_id), request_snapshot={"error_type": type(error).__name__}, result="failed", ) sync_knowledge_distillation_work_item( ticket, error_code="start_failed", error_message=str(error), actor=actor, ) return None return distillation.id def dispatch_ticket_knowledge_distillation( ticket_id: int, actor_id: int | None = None, ) -> None: try: start_ticket_knowledge_distillation_task.delay(ticket_id, actor_id) except Exception as error: from apps.tickets.models import Ticket from apps.workitems.services import sync_knowledge_distillation_work_item OperationAuditLog.objects.create( module="knowledge", action="knowledge_distillation_queue_failed", target_type="ticket", target_id=str(ticket_id), request_snapshot={"error_type": type(error).__name__}, result="failed", ) ticket = Ticket.objects.filter(id=ticket_id).first() if ticket is not None: sync_knowledge_distillation_work_item( ticket, error_code="queue_failed", error_message="知识蒸馏任务入队失败", )