feat: enhance file handling and logging in the application
This commit is contained in:
@@ -73,25 +73,25 @@ func LoadEnv() {
|
|||||||
DebugEnabled = os.Getenv("DEBUG") == "true"
|
DebugEnabled = os.Getenv("DEBUG") == "true"
|
||||||
MemoryCacheEnabled = os.Getenv("MEMORY_CACHE_ENABLED") == "true"
|
MemoryCacheEnabled = os.Getenv("MEMORY_CACHE_ENABLED") == "true"
|
||||||
IsMasterNode = os.Getenv("NODE_TYPE") != "slave"
|
IsMasterNode = os.Getenv("NODE_TYPE") != "slave"
|
||||||
|
|
||||||
// Parse requestInterval and set RequestInterval
|
// Parse requestInterval and set RequestInterval
|
||||||
requestInterval, _ = strconv.Atoi(os.Getenv("POLLING_INTERVAL"))
|
requestInterval, _ = strconv.Atoi(os.Getenv("POLLING_INTERVAL"))
|
||||||
RequestInterval = time.Duration(requestInterval) * time.Second
|
RequestInterval = time.Duration(requestInterval) * time.Second
|
||||||
|
|
||||||
// Initialize variables with GetEnvOrDefault
|
// Initialize variables with GetEnvOrDefault
|
||||||
SyncFrequency = GetEnvOrDefault("SYNC_FREQUENCY", 60)
|
SyncFrequency = GetEnvOrDefault("SYNC_FREQUENCY", 60)
|
||||||
BatchUpdateInterval = GetEnvOrDefault("BATCH_UPDATE_INTERVAL", 5)
|
BatchUpdateInterval = GetEnvOrDefault("BATCH_UPDATE_INTERVAL", 5)
|
||||||
RelayTimeout = GetEnvOrDefault("RELAY_TIMEOUT", 0)
|
RelayTimeout = GetEnvOrDefault("RELAY_TIMEOUT", 0)
|
||||||
|
|
||||||
// Initialize string variables with GetEnvOrDefaultString
|
// Initialize string variables with GetEnvOrDefaultString
|
||||||
GeminiSafetySetting = GetEnvOrDefaultString("GEMINI_SAFETY_SETTING", "BLOCK_NONE")
|
GeminiSafetySetting = GetEnvOrDefaultString("GEMINI_SAFETY_SETTING", "BLOCK_NONE")
|
||||||
CohereSafetySetting = GetEnvOrDefaultString("COHERE_SAFETY_SETTING", "NONE")
|
CohereSafetySetting = GetEnvOrDefaultString("COHERE_SAFETY_SETTING", "NONE")
|
||||||
|
|
||||||
// Initialize rate limit variables
|
// Initialize rate limit variables
|
||||||
GlobalApiRateLimitEnable = GetEnvOrDefaultBool("GLOBAL_API_RATE_LIMIT_ENABLE", true)
|
GlobalApiRateLimitEnable = GetEnvOrDefaultBool("GLOBAL_API_RATE_LIMIT_ENABLE", true)
|
||||||
GlobalApiRateLimitNum = GetEnvOrDefault("GLOBAL_API_RATE_LIMIT", 180)
|
GlobalApiRateLimitNum = GetEnvOrDefault("GLOBAL_API_RATE_LIMIT", 180)
|
||||||
GlobalApiRateLimitDuration = int64(GetEnvOrDefault("GLOBAL_API_RATE_LIMIT_DURATION", 180))
|
GlobalApiRateLimitDuration = int64(GetEnvOrDefault("GLOBAL_API_RATE_LIMIT_DURATION", 180))
|
||||||
|
|
||||||
GlobalWebRateLimitEnable = GetEnvOrDefaultBool("GLOBAL_WEB_RATE_LIMIT_ENABLE", true)
|
GlobalWebRateLimitEnable = GetEnvOrDefaultBool("GLOBAL_WEB_RATE_LIMIT_ENABLE", true)
|
||||||
GlobalWebRateLimitNum = GetEnvOrDefault("GLOBAL_WEB_RATE_LIMIT", 60)
|
GlobalWebRateLimitNum = GetEnvOrDefault("GLOBAL_WEB_RATE_LIMIT", 60)
|
||||||
GlobalWebRateLimitDuration = int64(GetEnvOrDefault("GLOBAL_WEB_RATE_LIMIT_DURATION", 180))
|
GlobalWebRateLimitDuration = int64(GetEnvOrDefault("GLOBAL_WEB_RATE_LIMIT_DURATION", 180))
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ type MediaContent struct {
|
|||||||
Text string `json:"text,omitempty"`
|
Text string `json:"text,omitempty"`
|
||||||
ImageUrl any `json:"image_url,omitempty"`
|
ImageUrl any `json:"image_url,omitempty"`
|
||||||
InputAudio any `json:"input_audio,omitempty"`
|
InputAudio any `json:"input_audio,omitempty"`
|
||||||
|
File any `json:"file,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MediaContent) GetImageMedia() *MessageImageUrl {
|
func (m *MediaContent) GetImageMedia() *MessageImageUrl {
|
||||||
@@ -120,6 +121,20 @@ func (m *MediaContent) GetImageMedia() *MessageImageUrl {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MediaContent) GetInputAudio() *MessageInputAudio {
|
||||||
|
if m.InputAudio != nil {
|
||||||
|
return m.InputAudio.(*MessageInputAudio)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MediaContent) GetFile() *MessageFile {
|
||||||
|
if m.File != nil {
|
||||||
|
return m.File.(*MessageFile)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type MessageImageUrl struct {
|
type MessageImageUrl struct {
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
Detail string `json:"detail"`
|
Detail string `json:"detail"`
|
||||||
@@ -135,10 +150,17 @@ type MessageInputAudio struct {
|
|||||||
Format string `json:"format"`
|
Format string `json:"format"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MessageFile struct {
|
||||||
|
FileName string `json:"filename,omitempty"`
|
||||||
|
FileData string `json:"file_data,omitempty"`
|
||||||
|
FileId string `json:"file_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ContentTypeText = "text"
|
ContentTypeText = "text"
|
||||||
ContentTypeImageURL = "image_url"
|
ContentTypeImageURL = "image_url"
|
||||||
ContentTypeInputAudio = "input_audio"
|
ContentTypeInputAudio = "input_audio"
|
||||||
|
ContentTypeFile = "file"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Message) GetPrefix() bool {
|
func (m *Message) GetPrefix() bool {
|
||||||
@@ -292,6 +314,30 @@ func (m *Message) ParseContent() []MediaContent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case ContentTypeFile:
|
||||||
|
if fileData, ok := contentItem["file"].(map[string]interface{}); ok {
|
||||||
|
fileId, ok3 := fileData["file_id"].(string)
|
||||||
|
if ok3 {
|
||||||
|
contentList = append(contentList, MediaContent{
|
||||||
|
Type: ContentTypeFile,
|
||||||
|
File: &MessageFile{
|
||||||
|
FileId: fileId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
fileName, ok1 := fileData["filename"].(string)
|
||||||
|
fileDataStr, ok2 := fileData["file_data"].(string)
|
||||||
|
if ok1 && ok2 {
|
||||||
|
contentList = append(contentList, MediaContent{
|
||||||
|
Type: ContentTypeFile,
|
||||||
|
File: &MessageFile{
|
||||||
|
FileName: fileName,
|
||||||
|
FileData: fileDataStr,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -34,7 +34,7 @@ var indexPage []byte
|
|||||||
func main() {
|
func main() {
|
||||||
err := godotenv.Load(".env")
|
err := godotenv.Load(".env")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SysLog("Support for .env file is disabled")
|
common.SysLog("Support for .env file is disabled: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
common.LoadEnv()
|
common.LoadEnv()
|
||||||
|
|||||||
@@ -208,6 +208,34 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) (*GeminiChatReque
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} else if part.Type == dto.ContentTypeFile {
|
||||||
|
if part.GetFile().FileId != "" {
|
||||||
|
return nil, fmt.Errorf("only base64 file is supported in gemini")
|
||||||
|
}
|
||||||
|
format, base64String, err := service.DecodeBase64FileData(part.GetFile().FileData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode base64 file data failed: %s", err.Error())
|
||||||
|
}
|
||||||
|
parts = append(parts, GeminiPart{
|
||||||
|
InlineData: &GeminiInlineData{
|
||||||
|
MimeType: format,
|
||||||
|
Data: base64String,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if part.Type == dto.ContentTypeInputAudio {
|
||||||
|
if part.GetInputAudio().Data == "" {
|
||||||
|
return nil, fmt.Errorf("only base64 audio is supported in gemini")
|
||||||
|
}
|
||||||
|
format, base64String, err := service.DecodeBase64FileData(part.GetInputAudio().Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode base64 audio data failed: %s", err.Error())
|
||||||
|
}
|
||||||
|
parts = append(parts, GeminiPart{
|
||||||
|
InlineData: &GeminiInlineData{
|
||||||
|
MimeType: format,
|
||||||
|
Data: base64String,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +261,6 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) (*GeminiChatReque
|
|||||||
return &geminiRequest, nil
|
return &geminiRequest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// cleanFunctionParameters recursively removes unsupported fields from Gemini function parameters.
|
// cleanFunctionParameters recursively removes unsupported fields from Gemini function parameters.
|
||||||
func cleanFunctionParameters(params interface{}) interface{} {
|
func cleanFunctionParameters(params interface{}) interface{} {
|
||||||
if params == nil {
|
if params == nil {
|
||||||
@@ -307,7 +334,6 @@ func cleanFunctionParameters(params interface{}) interface{} {
|
|||||||
cleanedMap["items"] = cleanedItemsArray
|
cleanedMap["items"] = cleanedItemsArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Recursively clean other schema composition keywords if necessary
|
// Recursively clean other schema composition keywords if necessary
|
||||||
for _, field := range []string{"allOf", "anyOf", "oneOf"} {
|
for _, field := range []string{"allOf", "anyOf", "oneOf"} {
|
||||||
if nested, ok := cleanedMap[field].([]interface{}); ok {
|
if nested, ok := cleanedMap[field].([]interface{}); ok {
|
||||||
@@ -322,7 +348,6 @@ func cleanFunctionParameters(params interface{}) interface{} {
|
|||||||
return cleanedMap
|
return cleanedMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func removeAdditionalPropertiesWithDepth(schema interface{}, depth int) interface{} {
|
func removeAdditionalPropertiesWithDepth(schema interface{}, depth int) interface{} {
|
||||||
if depth >= 5 {
|
if depth >= 5 {
|
||||||
return schema
|
return schema
|
||||||
|
|||||||
@@ -398,6 +398,8 @@ func CountTokenMessages(info *relaycommon.RelayInfo, messages []dto.Message, mod
|
|||||||
} else if m.Type == dto.ContentTypeInputAudio {
|
} else if m.Type == dto.ContentTypeInputAudio {
|
||||||
// TODO: 音频token数量计算
|
// TODO: 音频token数量计算
|
||||||
tokenNum += 100
|
tokenNum += 100
|
||||||
|
} else if m.Type == dto.ContentTypeFile {
|
||||||
|
tokenNum += 5000
|
||||||
} else {
|
} else {
|
||||||
tokenNum += getTokenNum(tokenEncoder, m.Text)
|
tokenNum += getTokenNum(tokenEncoder, m.Text)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user