1、增加调用 AI 视频生成能力和虚拟素材库管理的对外api
2、增加后台apikkey管理 3、增加apikey单独的模型定价 4、增加apikey调用情况 5、完善所有数据的注释增加
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
from app.schemas.admin_api.api_key import (
|
||||
ApiKeyCreateRequest,
|
||||
ApiKeyUpdateRequest,
|
||||
ApiKeyResponse,
|
||||
ApiKeyCreateResponse,
|
||||
ApiKeyListItem,
|
||||
ApiKeyListOut,
|
||||
)
|
||||
from app.schemas.admin_api.api_upscale import (
|
||||
ApiUpscaleConfigData,
|
||||
ApiUpscaleConfigSaveRequest,
|
||||
ApiUpscaleConfigResponse,
|
||||
)
|
||||
from app.schemas.admin_api.api_usage import (
|
||||
ApiUsageLogResponse,
|
||||
ApiUsageSummaryResponse,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"ApiKeyCreateRequest",
|
||||
"ApiKeyUpdateRequest",
|
||||
"ApiKeyResponse",
|
||||
"ApiKeyCreateResponse",
|
||||
"ApiKeyListItem",
|
||||
"ApiKeyListOut",
|
||||
"ApiUpscaleConfigData",
|
||||
"ApiUpscaleConfigSaveRequest",
|
||||
"ApiUpscaleConfigResponse",
|
||||
"ApiUsageLogResponse",
|
||||
"ApiUsageSummaryResponse",
|
||||
]
|
||||
@@ -0,0 +1,140 @@
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
|
||||
# 保留供其他地方使用
|
||||
def _empty_to_null(value):
|
||||
"""将空字符串转为 None,避免 Pydantic 校验失败。"""
|
||||
if value == "" or value == "null":
|
||||
return None
|
||||
return value
|
||||
|
||||
|
||||
class ApiKeyCallableModel(BaseModel):
|
||||
"""API Key 可调用模型配置。支持 camelCase 和 snake_case 两种字段名。"""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
engine_type: str = Field(..., description="video | image", alias="engineType")
|
||||
engine_id: str = Field(..., description="引擎ID", alias="engineId")
|
||||
model_name: str = Field(..., description="模型名称", alias="modelName")
|
||||
|
||||
|
||||
class ApiKeyCreateRequest(BaseModel):
|
||||
"""创建 API Key 请求。支持 camelCase 和 snake_case 两种字段名。"""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
company_name: str = Field(..., max_length=128, description="公司名称", alias="companyName")
|
||||
description: str | None = Field(None, description="备注")
|
||||
callable_models: list[ApiKeyCallableModel] = Field(
|
||||
default_factory=list, description="可调用模型列表", alias="callableModels",
|
||||
)
|
||||
quota_limit: float | None = Field(None, description="配额总量,NULL=无限", alias="quotaLimit")
|
||||
quota_cycle: str | None = Field(None, description="daily | monthly | one_time | NULL=无限", alias="quotaCycle")
|
||||
valid_from: datetime | None = Field(None, description="生效时间", alias="validFrom")
|
||||
valid_until: datetime | None = Field(None, description="过期时间", alias="validUntil")
|
||||
max_concurrent_video_tasks: int | None = Field(
|
||||
None, description="最大并发视频任务数", alias="maxConcurrentVideoTasks",
|
||||
)
|
||||
|
||||
@field_validator("valid_from", "valid_until", mode="before")
|
||||
@classmethod
|
||||
def empty_str_to_none(cls, v):
|
||||
if v == "" or v == "null" or v == 0:
|
||||
return None
|
||||
return v
|
||||
|
||||
|
||||
class ApiKeyUpdateRequest(BaseModel):
|
||||
"""更新 API Key 请求。支持 camelCase 和 snake_case 两种字段名。"""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
company_name: str | None = Field(None, max_length=128, alias="companyName")
|
||||
description: str | None = None
|
||||
callable_models: list[ApiKeyCallableModel] | None = Field(None, alias="callableModels")
|
||||
quota_limit: float | None = Field(None, alias="quotaLimit")
|
||||
quota_cycle: str | None = Field(None, alias="quotaCycle")
|
||||
valid_from: datetime | None = Field(None, alias="validFrom")
|
||||
valid_until: datetime | None = Field(None, alias="validUntil")
|
||||
max_concurrent_video_tasks: int | None = Field(None, alias="maxConcurrentVideoTasks")
|
||||
is_active: bool | None = Field(None, alias="isActive")
|
||||
|
||||
@field_validator("valid_from", "valid_until", mode="before")
|
||||
@classmethod
|
||||
def empty_str_to_none(cls, v):
|
||||
if v == "" or v == "null" or v == 0:
|
||||
return None
|
||||
return v
|
||||
|
||||
|
||||
class ApiKeyResponse(BaseModel):
|
||||
"""API Key 详情响应。"""
|
||||
|
||||
id: str
|
||||
company_name: str
|
||||
api_key_prefix: str = Field(..., description="Key 前缀,如 vk_xxxx****")
|
||||
description: str | None
|
||||
callable_models: list[ApiKeyCallableModel]
|
||||
quota_limit: float | None
|
||||
quota_cycle: str | None
|
||||
quota_used: float
|
||||
valid_from: datetime | None
|
||||
valid_until: datetime | None
|
||||
max_concurrent_video_tasks: int | None
|
||||
is_active: bool
|
||||
last_used_at: datetime | None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class ApiKeyCreateResponse(BaseModel):
|
||||
"""创建 API Key 响应(包含完整明文 Key,仅此一次)。"""
|
||||
|
||||
id: str
|
||||
company_name: str
|
||||
api_key: str = Field(..., description="完整 API Key,仅创建时返回一次")
|
||||
api_key_prefix: str
|
||||
valid_until: datetime | None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class ApiKeyRevealResponse(BaseModel):
|
||||
"""揭秘 API Key 响应(随时可获取明文)。"""
|
||||
|
||||
id: str
|
||||
company_name: str
|
||||
api_key: str = Field(..., description="完整 API Key")
|
||||
api_key_prefix: str
|
||||
|
||||
|
||||
class ApiKeyListItem(BaseModel):
|
||||
"""API Key 列表项。"""
|
||||
|
||||
id: str
|
||||
company_name: str
|
||||
api_key_prefix: str
|
||||
description: str | None
|
||||
callable_models: list[ApiKeyCallableModel] = []
|
||||
quota_limit: float | None
|
||||
quota_cycle: str | None
|
||||
quota_used: float
|
||||
is_active: bool
|
||||
valid_from: datetime | None
|
||||
valid_until: datetime | None
|
||||
max_concurrent_video_tasks: int | None
|
||||
last_used_at: datetime | None
|
||||
created_at: datetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class ApiKeyListOut(BaseModel):
|
||||
"""API Key 列表响应。"""
|
||||
|
||||
total: int
|
||||
items: list[ApiKeyListItem]
|
||||
@@ -0,0 +1,33 @@
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.schemas.common import NaiveDatetime
|
||||
|
||||
|
||||
class ApiModelPricingCreate(BaseModel):
|
||||
"""创建 API 模型价格请求。支持 camelCase 和 snake_case 两种字段名。"""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
model_config_id: str = Field(
|
||||
..., max_length=32, description="引擎ID", alias="modelConfigId",
|
||||
)
|
||||
gen_type: str = Field(default="video", max_length=16, description="image | video", alias="genType")
|
||||
resolution: str = Field(..., max_length=16, description="分辨率")
|
||||
price_ratio: float = Field(default=1.0, gt=0, description="价格系数", alias="priceRatio")
|
||||
base_price: float = Field(default=0.0, ge=0, description="基础价格(元)", alias="basePrice")
|
||||
per_second_price: float = Field(default=0.0, ge=0, description="每秒价格(元)", alias="perSecondPrice")
|
||||
input_video_ratio: float = Field(default=1.0, ge=0, description="传入视频系数", alias="inputVideoRatio")
|
||||
input_video_base_price: float = Field(default=0.0, ge=0, description="传入视频基础价(元)", alias="inputVideoBasePrice")
|
||||
input_video_per_second_price: float = Field(default=0.0, ge=0, description="传入视频每秒价(元)", alias="inputVideoPerSecondPrice")
|
||||
input_image_ratio: float = Field(default=1.0, ge=0, description="传入图片系数", alias="inputImageRatio")
|
||||
input_image_base_price: float = Field(default=0.0, ge=0, description="传入图片基础价(元)", alias="inputImageBasePrice")
|
||||
input_image_per_image_price: float = Field(default=0.0, ge=0, description="传入图片每张价(元)", alias="inputImagePerImagePrice")
|
||||
|
||||
|
||||
class ApiModelPricingOut(ApiModelPricingCreate):
|
||||
"""API 模型价格响应。"""
|
||||
|
||||
id: str
|
||||
created_at: NaiveDatetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||
@@ -0,0 +1,38 @@
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class ApiUpscaleRule(BaseModel):
|
||||
"""API 超分规则。支持 camelCase 和 snake_case 两种字段名。"""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
target_resolution: str = Field(..., description="目标分辨率: 480p | 720p | 1080p | 2K | 4K", alias="targetResolution")
|
||||
provider_generation_resolution: str = Field(..., description="供应商生成分辨率", alias="providerGenerationResolution")
|
||||
processor_key: str = Field(
|
||||
...,
|
||||
description="处理器: local_ffmpeg_crop_v1 | volc_standard_v1 | volc_professional_v1 | volc_large_model_v1",
|
||||
alias="processorKey",
|
||||
)
|
||||
enabled: bool = True
|
||||
|
||||
|
||||
class ApiUpscaleConfigData(BaseModel):
|
||||
"""API 超分配置数据。支持 camelCase 和 snake_case 两种字段名。"""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
enabled: bool = False
|
||||
delete_source_after_success: bool = Field(True, alias="deleteSourceAfterSuccess")
|
||||
rules: list[ApiUpscaleRule] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ApiUpscaleConfigSaveRequest(BaseModel):
|
||||
"""保存 API 超分配置请求。"""
|
||||
|
||||
data: ApiUpscaleConfigData
|
||||
|
||||
|
||||
class ApiUpscaleConfigResponse(BaseModel):
|
||||
"""API 超分配置响应。"""
|
||||
|
||||
data: ApiUpscaleConfigData
|
||||
@@ -0,0 +1,36 @@
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ApiUsageLogResponse(BaseModel):
|
||||
"""API 使用日志响应。"""
|
||||
|
||||
id: str
|
||||
api_key_id: str
|
||||
api_generation_task_id: str | None
|
||||
request_type: str
|
||||
model_name: str
|
||||
gen_type: str
|
||||
credits_cost: float
|
||||
tokens_used: int
|
||||
request_duration_ms: int
|
||||
status: str
|
||||
error_message: str | None
|
||||
error_code: str | None
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ApiUsageSummaryResponse(BaseModel):
|
||||
"""API 使用汇总响应。"""
|
||||
|
||||
total_requests: int
|
||||
total_credits_cost: float
|
||||
total_tokens_used: int
|
||||
success_count: int
|
||||
failed_count: int
|
||||
avg_duration_ms: int
|
||||
items: list[ApiUsageLogResponse]
|
||||
@@ -0,0 +1,33 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class VpV3QuotaConfigData(BaseModel):
|
||||
"""后台保存虚拟素材库配额。"""
|
||||
|
||||
project_limit: int = Field(0, ge=0, description="虚拟项目上限,0=不可创建")
|
||||
asset_limit: int = Field(0, ge=0, description="虚拟素材总数上限,0=不可上传")
|
||||
storage_mb_limit: int = Field(0, ge=0, description="存储上限 MB,0=不可上传文件")
|
||||
remark: str | None = Field(None, max_length=500, description="后台备注")
|
||||
|
||||
|
||||
class VpV3QuotaConfigResponse(BaseModel):
|
||||
"""虚拟素材库配额响应。"""
|
||||
|
||||
model_config = ConfigDict(extra="ignore")
|
||||
|
||||
api_key_id: str = Field(description="API Key ID")
|
||||
|
||||
# 上限
|
||||
project_limit: int = Field(0, description="虚拟项目上限")
|
||||
asset_limit: int = Field(0, description="虚拟素材上限")
|
||||
storage_mb_limit: int = Field(0, description="存储上限 MB")
|
||||
remark: str | None = Field(None, description="备注")
|
||||
|
||||
# 已使用
|
||||
project_used: int = Field(0, description="已创建项目数")
|
||||
asset_used: int = Field(0, description="已上传素材数")
|
||||
storage_mb_used: float = Field(0.0, description="已使用存储 MB")
|
||||
|
||||
enabled: bool = Field(False, description="是否启用(任一上限 > 0)")
|
||||
Reference in New Issue
Block a user