Update main.go
Browse files
main.go
CHANGED
@@ -21,12 +21,230 @@ import (
|
|
21 |
"sync"
|
22 |
"syscall"
|
23 |
"time"
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
25 |
"github.com/google/uuid"
|
26 |
"github.com/spf13/viper"
|
27 |
"golang.org/x/net/proxy"
|
28 |
)
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
// ---------------------- 配置结构 ----------------------
|
31 |
|
32 |
type Config struct {
|
|
|
21 |
"sync"
|
22 |
"syscall"
|
23 |
"time"
|
24 |
+
|
25 |
+
"strconv"
|
26 |
+
"strings"
|
27 |
+
"io/ioutil"
|
28 |
+
|
29 |
+
"gopkg.in/yaml.v2"
|
30 |
"github.com/google/uuid"
|
31 |
"github.com/spf13/viper"
|
32 |
"golang.org/x/net/proxy"
|
33 |
)
|
34 |
|
35 |
+
|
36 |
+
|
37 |
+
// 配置结构体定义
|
38 |
+
type Config struct {
|
39 |
+
ThinkingServices []ThinkingService `yaml:"thinking_services"`
|
40 |
+
Channels map[string]Channel `yaml:"channels"`
|
41 |
+
Global GlobalConfig `yaml:"global"`
|
42 |
+
}
|
43 |
+
|
44 |
+
type ThinkingService struct {
|
45 |
+
ID int `yaml:"id"`
|
46 |
+
Name string `yaml:"name"`
|
47 |
+
Mode string `yaml:"mode"`
|
48 |
+
Model string `yaml:"model"`
|
49 |
+
BaseURL string `yaml:"base_url"`
|
50 |
+
APIPath string `yaml:"api_path"`
|
51 |
+
APIKey string `yaml:"api_key"`
|
52 |
+
Timeout int `yaml:"timeout"`
|
53 |
+
Weight int `yaml:"weight"`
|
54 |
+
Proxy string `yaml:"proxy"`
|
55 |
+
ReasoningEffort string `yaml:"reasoning_effort"`
|
56 |
+
ReasoningFormat string `yaml:"reasoning_format"`
|
57 |
+
Temperature float64 `yaml:"temperature"`
|
58 |
+
ForceStopDeepThinking bool `yaml:"force_stop_deep_thinking"`
|
59 |
+
}
|
60 |
+
|
61 |
+
type Channel struct {
|
62 |
+
Name string `yaml:"name"`
|
63 |
+
BaseURL string `yaml:"base_url"`
|
64 |
+
APIPath string `yaml:"api_path"`
|
65 |
+
Timeout int `yaml:"timeout"`
|
66 |
+
Proxy string `yaml:"proxy"`
|
67 |
+
}
|
68 |
+
|
69 |
+
type GlobalConfig struct {
|
70 |
+
Log LogConfig `yaml:"log"`
|
71 |
+
Server ServerConfig `yaml:"server"`
|
72 |
+
}
|
73 |
+
|
74 |
+
type LogConfig struct {
|
75 |
+
Level string `yaml:"level"`
|
76 |
+
Format string `yaml:"format"`
|
77 |
+
Output string `yaml:"output"`
|
78 |
+
FilePath string `yaml:"file_path"`
|
79 |
+
Debug DebugConfig `yaml:"debug"`
|
80 |
+
}
|
81 |
+
|
82 |
+
type DebugConfig struct {
|
83 |
+
Enabled bool `yaml:"enabled"`
|
84 |
+
PrintRequest bool `yaml:"print_request"`
|
85 |
+
PrintResponse bool `yaml:"print_response"`
|
86 |
+
MaxContentLength int `yaml:"max_content_length"`
|
87 |
+
}
|
88 |
+
|
89 |
+
type ServerConfig struct {
|
90 |
+
Port int `yaml:"port"`
|
91 |
+
Host string `yaml:"host"`
|
92 |
+
ReadTimeout int `yaml:"read_timeout"`
|
93 |
+
WriteTimeout int `yaml:"write_timeout"`
|
94 |
+
IdleTimeout int `yaml:"idle_timeout"`
|
95 |
+
}
|
96 |
+
|
97 |
+
// 从环境变量获取字符串值,如果环境变量不存在则返回默认值
|
98 |
+
func getEnvString(key, defaultValue string) string {
|
99 |
+
value := os.Getenv(key)
|
100 |
+
if value == "" {
|
101 |
+
return defaultValue
|
102 |
+
}
|
103 |
+
return value
|
104 |
+
}
|
105 |
+
|
106 |
+
// 从环境变量获取整数值,如果环境变量不存在或无法解析则返回默认值
|
107 |
+
func getEnvInt(key string, defaultValue int) int {
|
108 |
+
valueStr := os.Getenv(key)
|
109 |
+
if valueStr == "" {
|
110 |
+
return defaultValue
|
111 |
+
}
|
112 |
+
|
113 |
+
value, err := strconv.Atoi(valueStr)
|
114 |
+
if err != nil {
|
115 |
+
fmt.Printf("警告: 环境变量 %s 的值 '%s' 不是有效的整数,使用默认值 %d\n",
|
116 |
+
key, valueStr, defaultValue)
|
117 |
+
return defaultValue
|
118 |
+
}
|
119 |
+
|
120 |
+
return value
|
121 |
+
}
|
122 |
+
|
123 |
+
// 从环境变量获取浮点数值,如果环境变量不存在或无法解析则返回默认值
|
124 |
+
func getEnvFloat(key string, defaultValue float64) float64 {
|
125 |
+
valueStr := os.Getenv(key)
|
126 |
+
if valueStr == "" {
|
127 |
+
return defaultValue
|
128 |
+
}
|
129 |
+
|
130 |
+
value, err := strconv.ParseFloat(valueStr, 64)
|
131 |
+
if err != nil {
|
132 |
+
fmt.Printf("警告: 环境变量 %s 的值 '%s' 不是有效的浮点数,使用默认值 %f\n",
|
133 |
+
key, valueStr, defaultValue)
|
134 |
+
return defaultValue
|
135 |
+
}
|
136 |
+
|
137 |
+
return value
|
138 |
+
}
|
139 |
+
|
140 |
+
// 从环境变量获取布尔值,如果环境变量不存在或无法解析则返回默认值
|
141 |
+
func getEnvBool(key string, defaultValue bool) bool {
|
142 |
+
valueStr := os.Getenv(key)
|
143 |
+
if valueStr == "" {
|
144 |
+
return defaultValue
|
145 |
+
}
|
146 |
+
|
147 |
+
// 将字符串转换为小写以进行比较
|
148 |
+
valueStr = strings.ToLower(valueStr)
|
149 |
+
|
150 |
+
// 检查常见的布尔值表示
|
151 |
+
if valueStr == "true" || valueStr == "1" || valueStr == "yes" || valueStr == "y" {
|
152 |
+
return true
|
153 |
+
} else if valueStr == "false" || valueStr == "0" || valueStr == "no" || valueStr == "n" {
|
154 |
+
return false
|
155 |
+
}
|
156 |
+
|
157 |
+
fmt.Printf("警告: 环境变量 %s 的值 '%s' 不是有效的布尔值,使用默认值 %t\n",
|
158 |
+
key, valueStr, defaultValue)
|
159 |
+
return defaultValue
|
160 |
+
}
|
161 |
+
|
162 |
+
// 加载配置文件并应用环境变量
|
163 |
+
func LoadConfig(configPath string) (*Config, error) {
|
164 |
+
// 读取配置文件
|
165 |
+
data, err := ioutil.ReadFile(configPath)
|
166 |
+
if err != nil {
|
167 |
+
return nil, fmt.Errorf("读取配置文件错误: %v", err)
|
168 |
+
}
|
169 |
+
|
170 |
+
// 解析YAML
|
171 |
+
var config Config
|
172 |
+
if err := yaml.Unmarshal(data, &config); err != nil {
|
173 |
+
return nil, fmt.Errorf("解析配置文件错误: %v", err)
|
174 |
+
}
|
175 |
+
|
176 |
+
// 应用环境变量覆盖配置
|
177 |
+
applyEnvironmentVariables(&config)
|
178 |
+
|
179 |
+
return &config, nil
|
180 |
+
}
|
181 |
+
|
182 |
+
// 应用环境变量覆盖配置
|
183 |
+
func applyEnvironmentVariables(config *Config) {
|
184 |
+
// 确保至少有一个思考服务
|
185 |
+
if len(config.ThinkingServices) > 0 {
|
186 |
+
// 应用环境变量到第一个思考服务
|
187 |
+
ts := &config.ThinkingServices[0]
|
188 |
+
ts.Name = getEnvString("THINKING_SERVICE_NAME", ts.Name)
|
189 |
+
ts.Mode = getEnvString("THINKING_SERVICE_MODE", ts.Mode)
|
190 |
+
ts.Model = getEnvString("THINKING_SERVICE_MODEL", ts.Model)
|
191 |
+
ts.BaseURL = getEnvString("THINKING_SERVICE_BASE_URL", ts.BaseURL)
|
192 |
+
ts.APIKey = getEnvString("THINKING_SERVICE_API_KEY", ts.APIKey)
|
193 |
+
ts.Proxy = getEnvString("THINKING_SERVICE_PROXY", ts.Proxy)
|
194 |
+
ts.ReasoningEffort = getEnvString("THINKING_SERVICE_REASONING_EFFORT", ts.ReasoningEffort)
|
195 |
+
ts.ReasoningFormat = getEnvString("THINKING_SERVICE_REASONING_FORMAT", ts.ReasoningFormat)
|
196 |
+
ts.Timeout = getEnvInt("THINKING_SERVICE_TIMEOUT", ts.Timeout)
|
197 |
+
ts.Weight = getEnvInt("THINKING_SERVICE_WEIGHT", ts.Weight)
|
198 |
+
ts.Temperature = getEnvFloat("THINKING_SERVICE_TEMPERATURE", ts.Temperature)
|
199 |
+
ts.ForceStopDeepThinking = getEnvBool("THINKING_SERVICE_FORCE_STOP", ts.ForceStopDeepThinking)
|
200 |
+
}
|
201 |
+
|
202 |
+
// 应用环境变量到通道配置
|
203 |
+
if channel, exists := config.Channels["1"]; exists {
|
204 |
+
channel.Name = getEnvString("CHANNEL_NAME", channel.Name)
|
205 |
+
channel.BaseURL = getEnvString("CHANNEL_BASE_URL", channel.BaseURL)
|
206 |
+
channel.Proxy = getEnvString("CHANNEL_PROXY", channel.Proxy)
|
207 |
+
channel.Timeout = getEnvInt("CHANNEL_TIMEOUT", channel.Timeout)
|
208 |
+
config.Channels["1"] = channel
|
209 |
+
}
|
210 |
+
|
211 |
+
// 应用环境变量到全局配置
|
212 |
+
config.Global.Log.Level = getEnvString("LOG_LEVEL", config.Global.Log.Level)
|
213 |
+
config.Global.Log.Format = getEnvString("LOG_FORMAT", config.Global.Log.Format)
|
214 |
+
config.Global.Log.Output = getEnvString("LOG_OUTPUT", config.Global.Log.Output)
|
215 |
+
config.Global.Log.FilePath = getEnvString("LOG_FILE_PATH", config.Global.Log.FilePath)
|
216 |
+
|
217 |
+
config.Global.Log.Debug.Enabled = getEnvBool("DEBUG_ENABLED", config.Global.Log.Debug.Enabled)
|
218 |
+
config.Global.Log.Debug.PrintRequest = getEnvBool("DEBUG_PRINT_REQUEST", config.Global.Log.Debug.PrintRequest)
|
219 |
+
config.Global.Log.Debug.PrintResponse = getEnvBool("DEBUG_PRINT_RESPONSE", config.Global.Log.Debug.PrintResponse)
|
220 |
+
config.Global.Log.Debug.MaxContentLength = getEnvInt("DEBUG_MAX_CONTENT_LENGTH", config.Global.Log.Debug.MaxContentLength)
|
221 |
+
|
222 |
+
config.Global.Server.Port = getEnvInt("SERVER_PORT", config.Global.Server.Port)
|
223 |
+
config.Global.Server.Host = getEnvString("SERVER_HOST", config.Global.Server.Host)
|
224 |
+
config.Global.Server.ReadTimeout = getEnvInt("SERVER_READ_TIMEOUT", config.Global.Server.ReadTimeout)
|
225 |
+
config.Global.Server.WriteTimeout = getEnvInt("SERVER_WRITE_TIMEOUT", config.Global.Server.WriteTimeout)
|
226 |
+
config.Global.Server.IdleTimeout = getEnvInt("SERVER_IDLE_TIMEOUT", config.Global.Server.IdleTimeout)
|
227 |
+
}
|
228 |
+
|
229 |
+
// 示例主函数
|
230 |
+
func main() {
|
231 |
+
// 加载配置
|
232 |
+
config, err := LoadConfig("config.yaml")
|
233 |
+
if err != nil {
|
234 |
+
fmt.Printf("加载配置失败: %v\n", err)
|
235 |
+
os.Exit(1)
|
236 |
+
}
|
237 |
+
|
238 |
+
// 打印配置信息(仅用于调试)
|
239 |
+
fmt.Printf("已加载配置:\n")
|
240 |
+
fmt.Printf("思考服务名称: %s\n", config.ThinkingServices[0].Name)
|
241 |
+
fmt.Printf("思考服务基础URL: %s\n", config.ThinkingServices[0].BaseURL)
|
242 |
+
fmt.Printf("通道名称: %s\n", config.Channels["1"].Name)
|
243 |
+
fmt.Printf("通道基础URL: %s\n", config.Channels["1"].BaseURL)
|
244 |
+
|
245 |
+
// 这里继续你的应用程序逻辑...
|
246 |
+
|
247 |
+
|
248 |
// ---------------------- 配置结构 ----------------------
|
249 |
|
250 |
type Config struct {
|