mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-29 06:00:52 +02:00
fix: normalize deepseek config profile
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -946,10 +947,12 @@ func (c *Config) ApplyDefaultAIChannel() {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
c.NormalizeAIProviderProfiles()
|
||||
c.AI.EnsureDefaultFromOpenAI(c.OpenAI)
|
||||
if oa, _, ok := c.AI.ResolveChannel(c.AI.DefaultChannel); ok {
|
||||
c.OpenAI = oa
|
||||
}
|
||||
c.NormalizeAIProviderProfiles()
|
||||
}
|
||||
|
||||
func (c OpenAIConfig) MaxCompletionTokensEffective() int {
|
||||
@@ -968,6 +971,50 @@ func (c OpenAIConfig) IsDeepSeekEndpointOrModel() bool {
|
||||
return strings.Contains(baseURL, "deepseek")
|
||||
}
|
||||
|
||||
func (c OpenAIConfig) IsDeepSeekOfficialEndpoint() bool {
|
||||
host := normalizedURLHost(c.BaseURL)
|
||||
return host == "api.deepseek.com"
|
||||
}
|
||||
|
||||
func normalizedURLHost(raw string) string {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return ""
|
||||
}
|
||||
parsed, err := url.Parse(raw)
|
||||
if err != nil || parsed.Host == "" {
|
||||
parsed, err = url.Parse("https://" + strings.TrimLeft(raw, "/"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return strings.ToLower(strings.TrimPrefix(parsed.Hostname(), "www."))
|
||||
}
|
||||
|
||||
func NormalizeOpenAIProviderProfile(oa *OpenAIConfig) {
|
||||
if oa == nil {
|
||||
return
|
||||
}
|
||||
if oa.IsDeepSeekOfficialEndpoint() {
|
||||
oa.Reasoning.Profile = "deepseek"
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) NormalizeAIProviderProfiles() {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
NormalizeOpenAIProviderProfile(&c.OpenAI)
|
||||
if c.AI.Channels != nil {
|
||||
for id, ch := range c.AI.Channels {
|
||||
oa := ch.ToOpenAIConfig()
|
||||
NormalizeOpenAIProviderProfile(&oa)
|
||||
ch.Reasoning = oa.Reasoning
|
||||
c.AI.Channels[id] = ch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAIReasoningConfig 全局默认与网关 profile(对话页可通过 ChatRequest.reasoning 覆盖,受 AllowClientReasoning 约束)。
|
||||
type OpenAIReasoningConfig struct {
|
||||
// Mode: auto(默认)| on | off | default(与 auto 相同)。
|
||||
@@ -1399,6 +1446,7 @@ func Load(path string) (*Config, error) {
|
||||
if cfg.Audit.MaxDetailBytes <= 0 {
|
||||
cfg.Audit.MaxDetailBytes = 8192
|
||||
}
|
||||
cfg.NormalizeAIProviderProfiles()
|
||||
cfg.ApplyDefaultAIChannel()
|
||||
if err := validateOpenAIOutputLimits(cfg.OpenAI); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -160,6 +160,84 @@ func TestLoadUsesAIDefaultChannelAsRuntimeOpenAI(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeAIProviderProfilesForOfficialDeepSeekEndpoint(t *testing.T) {
|
||||
cfg := &Config{
|
||||
OpenAI: OpenAIConfig{
|
||||
BaseURL: "https://api.deepseek.com/v1",
|
||||
Model: "deepseek-chat",
|
||||
Reasoning: OpenAIReasoningConfig{
|
||||
Profile: "openai_compat",
|
||||
},
|
||||
},
|
||||
AI: AIConfig{
|
||||
Channels: map[string]AIChannelConfig{
|
||||
"official": {
|
||||
BaseURL: "api.deepseek.com/v1",
|
||||
Model: "deepseek-chat",
|
||||
Reasoning: OpenAIReasoningConfig{
|
||||
Profile: "auto",
|
||||
},
|
||||
},
|
||||
"gateway": {
|
||||
BaseURL: "https://compatible.example.com/v1",
|
||||
Model: "deepseek-chat",
|
||||
Reasoning: OpenAIReasoningConfig{
|
||||
Profile: "openai_compat",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cfg.NormalizeAIProviderProfiles()
|
||||
|
||||
if cfg.OpenAI.Reasoning.Profile != "deepseek" {
|
||||
t.Fatalf("openai profile = %q, want deepseek", cfg.OpenAI.Reasoning.Profile)
|
||||
}
|
||||
if got := cfg.AI.Channels["official"].Reasoning.Profile; got != "deepseek" {
|
||||
t.Fatalf("official channel profile = %q, want deepseek", got)
|
||||
}
|
||||
if got := cfg.AI.Channels["gateway"].Reasoning.Profile; got != "openai_compat" {
|
||||
t.Fatalf("gateway profile should be preserved, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadNormalizesDefaultChannelForOfficialDeepSeekEndpoint(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "config.yaml")
|
||||
initial := strings.Join([]string{
|
||||
"ai:",
|
||||
" default_channel: deepseek",
|
||||
" channels:",
|
||||
" deepseek:",
|
||||
" name: DeepSeek",
|
||||
" provider: openai_compatible",
|
||||
" base_url: https://api.deepseek.com/v1",
|
||||
" api_key: deepseek-key",
|
||||
" model: deepseek-chat",
|
||||
" reasoning:",
|
||||
" profile: openai_compat",
|
||||
"server:",
|
||||
" host: 127.0.0.1",
|
||||
" port: 8080",
|
||||
"",
|
||||
}, "\n")
|
||||
if err := os.WriteFile(path, []byte(initial), 0644); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
|
||||
cfg, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Load: %v", err)
|
||||
}
|
||||
if cfg.OpenAI.Reasoning.Profile != "deepseek" {
|
||||
t.Fatalf("runtime OpenAI profile = %q, want deepseek", cfg.OpenAI.Reasoning.Profile)
|
||||
}
|
||||
if got := cfg.AI.Channels["deepseek"].Reasoning.Profile; got != "deepseek" {
|
||||
t.Fatalf("channel profile = %q, want deepseek", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSummarizationUserIntentLedgerRunesEffective(t *testing.T) {
|
||||
var zero MultiAgentEinoMiddlewareConfig
|
||||
if got := zero.SummarizationUserIntentLedgerMaxRunesEffective(); got != DefaultSummarizationUserIntentLedgerMaxRunes {
|
||||
|
||||
@@ -1169,6 +1169,8 @@ func (h *ConfigHandler) UpdateConfig(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
h.config.NormalizeAIProviderProfiles()
|
||||
|
||||
// 保存配置到文件
|
||||
if err := h.saveConfig(); err != nil {
|
||||
h.logger.Error("保存配置失败", zap.Error(err))
|
||||
@@ -1744,6 +1746,8 @@ func (h *ConfigHandler) ApplyConfig(c *gin.Context) {
|
||||
|
||||
// saveConfig 保存配置到文件
|
||||
func (h *ConfigHandler) saveConfig() error {
|
||||
h.config.NormalizeAIProviderProfiles()
|
||||
|
||||
// 读取现有配置文件并创建备份
|
||||
data, err := os.ReadFile(h.configPath)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user