实现统一模型 ID 格式 (provider_id/model_name),支持跨协议模型标识和 Smart Passthrough。 核心变更: - 新增 pkg/modelid 包:解析、格式化、校验统一模型 ID - 数据库迁移:models 表使用 UUID 主键 + UNIQUE(provider_id, model_name) 约束 - Repository 层:FindByProviderAndModelName、ListEnabled 方法 - Service 层:联合唯一校验、provider ID 字符集校验 - Conversion 层:ExtractModelName、RewriteRequestModelName/RewriteResponseModelName 方法 - Handler 层:统一模型 ID 路由、Smart Passthrough、Models API 本地聚合 - 新增 error-responses、unified-model-id 规范 测试覆盖: - 单元测试:modelid、conversion、handler、service、repository - 集成测试:统一模型 ID 路由、Smart Passthrough 保真性、跨协议转换 - 迁移测试:UUID 主键、UNIQUE 约束、级联删除 OpenSpec: - 归档 unified-model-id 变更到 archive/2026-04-21-unified-model-id - 同步 11 个 delta specs 到 main specs - 新增 error-responses、unified-model-id 规范文件
107 lines
3.5 KiB
Go
107 lines
3.5 KiB
Go
package conversion
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"nex/backend/internal/conversion/canonical"
|
|
)
|
|
|
|
// ProtocolAdapter 协议适配器接口
|
|
type ProtocolAdapter interface {
|
|
ProtocolName() string
|
|
ProtocolVersion() string
|
|
SupportsPassthrough() bool
|
|
|
|
DetectInterfaceType(nativePath string) InterfaceType
|
|
BuildUrl(nativePath string, interfaceType InterfaceType) string
|
|
BuildHeaders(provider *TargetProvider) map[string]string
|
|
SupportsInterface(interfaceType InterfaceType) bool
|
|
|
|
DecodeRequest(raw []byte) (*canonical.CanonicalRequest, error)
|
|
EncodeRequest(req *canonical.CanonicalRequest, provider *TargetProvider) ([]byte, error)
|
|
DecodeResponse(raw []byte) (*canonical.CanonicalResponse, error)
|
|
EncodeResponse(resp *canonical.CanonicalResponse) ([]byte, error)
|
|
|
|
CreateStreamDecoder() StreamDecoder
|
|
CreateStreamEncoder() StreamEncoder
|
|
|
|
EncodeError(err *ConversionError) ([]byte, int)
|
|
|
|
DecodeModelsResponse(raw []byte) (*canonical.CanonicalModelList, error)
|
|
EncodeModelsResponse(list *canonical.CanonicalModelList) ([]byte, error)
|
|
DecodeModelInfoResponse(raw []byte) (*canonical.CanonicalModelInfo, error)
|
|
EncodeModelInfoResponse(info *canonical.CanonicalModelInfo) ([]byte, error)
|
|
DecodeEmbeddingRequest(raw []byte) (*canonical.CanonicalEmbeddingRequest, error)
|
|
EncodeEmbeddingRequest(req *canonical.CanonicalEmbeddingRequest, provider *TargetProvider) ([]byte, error)
|
|
DecodeEmbeddingResponse(raw []byte) (*canonical.CanonicalEmbeddingResponse, error)
|
|
EncodeEmbeddingResponse(resp *canonical.CanonicalEmbeddingResponse) ([]byte, error)
|
|
DecodeRerankRequest(raw []byte) (*canonical.CanonicalRerankRequest, error)
|
|
EncodeRerankRequest(req *canonical.CanonicalRerankRequest, provider *TargetProvider) ([]byte, error)
|
|
DecodeRerankResponse(raw []byte) (*canonical.CanonicalRerankResponse, error)
|
|
EncodeRerankResponse(resp *canonical.CanonicalRerankResponse) ([]byte, error)
|
|
|
|
// 统一模型 ID 相关方法
|
|
ExtractUnifiedModelID(nativePath string) (string, error)
|
|
ExtractModelName(body []byte, ifaceType InterfaceType) (string, error)
|
|
RewriteRequestModelName(body []byte, newModel string, ifaceType InterfaceType) ([]byte, error)
|
|
RewriteResponseModelName(body []byte, newModel string, ifaceType InterfaceType) ([]byte, error)
|
|
}
|
|
|
|
// AdapterRegistry 适配器注册表接口
|
|
type AdapterRegistry interface {
|
|
Register(adapter ProtocolAdapter) error
|
|
Get(protocolName string) (ProtocolAdapter, error)
|
|
ListProtocols() []string
|
|
}
|
|
|
|
// memoryRegistry 基于内存的适配器注册表
|
|
type memoryRegistry struct {
|
|
mu sync.RWMutex
|
|
adapters map[string]ProtocolAdapter
|
|
}
|
|
|
|
// NewMemoryRegistry 创建内存注册表
|
|
func NewMemoryRegistry() AdapterRegistry {
|
|
return &memoryRegistry{
|
|
adapters: make(map[string]ProtocolAdapter),
|
|
}
|
|
}
|
|
|
|
// Register 注册适配器
|
|
func (r *memoryRegistry) Register(adapter ProtocolAdapter) error {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
name := adapter.ProtocolName()
|
|
if _, exists := r.adapters[name]; exists {
|
|
return fmt.Errorf("适配器已注册: %s", name)
|
|
}
|
|
r.adapters[name] = adapter
|
|
return nil
|
|
}
|
|
|
|
// Get 获取适配器
|
|
func (r *memoryRegistry) Get(protocolName string) (ProtocolAdapter, error) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
adapter, ok := r.adapters[protocolName]
|
|
if !ok {
|
|
return nil, fmt.Errorf("未找到适配器: %s", protocolName)
|
|
}
|
|
return adapter, nil
|
|
}
|
|
|
|
// ListProtocols 列出所有已注册协议
|
|
func (r *memoryRegistry) ListProtocols() []string {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
protocols := make([]string, 0, len(r.adapters))
|
|
for name := range r.adapters {
|
|
protocols = append(protocols, name)
|
|
}
|
|
return protocols
|
|
}
|