feat(multimodal): 实现本地模型管线与请求用量配置
This commit is contained in:
@@ -2,7 +2,8 @@ from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Annotated, Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, SecretStr, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, SecretStr, field_validator, model_validator
|
||||
from app.request_overrides import RequestOverride
|
||||
|
||||
|
||||
class Contract(BaseModel):
|
||||
@@ -783,6 +784,8 @@ class ProviderConnectionFields(Contract):
|
||||
|
||||
|
||||
class ProviderConfig(ProviderConnectionFields):
|
||||
version: int = Field(default=1, ge=1)
|
||||
request_overrides: list[RequestOverride] = Field(default_factory=list, max_length=32)
|
||||
provider_id: str
|
||||
provider_type: ProviderType
|
||||
name: str
|
||||
@@ -794,6 +797,7 @@ class ProviderConfig(ProviderConnectionFields):
|
||||
|
||||
|
||||
class ProviderCreateRequest(ProviderConnectionFields):
|
||||
request_overrides: list[RequestOverride] = Field(default_factory=list, max_length=32)
|
||||
provider_type: ProviderType
|
||||
name: str
|
||||
base_url: str | None = None
|
||||
@@ -803,6 +807,8 @@ class ProviderCreateRequest(ProviderConnectionFields):
|
||||
|
||||
|
||||
class ProviderUpdateRequest(ProviderConnectionFields):
|
||||
version: int | None = Field(default=None, ge=1)
|
||||
request_overrides: list[RequestOverride] | None = Field(default=None, max_length=32)
|
||||
provider_type: ProviderType | None = None
|
||||
name: str | None = None
|
||||
base_url: str | None = None
|
||||
@@ -890,6 +896,7 @@ class EmbeddingResult(Contract):
|
||||
class SpeakerMatchRequest(Contract):
|
||||
attachment_id: str
|
||||
reference_attachment_id: str
|
||||
local_only: bool = False
|
||||
|
||||
|
||||
class SpeakerMatchResult(Contract):
|
||||
@@ -978,18 +985,74 @@ class TranscriptionRequest(Contract):
|
||||
attachment_id: str
|
||||
language: str | None = None
|
||||
diarization: bool = False
|
||||
local_only: bool = False
|
||||
word_timestamps: bool = False
|
||||
idempotency_key: str | None = Field(default=None, min_length=1, max_length=128)
|
||||
terminology: dict[str, str] = Field(default_factory=dict, max_length=200)
|
||||
|
||||
@field_validator("terminology")
|
||||
@classmethod
|
||||
def bound_terminology(cls, value):
|
||||
if any(not key or len(key) > 200 or len(replacement) > 200 for key, replacement in value.items()):
|
||||
raise ValueError("术语不能为空,每个术语与替换文本最多 200 字符")
|
||||
return value
|
||||
|
||||
|
||||
class TranscriptSegment(Contract):
|
||||
segment_id: str
|
||||
start_time: float = Field(ge=0)
|
||||
end_time: float = Field(ge=0)
|
||||
text: str
|
||||
speaker: str | None = None
|
||||
language: str | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def valid_interval(self):
|
||||
import math
|
||||
if not math.isfinite(self.start_time) or not math.isfinite(self.end_time) or self.end_time < self.start_time:
|
||||
raise ValueError("invalid segment time range")
|
||||
return self
|
||||
|
||||
|
||||
class TranscriptionJob(Contract):
|
||||
job_id: str
|
||||
attachment_id: str
|
||||
status: Literal["queued", "processing", "completed", "failed"]
|
||||
status: Literal["queued", "processing", "running", "completed", "failed", "cancelled"]
|
||||
text: str | None = None
|
||||
error_code: str | None = None
|
||||
error_message: str | None = None
|
||||
created_at: datetime
|
||||
source: Literal["api", "local", "sidecar"] | None = None
|
||||
fallback_reason: str | None = None
|
||||
segments: list[TranscriptSegment] = Field(default_factory=list)
|
||||
original_text: str | None = None
|
||||
original_segments: list[TranscriptSegment] = Field(default_factory=list)
|
||||
speaker_names: dict[str, str] = Field(default_factory=dict)
|
||||
warnings: list[str] = Field(default_factory=list)
|
||||
progress: float | None = Field(default=None, ge=0, le=1)
|
||||
revision: int = 1
|
||||
started_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
completed_at: datetime | None = None
|
||||
language: str | None = None
|
||||
local_only: bool = False
|
||||
previous_job_id: str | None = None
|
||||
model_snapshot: dict[str, Any] = Field(default_factory=dict)
|
||||
corrections: list[dict[str, str]] = Field(default_factory=list)
|
||||
|
||||
|
||||
class TranscriptEditRequest(Contract):
|
||||
revision: int = Field(ge=1)
|
||||
text: str = Field(max_length=1_000_000)
|
||||
segments: list[TranscriptSegment] = Field(default_factory=list, max_length=10000)
|
||||
speaker_names: dict[str, str] = Field(default_factory=dict, max_length=200)
|
||||
|
||||
|
||||
class TranscriptNoteRequest(Contract):
|
||||
title: str = Field(min_length=1, max_length=200)
|
||||
folder: str | None = None
|
||||
include_timestamps: bool = True
|
||||
include_speakers: bool = True
|
||||
|
||||
|
||||
class IndexStatus(Contract):
|
||||
|
||||
Reference in New Issue
Block a user