feat: 完善模型请求适配与输出限制
This commit is contained in:
@@ -3,6 +3,8 @@ package store
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
@@ -116,6 +118,9 @@ func (s *Store) createPlatformModel(ctx context.Context, q platformModelQuerier,
|
||||
if len(capabilities) == 0 {
|
||||
capabilities = EffectivePlatformModelCapabilities(base.Capabilities, input.CapabilityOverride)
|
||||
}
|
||||
if err := validateEnabledVolcesTextModelCapabilities(ctx, q, input, capabilities); err != nil {
|
||||
return PlatformModel{}, err
|
||||
}
|
||||
billingConfig := input.BillingConfig
|
||||
if len(billingConfig) == 0 {
|
||||
billingConfig = mergeObjects(base.BaseBillingConfig, input.BillingConfigOverride)
|
||||
@@ -262,6 +267,76 @@ RETURNING id::text, platform_id::text, COALESCE(base_model_id::text, ''), model_
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func validateEnabledVolcesTextModelCapabilities(ctx context.Context, q platformModelQuerier, input CreatePlatformModelInput, capabilities map[string]any) error {
|
||||
// createPlatformModel enables/upserts models unconditionally, so every text
|
||||
// model that reaches this path must already satisfy the Volcengine invariant.
|
||||
if !containsTextOutputModelType(input.ModelType) {
|
||||
return nil
|
||||
}
|
||||
var provider string
|
||||
var baseURL string
|
||||
if err := q.QueryRow(ctx, `SELECT provider, COALESCE(base_url, '') FROM integration_platforms WHERE id = $1::uuid`, input.PlatformID).Scan(&provider, &baseURL); err != nil {
|
||||
return err
|
||||
}
|
||||
provider = strings.ToLower(strings.TrimSpace(provider))
|
||||
baseURL = strings.ToLower(strings.TrimSpace(baseURL))
|
||||
if provider != "volces-openai" && !strings.Contains(baseURL, "volces.com") && !strings.Contains(baseURL, "byteplus.com") {
|
||||
return nil
|
||||
}
|
||||
seen := map[string]struct{}{}
|
||||
for _, modelType := range append(append(StringList{}, input.ModelType...), "text_generate") {
|
||||
modelType = strings.TrimSpace(modelType)
|
||||
if modelType == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[modelType]; ok {
|
||||
continue
|
||||
}
|
||||
seen[modelType] = struct{}{}
|
||||
capability, _ := capabilities[modelType].(map[string]any)
|
||||
if value, ok := positiveWholeNumber(capability["max_output_tokens"]); ok && value > 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("%w: enabled Volcengine text model %q requires a positive integer max_output_tokens capability for its text model type or text_generate fallback", ErrInvalidPlatformModelConfiguration, input.ProviderModelName)
|
||||
}
|
||||
|
||||
func containsTextOutputModelType(values StringList) bool {
|
||||
for _, value := range values {
|
||||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||||
case "text_generate", "chat", "responses", "text":
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func positiveWholeNumber(value any) (int64, bool) {
|
||||
var number float64
|
||||
switch typed := value.(type) {
|
||||
case int:
|
||||
number = float64(typed)
|
||||
case int32:
|
||||
number = float64(typed)
|
||||
case int64:
|
||||
number = float64(typed)
|
||||
case float64:
|
||||
number = typed
|
||||
case json.Number:
|
||||
parsed, err := typed.Float64()
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
number = parsed
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
if number <= 0 || math.Trunc(number) != number || number > math.MaxInt64 {
|
||||
return 0, false
|
||||
}
|
||||
return int64(number), true
|
||||
}
|
||||
|
||||
func (s *Store) DeletePlatformModel(ctx context.Context, id string) error {
|
||||
tx, err := s.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user