from django.conf import settings from django.db import models from django.db.models import Q class SkillDefinition(models.Model): code = models.SlugField(max_length=80, unique=True) name = models.CharField(max_length=120) description = models.TextField(blank=True) active_version = models.ForeignKey( "SkillVersion", null=True, blank=True, on_delete=models.SET_NULL, related_name="active_for_definitions", ) created_by = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="created_skills", ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["name"] class SkillVersion(models.Model): class OutputEnforcement(models.TextChoices): NATIVE_JSON_SCHEMA = "native_json_schema", "原生 JSON Schema" JSON_OBJECT = "json_object", "JSON Object" VALIDATED_JSON = "validated_json", "校验型 JSON" definition = models.ForeignKey( SkillDefinition, on_delete=models.CASCADE, related_name="versions", ) version = models.PositiveIntegerField() status = models.CharField(max_length=24, default="draft") prompt_template = models.TextField() input_schema = models.JSONField(default=dict) output_schema = models.JSONField(default=dict) output_enforcement = models.CharField( max_length=32, choices=OutputEnforcement.choices, default=OutputEnforcement.VALIDATED_JSON, ) example_input = models.JSONField(default=dict, blank=True) created_by = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="created_skill_versions", ) published_by = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="published_skill_versions", ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) published_at = models.DateTimeField(null=True, blank=True) class Meta: ordering = ["-version"] constraints = [ models.UniqueConstraint( fields=["definition", "version"], name="unique_skill_version", ), models.UniqueConstraint( fields=["definition"], condition=Q(status="draft"), name="unique_skill_draft", ), ] @property def structured_output_metrics(self) -> dict: from apps.agents.structured_metrics import build_structured_output_metrics return build_structured_output_metrics(skill_version_id=self.id)