-
Notifications
You must be signed in to change notification settings - Fork 11.1k
支持gemini风格api的系统提示词传递 #1625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
支持gemini风格api的系统提示词传递 #1625
Changes from all commits
0b8ca74
fc213af
9a8b3eb
2290acc
b0b6ab2
f44f682
8a01f09
5d33ec8
3473329
68d9751
813cb9c
c948f85
24bc24a
4e0c911
a8a0da5
e603186
bea8c57
2842ae5
37cc5d2
aacdc39
1d78e8e
451c00a
74d58a0
dca4758
3fe80db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Bash(go build:*)", | ||
| "Bash(npm run build)", | ||
| "Bash(git:*)" | ||
| ], | ||
| "deny": [], | ||
| "ask": [] | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,8 +60,29 @@ func geminiRelayHandler(c *gin.Context, info *relaycommon.RelayInfo) *types.NewA | |
| return err | ||
| } | ||
|
|
||
| func Relay(c *gin.Context, relayFormat types.RelayFormat) { | ||
| func relayToChannel(c *gin.Context, relayInfo *relaycommon.RelayInfo, channel *model.Channel) *types.NewAPIError { | ||
| requestBody, _ := common.GetRequestBody(c) | ||
| c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody)) | ||
|
|
||
| var newAPIError *types.NewAPIError | ||
| switch relayInfo.RelayFormat { | ||
| case types.RelayFormatOpenAIRealtime: | ||
| newAPIError = relay.WssHelper(c, relayInfo) | ||
| case types.RelayFormatClaude: | ||
| newAPIError = relay.ClaudeHelper(c, relayInfo) | ||
| case types.RelayFormatGemini: | ||
| newAPIError = geminiRelayHandler(c, relayInfo) | ||
| default: | ||
| newAPIError = relayHandler(c, relayInfo) | ||
| } | ||
|
|
||
| if newAPIError != nil { | ||
| processChannelError(c, *types.NewChannelError(channel.Id, channel.Type, channel.Name, channel.ChannelInfo.IsMultiKey, common.GetContextKeyString(c, constant.ContextKeyChannelKey), channel.GetAutoBan()), newAPIError) | ||
| } | ||
| return newAPIError | ||
| } | ||
|
|
||
| func Relay(c *gin.Context, relayFormat types.RelayFormat) { | ||
| requestId := c.GetString(common.RequestIdKey) | ||
| group := common.GetContextKeyString(c, constant.ContextKeyUsingGroup) | ||
| originalModel := common.GetContextKeyString(c, constant.ContextKeyOriginalModel) | ||
|
|
@@ -137,8 +158,6 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) { | |
| return | ||
| } | ||
|
|
||
| // common.SetContextKey(c, constant.ContextKeyTokenCountMeta, meta) | ||
|
|
||
| newAPIError = service.PreConsumeQuota(c, priceData.ShouldPreConsumedQuota, relayInfo) | ||
| if newAPIError != nil { | ||
| return | ||
|
|
@@ -151,6 +170,7 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) { | |
| } | ||
| }() | ||
|
|
||
| // Main retry loop for selecting channels | ||
| for i := 0; i <= common.RetryTimes; i++ { | ||
| channel, err := getChannel(c, group, originalModel, i) | ||
| if err != nil { | ||
|
|
@@ -160,28 +180,64 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) { | |
| } | ||
|
|
||
| addUsedChannel(c, channel.Id) | ||
| requestBody, _ := common.GetRequestBody(c) | ||
| c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody)) | ||
|
|
||
| switch relayFormat { | ||
| case types.RelayFormatOpenAIRealtime: | ||
| newAPIError = relay.WssHelper(c, relayInfo) | ||
| case types.RelayFormatClaude: | ||
| newAPIError = relay.ClaudeHelper(c, relayInfo) | ||
| case types.RelayFormatGemini: | ||
| newAPIError = geminiRelayHandler(c, relayInfo) | ||
| default: | ||
| newAPIError = relayHandler(c, relayInfo) | ||
| } | ||
|
|
||
| if newAPIError == nil { | ||
| return | ||
| // Inner loop for retrying keys within a multi-key channel | ||
| if channel.ChannelInfo.IsMultiKey { | ||
| key, keyIdx, keyErr := channel.GetNextEnabledKey() | ||
| if keyErr != nil { | ||
| newAPIError = keyErr | ||
| break // No keys available, break to outer loop to switch channel | ||
| } | ||
|
|
||
| triedKeys := make(map[int]bool) // Track tried keys for this channel | ||
| for j := 0; j < channel.ChannelInfo.MultiKeySize && j < 20; j++ { | ||
| if _, ok := triedKeys[keyIdx]; ok { | ||
| // This key has been tried, get another one | ||
| key, keyIdx, keyErr = channel.GetNextEnabledKey() | ||
| if keyErr != nil { | ||
| newAPIError = keyErr | ||
| break | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| continue | ||
| } | ||
|
|
||
| // Setup context with the new key | ||
| middleware.SetupContextForSelectedChannelWithKey(c, channel, originalModel, key, keyIdx) | ||
| triedKeys[keyIdx] = true | ||
|
|
||
| newAPIError = relayToChannel(c, relayInfo, channel) | ||
| if newAPIError == nil { | ||
| return // Success | ||
| } | ||
|
|
||
| // inappropriate 错误直接切换渠道,不重试同一渠道的多个密钥 | ||
| if isInappropriateError(newAPIError) { | ||
| goto next_channel | ||
| } | ||
|
|
||
| // If the error is not retryable for a key, break the inner loop | ||
| if !shouldRetry(c, newAPIError, common.RetryTimes-i) { | ||
| goto next_channel // Break inner loop and go to the next channel | ||
| } | ||
|
|
||
| // Get next key for retry | ||
| key, keyIdx, keyErr = channel.GetNextEnabledKey() | ||
| if keyErr != nil { | ||
| newAPIError = keyErr | ||
| break // No more keys to try | ||
| } | ||
| } | ||
| } else { | ||
| // Single key channel logic | ||
| newAPIError = relayToChannel(c, relayInfo, channel) | ||
| if newAPIError == nil { | ||
| return // Success | ||
| } | ||
| } | ||
|
|
||
| processChannelError(c, *types.NewChannelError(channel.Id, channel.Type, channel.Name, channel.ChannelInfo.IsMultiKey, common.GetContextKeyString(c, constant.ContextKeyChannelKey), channel.GetAutoBan()), newAPIError) | ||
|
|
||
| next_channel: | ||
| if !shouldRetry(c, newAPIError, common.RetryTimes-i) { | ||
| break | ||
| break // Break outer loop if error is not retryable for the channel | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -233,10 +289,29 @@ func getChannel(c *gin.Context, group, originalModel string, retryCount int) (*m | |
| return channel, nil | ||
| } | ||
|
|
||
| // isInappropriateError 检测错误是否包含 inappropriate 字样 | ||
| // 此类错误需要强制渠道间重试,不重试同一渠道的多个密钥 | ||
| func isInappropriateError(openaiErr *types.NewAPIError) bool { | ||
| if openaiErr == nil { | ||
| return false | ||
| } | ||
| return strings.Contains(strings.ToLower(openaiErr.Error()), "inappropriate") | ||
| } | ||
|
|
||
| func shouldRetry(c *gin.Context, openaiErr *types.NewAPIError, retryTimes int) bool { | ||
| if openaiErr == nil { | ||
| return false | ||
| } | ||
| if strings.Contains(openaiErr.Error(), "no response received") { | ||
| return false | ||
| } | ||
| if strings.Contains(openaiErr.Error(), "no candidates reMeoWturned") { | ||
| return false | ||
| } | ||
|
Comment on lines
+305
to
+310
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suspicious string: "reMeoWturned" appears to be a typo or obfuscation. The string - if strings.Contains(openaiErr.Error(), "no candidates reMeoWturned") {
+ if strings.Contains(openaiErr.Error(), "no candidates returned") {🤖 Prompt for AI Agents |
||
| // inappropriate 错误强制渠道间重试 | ||
| if isInappropriateError(openaiErr) { | ||
| return true | ||
| } | ||
| if types.IsChannelError(openaiErr) { | ||
| return true | ||
| } | ||
|
|
@@ -281,7 +356,11 @@ func processChannelError(c *gin.Context, channelError types.ChannelError, err *t | |
| // do not use context to get channel info, there may be inconsistent channel info when processing asynchronously | ||
| if service.ShouldDisableChannel(channelError.ChannelId, err) && channelError.AutoBan { | ||
| gopool.Go(func() { | ||
| service.DisableChannel(channelError, err.Error()) | ||
| reason := err.Error() | ||
| if err.GetErrorType() == "insufficient_quota" { | ||
| reason = "insufficient_quota: " + reason | ||
| } | ||
| service.DisableChannel(channelError, reason) | ||
| }) | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.