feat: 接入模型动态 Fallback 与调用审计
This commit is contained in:
@@ -174,6 +174,60 @@ class AITask(TeamOwnedModel):
|
||||
return f"{self.task_type}:{self.status}:{self.id}"
|
||||
|
||||
|
||||
class AIModelAttempt(TimeStampedModel):
|
||||
"""AITask 下的一次真实模型请求审计;不参与积分预留、扣费或任务生命周期。"""
|
||||
|
||||
class Status(models.TextChoices):
|
||||
STARTED = "started", "Started"
|
||||
SUCCEEDED = "succeeded", "Succeeded"
|
||||
FAILED = "failed", "Failed"
|
||||
|
||||
task = models.ForeignKey(AITask, on_delete=models.CASCADE, related_name="model_attempts")
|
||||
sequence = models.PositiveIntegerField()
|
||||
provider = models.ForeignKey(ModelProvider, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
model_config = models.ForeignKey(ModelConfig, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
# 名称均保存历史快照,后续后台改名或删除配置也不影响旧任务审计。
|
||||
provider_name = models.CharField(max_length=128)
|
||||
provider_display_name = models.CharField(max_length=128, blank=True)
|
||||
model_name = models.CharField(max_length=128)
|
||||
model_display_name = models.CharField(max_length=128, blank=True)
|
||||
public_model_name = models.CharField(max_length=128, blank=True)
|
||||
capability = models.CharField(max_length=32)
|
||||
operation = models.CharField(max_length=64)
|
||||
status = models.CharField(max_length=24, choices=Status.choices, default=Status.STARTED)
|
||||
is_retry = models.BooleanField(default=False)
|
||||
is_fallback = models.BooleanField(default=False)
|
||||
previous_attempt = models.ForeignKey(
|
||||
"self",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="next_attempts",
|
||||
)
|
||||
provider_task_id = models.CharField(max_length=255, blank=True)
|
||||
started_at = models.DateTimeField()
|
||||
finished_at = models.DateTimeField(null=True, blank=True)
|
||||
duration_ms = models.PositiveBigIntegerField(null=True, blank=True)
|
||||
error_type = models.CharField(max_length=64, blank=True)
|
||||
provider_error_code = models.CharField(max_length=128, blank=True)
|
||||
raw_error = models.TextField(blank=True)
|
||||
safe_error_summary = models.TextField(blank=True)
|
||||
usage = models.JSONField(default=dict, blank=True)
|
||||
platform_cost = models.DecimalField(max_digits=12, decimal_places=4, default=0)
|
||||
request_summary = models.JSONField(default=dict, blank=True)
|
||||
response_summary = models.JSONField(default=dict, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["sequence"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=["task", "sequence"], name="ai_attempt_task_sequence_unique"),
|
||||
]
|
||||
indexes = [models.Index(fields=["task", "status"], name="ai_attempt_task_status_idx")]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.task_id}:{self.sequence}:{self.status}"
|
||||
|
||||
|
||||
class QualityWord(TimeStampedModel):
|
||||
"""平台单层质量词配置:按生成阶段(stage)+ 槽位(slot)挂若干质量词,
|
||||
生成侧拼提示词时优先读取本配置;**无配置则回落各 builder 的写死值**(零回归)。
|
||||
|
||||
Reference in New Issue
Block a user