feat: add governed knowledge lifecycle
This commit is contained in:
153
backend/apps/knowledge/tasks.py
Normal file
153
backend/apps/knowledge/tasks.py
Normal file
@@ -0,0 +1,153 @@
|
||||
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="知识蒸馏任务入队失败",
|
||||
)
|
||||
Reference in New Issue
Block a user