6.9 KiB
6.9 KiB
Context
当前代码已经具备以下基础能力:
settings-manager可以管理ProviderProfile / ProviderCatalog / ModelRef / InvocationPresetruntime-model-discovery可以按profileId隔离发现和选择模型- 图片和视频侧已经存在若干专用 adapter,分别处理 Flux、MJ、Kling、Seedance 等协议变体
但当前结构仍存在三个核心缺口:
resolveInvocationRoute只解析凭证和模型,不解析协议与请求体策略runtime-model-discovery仍以统一/models + Bearer的假设执行发现model-adapters仍然按模型 / 厂商 / 标签进行猜测式匹配,无法表达“同名模型在不同 profile 下走不同协议”的事实
这会导致下列问题:
- 同名模型在不同上游中发生协议冲突
- 同协议不同请求体的差异只能堆在 adapter 内的条件分支中,难以扩展
- 文本链路继续绕过统一路由层,无法和图片 / 视频共享同一套供应商协议规划
Goals / Non-Goals
- Goals:
- 让运行时调用基于
profileId + modelId + operation选择协议绑定 - 支持同一模型 ID 在不同供应商下走不同协议
- 支持同一协议下的不同请求体 schema
- 统一文本、图片、视频三类调用的运行时规划流程
- 尽量降低用户配置成本,优先自动推断协议绑定,仅在歧义时暴露高级覆盖项
- 让运行时调用基于
- Non-Goals:
- 本次不实现跨供应商自动故障切换
- 本次不实现按价格 / 延迟 / 健康度自动择优调度
- 本次不为所有第三方平台实现完全自动化、零误差的协议识别
Decisions
-
Decision: 区分“模型标识”和“可执行绑定”
modelId表示用户看到的模型ProviderModelBinding表示该模型在特定供应商下针对特定操作的调用方式- 绑定的主键必须至少包含
profileId + modelId + operation
-
Decision: 引入
InvocationPlanner- 输入:
routeType + ModelRef + optional override - 输出:
InvocationPlan - Planner 负责在多个绑定中选择当前最合适的协议,而不是让 UI 或 service 直接拼 URL
- 输入:
-
Decision: 将适配器从“按模型注册”迁移为“按协议注册”
- 现有 Flux / MJ / Kling / Seedance 等实现可以保留,但角色改为
ProtocolAdapter ProtocolAdapter负责请求体构建、响应解析、可选轮询策略
- 现有 Flux / MJ / Kling / Seedance 等实现可以保留,但角色改为
-
Decision: 将鉴权和基础 URL 处理下沉到
ProviderTransport- 统一处理
bearer / header / query / custom等认证方式 - 统一处理额外 Header、查询参数和供应商级发现接口
- 避免每个 adapter 再重复拼装认证信息
- 统一处理
-
Decision: discovery 必须保留原始元数据和绑定推断结果
- 不能只把远端模型压成扁平
ModelConfig - 必须保留
raw、capabilityHints、bindingCandidates - 否则后续运行时无法稳定判断同名模型的协议归属
- 不能只把远端模型压成扁平
-
Decision: 同名模型不得按裸
modelId全局去重- 选择器和运行时缓存应使用
selectionKey = profileId::modelId - 运行时绑定必须保留
profileId
- 选择器和运行时缓存应使用
Proposed Data Model
interface ResolvedProviderContext {
profileId: string;
profileName: string;
providerType: string;
baseUrl: string;
apiKey: string;
authType: 'bearer' | 'header' | 'query' | 'custom';
extraHeaders?: Record<string, string>;
}
interface ProviderModelBinding {
id: string;
profileId: string;
modelId: string;
operation: 'text' | 'image' | 'video';
protocol:
| 'openai.chat.completions'
| 'openai.images.generations'
| 'openai.async.video'
| 'google.generateContent'
| 'mj.imagine'
| 'flux.task'
| 'kling.video'
| 'seedance.task';
requestSchema: string;
responseSchema: string;
submitPath: string;
pollPathTemplate?: string;
priority: number;
confidence: 'high' | 'medium' | 'low';
source: 'discovered' | 'template' | 'manual';
}
interface DiscoveredProviderModel {
profileId: string;
modelId: string;
selectionKey: string;
raw: unknown;
capabilityHints: {
supportsText: boolean;
supportsImage: boolean;
supportsVideo: boolean;
};
bindings: ProviderModelBinding[];
}
interface InvocationPlan {
provider: ResolvedProviderContext;
modelRef: { profileId: string; modelId: string };
binding: ProviderModelBinding;
}
Execution Flow
- 用户在设置中保存
ProviderProfile ProviderTransport根据providerType/baseUrl选择供应商模板或探测策略- discovery 同步远端模型,并推断出每个模型的
bindings[] - 用户在运行时选择
ModelRef(profileId + modelId) InvocationPlanner根据operation找到最高优先级的可执行 bindingProtocolAdapterRegistry按binding.protocol取得协议适配器- 适配器根据
requestSchema构建请求,并通过ProviderTransport发送 - 如为异步任务,则由对应
PollingStrategy轮询并标准化结果
Binding Inference Strategy
- OpenAI 兼容供应商:
- 优先使用
/v1/models返回的字段、模型 ID 和供应商模板推断绑定 - 默认优先生成
openai.chat.completions / openai.images.generations / openai.async.video
- 优先使用
- Gemini 官方供应商:
- 不再强依赖
/models - 允许由 provider template 直接提供
google.generateContent绑定
- 不再强依赖
- 自定义供应商:
- 若 discovery 无法高置信度推断协议,则保留低置信度绑定
- 仅在需要时暴露高级覆盖入口
Request Schema Strategy
同一协议下的请求体差异不再通过大量 if modelId.includes(...) 解决,而是显式建模:
openai.image.basic-jsonopenai.video.form.input-referencegoogle.gemini.generate-content.imagekling.video.text2videokling.video.image2videoseedance.video.first-last-frame
这样新增模型时,优先复用已有协议,仅为其指派合适的 requestSchema。
Migration Plan
- 新增 provider protocol routing 类型与 planner,不改 UI
- 将现有图片 / 视频 adapter 包装为
ProtocolAdapter - 将文本链路迁移到同一 planner 和 protocol registry
- 扩展 discovery 存储,保留
bindings[] - 最后再清理旧的“按模型猜 adapter”逻辑
Risks / Trade-offs
-
风险: 架构抽象增加初始复杂度
- Mitigation: 分阶段迁移,先保留现有 adapter 实现,只调整其注册方式
-
风险: 自动推断协议可能存在误判
- Mitigation: 为 binding 引入
confidence与source,仅在低置信度场景允许高级覆盖
- Mitigation: 为 binding 引入
-
风险: 文本 / 图片 / 视频同时迁移会影响面较大
- Mitigation: 先完成 planner 和 image/video 迁移,再迁移 text
Open Questions
- 是否需要将用户手动覆盖的 binding 保存在
ProviderCatalog,还是单独存为ProviderBindingOverrides authType是否需要从当前的bearer/header扩展为更通用的query/custom- 官方 Gemini 等不提供 OpenAI 风格
/models时,设置页是否需要显式展示“供应商模板已接管模型能力”