160 lines
6.4 KiB
Python
160 lines
6.4 KiB
Python
from django.core.management.base import BaseCommand, CommandError
|
||
from django.db import transaction
|
||
from django.utils import timezone
|
||
|
||
from apps.agents.models import AgentDefinition, AgentStepBinding, AgentVersion
|
||
from apps.modelhub.models import ModelDeployment
|
||
from apps.skills.models import SkillDefinition, SkillVersion
|
||
|
||
TICKET_FIELDS = {
|
||
"type": "object",
|
||
"properties": {
|
||
"title": {"type": "string"},
|
||
"description": {"type": "string"},
|
||
"category_code": {"type": "string"},
|
||
"priority": {"type": "string", "enum": ["low", "medium", "high", "urgent"]},
|
||
"problem_performance": {"type": "string"},
|
||
"problem_object": {"type": "string"},
|
||
"submitter_name": {"type": "string"},
|
||
"submitter_org": {"type": "string"},
|
||
"impact_scope": {"type": "string"},
|
||
"environment": {"type": "string"},
|
||
"related_system": {"type": "string"},
|
||
},
|
||
"required": [
|
||
"title",
|
||
"description",
|
||
"category_code",
|
||
"priority",
|
||
"problem_performance",
|
||
"problem_object",
|
||
"submitter_name",
|
||
"submitter_org",
|
||
"impact_scope",
|
||
"environment",
|
||
"related_system",
|
||
],
|
||
"additionalProperties": False,
|
||
}
|
||
|
||
AGENT_INPUT_SCHEMA = {
|
||
"type": "object",
|
||
"properties": {
|
||
"source_text": {"type": "string"},
|
||
"current_fields": {"type": "object"},
|
||
"messages": {"type": "array", "items": {"type": "object"}},
|
||
"image_refs": {"type": "array", "items": {"type": "object"}},
|
||
},
|
||
"required": ["source_text", "current_fields", "messages", "image_refs"],
|
||
}
|
||
|
||
OUTPUT_SCHEMA = {
|
||
"type": "object",
|
||
"properties": {
|
||
"fields": TICKET_FIELDS,
|
||
"missing_fields": {"type": "array", "items": {"type": "string"}},
|
||
"questions": {"type": "array", "items": {"type": "string"}},
|
||
},
|
||
"required": ["fields", "missing_fields", "questions"],
|
||
"additionalProperties": False,
|
||
}
|
||
|
||
|
||
class Command(BaseCommand):
|
||
help = "Create and publish the single-step ticket intake Agent and Skill."
|
||
|
||
def add_arguments(self, parser):
|
||
parser.add_argument("--deployment-id", type=int)
|
||
|
||
@transaction.atomic
|
||
def handle(self, *args, **options):
|
||
deployments = ModelDeployment.objects.filter(enabled=True, provider__enabled=True)
|
||
deployment_id = options.get("deployment_id")
|
||
deployment = (
|
||
deployments.filter(id=deployment_id).first() if deployment_id else deployments.first()
|
||
)
|
||
if deployment is None:
|
||
raise CommandError("请先配置并启用模型渠道和模型配置")
|
||
|
||
skill, _ = SkillDefinition.objects.get_or_create(
|
||
code="ticket-draft",
|
||
defaults={"name": "可信建单草稿", "description": "从描述与追问答案生成工单草稿。"},
|
||
)
|
||
skill_version = skill.versions.filter(status="published").order_by("-version").first()
|
||
if skill_version is None:
|
||
next_version = (
|
||
skill.versions.order_by("-version").values_list("version", flat=True).first() or 0
|
||
) + 1
|
||
skill_version = SkillVersion.objects.create(
|
||
definition=skill,
|
||
version=next_version,
|
||
status="published",
|
||
prompt_template=(
|
||
"根据用户原始描述 {{ input.source_text }}、"
|
||
"当前字段 {{ input.current_fields }}、"
|
||
"逐问记录 {{ input.messages }} 以及随消息提供的可选图片,生成完整工单草稿。"
|
||
"分类代码只能使用 business_issue、operation_issue、"
|
||
"data_issue、technical_issue。"
|
||
"无法可靠判断的值使用空字符串并列入 missing_fields,同时为缺失项生成简洁问题。"
|
||
"只输出符合 Schema 的 JSON。"
|
||
),
|
||
input_schema=AGENT_INPUT_SCHEMA,
|
||
output_schema=OUTPUT_SCHEMA,
|
||
example_input={
|
||
"source_text": "生产环境采集任务两小时没有更新",
|
||
"current_fields": {},
|
||
"messages": [],
|
||
"image_refs": [],
|
||
},
|
||
published_at=timezone.now(),
|
||
)
|
||
skill.active_version = skill_version
|
||
skill.save(update_fields=["active_version", "updated_at"])
|
||
|
||
agent, _ = AgentDefinition.objects.get_or_create(
|
||
code="ticket-intake",
|
||
defaults={"name": "可信建单 Agent", "description": "单步生成可审核的结构化工单草稿。"},
|
||
)
|
||
version = agent.versions.filter(status="published").order_by("-version").first()
|
||
if version is None:
|
||
next_version = (
|
||
agent.versions.order_by("-version").values_list("version", flat=True).first() or 0
|
||
) + 1
|
||
version = AgentVersion.objects.create(
|
||
definition=agent,
|
||
version=next_version,
|
||
status="published",
|
||
model_deployment=deployment,
|
||
system_prompt=(
|
||
"你是企业技术支持建单助手。不得创建工单,只生成待用户审核的 JSON 草稿;"
|
||
"不得臆造机构、联系人、环境或影响范围。"
|
||
),
|
||
input_schema=AGENT_INPUT_SCHEMA,
|
||
example_input={
|
||
"source_text": "生产环境采集任务两小时没有更新",
|
||
"current_fields": {},
|
||
"messages": [],
|
||
"image_refs": [],
|
||
},
|
||
published_at=timezone.now(),
|
||
)
|
||
AgentStepBinding.objects.create(
|
||
agent_version=version,
|
||
code="draft",
|
||
order=1,
|
||
skill_version=skill_version,
|
||
input_mapping={
|
||
"source_text": "$input.source_text",
|
||
"current_fields": "$input.current_fields",
|
||
"messages": "$input.messages",
|
||
"image_refs": "$input.image_refs",
|
||
},
|
||
)
|
||
agent.active_version = version
|
||
agent.save(update_fields=["active_version", "updated_at"])
|
||
self.stdout.write(
|
||
self.style.SUCCESS(
|
||
f"Published ticket-intake v{version.version} with deployment {deployment.id}."
|
||
)
|
||
)
|