Files

134 lines
5.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package common
import (
"context"
"io"
"net/http"
)
// TaskAdaptor 异步任务适配器接口
// 与同步 Adaptor 分离,因为异步任务有提交/轮询/解析等特殊方法
type TaskAdaptor interface {
// Init 初始化适配器
Init(info *RelayInfo)
// ValidateRequest 校验请求参数
ValidateRequest(ctx context.Context, info *RelayInfo, body []byte) *TaskError
// EstimateBilling 估算任务费用(提交前)。
// 返回计费上下文 map,两类键:
// - float64 乘数值:如 {"video_input": 0.6, "quality": 3.5},引擎按序连乘;
// - string 规格事实值:如 {"spec.duration": 8, "spec.resolution": "720p"},
// per_second 计费模式据此查定价矩阵(spec.duration 为 float64 秒数,spec.resolution 为规格原值)。
// 旧键 duration/resolution 保留 token 伪装估算路径使用,语义随各 adaptor 存量口径,勿混用。
EstimateBilling(ctx context.Context, info *RelayInfo, body []byte) map[string]any
// AdjustBillingOnSubmit 提交后根据上游确认参数调整计费
AdjustBillingOnSubmit(info *RelayInfo, taskData []byte) map[string]any
// BuildRequestURL 构建上游请求 URL
BuildRequestURL(info *RelayInfo) (string, error)
// BuildRequestHeader 构建上游请求 Header
BuildRequestHeader(header http.Header, info *RelayInfo) error
// BuildRequestBody 构建上游请求体
BuildRequestBody(ctx context.Context, info *RelayInfo, body []byte) (io.Reader, error)
// DoRequest 发送请求到上游
DoRequest(ctx context.Context, info *RelayInfo, requestBody io.Reader) (*http.Response, error)
// DoResponse 解析上游提交响应,返回上游任务 ID 和任务数据
DoResponse(ctx context.Context, resp *http.Response, info *RelayInfo) (upstreamTaskID string, taskData []byte, taskErr *TaskError)
// FetchTask 查询上游任务状态。ctx 供超时控制与渠道调试日志捕获器传递
//(轮询侧经 WithDebugAttempt 注入,未开启调试时透传无额外开销)
FetchTask(ctx context.Context, baseURL, apiKey string, taskData []byte) (*http.Response, error)
// ParseTaskResult 解析上游任务查询结果
ParseTaskResult(body []byte) (*TaskInfo, error)
// GetModelList 返回适配器支持的模型列表
GetModelList() []string
// GetChannelName 返回适配器名称
GetChannelName() string
}
// UpstreamRequestIDExtractor 供应商私有的「上游调用追踪 ID 提取」可选能力。
// 为什么需要:部分异步上游(如阿里 DashScope)不在响应头返回请求 ID,而是放在
// 提交响应体顶层(request_id 字段),通用管线无法用统一键提取。实现方从提交
// 响应体解析自家私有的追踪 ID,与 output.task_id(任务句柄)互补——提工单或
// 在上游日志定位一次提交调用时用它。未实现的上游走响应头提取或为空。
type UpstreamRequestIDExtractor interface {
// ExtractUpstreamRequestID 从上游提交响应体提取调用追踪 ID,未返回时为空串
ExtractUpstreamRequestID(body []byte) string
}
// TaskInfo 异步任务查询结果
type TaskInfo struct {
Status TaskStatusEnum
Progress string // "10%", "50%", "100%"
FailReason string
ResultURL string // 成功时的结果资源 URL
Data []byte // 上游原始响应
SubTasks []SubTask // 子任务结果(如多图/多视频场景)
ActualCost float64 // 上游返回的实际费用(0 表示未提供,使用预扣金额)
// 素材计量(部分任务上游 usage 返回,如 MiniMax H3 的 input_seconds/input_image_count):
// 「预扣时未知、生成后官方返回」的计费依据,素材计费方案(BillingScheme.SettleTaskCost)的结算输入。
// nil = 上游未提供
MaterialUsage *TaskMaterialUsage
// Token 用量(部分异步任务上游会返回,如火山引擎视频模型)
PromptTokens int
CompletionTokens int
TotalTokens int
}
// TaskMaterialUsage 上游任务 usage 中的素材计量。
// 与 TaskInfo.TotalTokens 同级的结算信号:链接素材(视频/音频)的时长在提交时不可知,
// 以生成成功后官方返回为准;各字段零值表示该计量上游未返回(方案自行回退)。
type TaskMaterialUsage struct {
InputVideoSeconds float64 // 输入视频时长(秒)
InputImageCount int // 输入图片张数
InputAudioSeconds float64 // 输入音频时长(秒)
OutputSeconds float64 // 输出(生成)时长(秒)
Resolution string // 实际输出分辨率规格(如 "720P",对齐 per_second 矩阵键);空 = 上游未返回
}
// TaskStatusEnum 任务状态枚举
type TaskStatusEnum string
const (
TaskStatusNotStart TaskStatusEnum = "NOT_START"
TaskStatusSubmitted TaskStatusEnum = "SUBMITTED"
TaskStatusQueued TaskStatusEnum = "QUEUED"
TaskStatusInProgress TaskStatusEnum = "IN_PROGRESS"
TaskStatusSuccess TaskStatusEnum = "SUCCESS"
TaskStatusFailure TaskStatusEnum = "FAILURE"
)
// IsTerminal 判断是否为终态
func (s TaskStatusEnum) IsTerminal() bool {
return s == TaskStatusSuccess || s == TaskStatusFailure
}
// SubTask 子任务结果
type SubTask struct {
Index int
Status TaskStatusEnum
ResultURL string
}
// TaskError 异步任务错误
type TaskError struct {
StatusCode int // HTTP 状态码
Message string // 错误消息
ErrCode string // 错误码
}
func (e *TaskError) Error() string {
return e.Message
}