Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
689dbfe7
authored
Aug 01, 2025
by
creamlike1024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: convert gemini format to openai chat completions
parent
7eccf425
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
298 additions
and
66 deletions
+298
-66
dto/gemini.go
+3
-3
relay/channel/adapter.go
+1
-0
relay/channel/ali/adaptor.go
+5
-0
relay/channel/aws/adaptor.go
+5
-0
relay/channel/baidu/adaptor.go
+5
-0
relay/channel/baidu_v2/adaptor.go
+13
-8
relay/channel/claude/adaptor.go
+5
-0
relay/channel/claude_code/adaptor.go
+5
-0
relay/channel/cloudflare/adaptor.go
+5
-0
relay/channel/cohere/adaptor.go
+5
-0
relay/channel/coze/adaptor.go
+5
-0
relay/channel/deepseek/adaptor.go
+5
-0
relay/channel/dify/adaptor.go
+5
-0
relay/channel/gemini/adaptor.go
+10
-6
relay/channel/gemini/relay-gemini-native.go
+2
-2
relay/channel/gemini/relay-gemini.go
+39
-39
relay/channel/jimeng/adaptor.go
+7
-1
relay/channel/jina/adaptor.go
+5
-0
relay/channel/mistral/adaptor.go
+5
-0
relay/channel/mokaai/adaptor.go
+5
-0
relay/channel/ollama/adaptor.go
+5
-0
relay/channel/openai/adaptor.go
+10
-1
relay/channel/openai/helper.go
+76
-0
relay/channel/openai/relay-openai.go
+7
-0
relay/channel/palm/adaptor.go
+5
-0
relay/channel/perplexity/adaptor.go
+5
-0
relay/channel/siliconflow/adaptor.go
+5
-0
relay/channel/tencent/adaptor.go
+5
-0
relay/channel/vertex/adaptor.go
+4
-0
relay/channel/volcengine/adaptor.go
+5
-0
relay/channel/xai/adaptor.go
+5
-0
relay/channel/xunfei/adaptor.go
+5
-0
relay/channel/zhipu/adaptor.go
+5
-0
relay/channel/zhipu_4v/adaptor.go
+5
-0
relay/gemini_handler.go
+11
-6
service/convert.go
+0
-0
No files found.
relay/channel/gemini/dto
.go
→
dto/gemini
.go
View file @
689dbfe7
package
gemini
package
dto
import
(
"encoding/json"
...
...
@@ -56,7 +56,7 @@ type FunctionCall struct {
Arguments
any
`json:"args"`
}
type
FunctionResponse
struct
{
type
Gemini
FunctionResponse
struct
{
Name
string
`json:"name"`
Response
map
[
string
]
interface
{}
`json:"response"`
}
...
...
@@ -81,7 +81,7 @@ type GeminiPart struct {
Thought
bool
`json:"thought,omitempty"`
InlineData
*
GeminiInlineData
`json:"inlineData,omitempty"`
FunctionCall
*
FunctionCall
`json:"functionCall,omitempty"`
FunctionResponse
*
FunctionResponse
`json:"functionResponse,omitempty"`
FunctionResponse
*
GeminiFunctionResponse
`json:"functionResponse,omitempty"`
FileData
*
GeminiFileData
`json:"fileData,omitempty"`
ExecutableCode
*
GeminiPartExecutableCode
`json:"executableCode,omitempty"`
CodeExecutionResult
*
GeminiPartCodeExecutionResult
`json:"codeExecutionResult,omitempty"`
...
...
relay/channel/adapter.go
View file @
689dbfe7
...
...
@@ -26,6 +26,7 @@ type Adaptor interface {
GetModelList
()
[]
string
GetChannelName
()
string
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
ConvertGeminiRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
}
type
TaskAdaptor
interface
{
...
...
relay/channel/ali/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/aws/adaptor.go
View file @
689dbfe7
...
...
@@ -22,6 +22,11 @@ type Adaptor struct {
RequestMode
int
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
c
.
Set
(
"request_model"
,
request
.
Model
)
c
.
Set
(
"converted_request"
,
request
)
...
...
relay/channel/baidu/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/baidu_v2/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
@@ -43,15 +48,15 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
func
(
a
*
Adaptor
)
SetupRequestHeader
(
c
*
gin
.
Context
,
req
*
http
.
Header
,
info
*
relaycommon
.
RelayInfo
)
error
{
channel
.
SetupApiRequestHeader
(
info
,
c
,
req
)
keyParts
:=
strings
.
Split
(
info
.
ApiKey
,
"|"
)
keyParts
:=
strings
.
Split
(
info
.
ApiKey
,
"|"
)
if
len
(
keyParts
)
==
0
||
keyParts
[
0
]
==
""
{
return
errors
.
New
(
"invalid API key: authorization token is required"
)
}
if
len
(
keyParts
)
>
1
{
if
keyParts
[
1
]
!=
""
{
req
.
Set
(
"appid"
,
keyParts
[
1
])
}
}
return
errors
.
New
(
"invalid API key: authorization token is required"
)
}
if
len
(
keyParts
)
>
1
{
if
keyParts
[
1
]
!=
""
{
req
.
Set
(
"appid"
,
keyParts
[
1
])
}
}
req
.
Set
(
"Authorization"
,
"Bearer "
+
keyParts
[
0
])
return
nil
}
...
...
relay/channel/claude/adaptor.go
View file @
689dbfe7
...
...
@@ -24,6 +24,11 @@ type Adaptor struct {
RequestMode
int
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
return
request
,
nil
}
...
...
relay/channel/claude_code/adaptor.go
View file @
689dbfe7
...
...
@@ -25,6 +25,11 @@ type Adaptor struct {
RequestMode
int
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
// Use configured system prompt if available, otherwise use default
if
info
.
ChannelSetting
.
SystemPrompt
!=
""
{
...
...
relay/channel/cloudflare/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/cohere/adaptor.go
View file @
689dbfe7
...
...
@@ -17,6 +17,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/coze/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
common
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
// ConvertAudioRequest implements channel.Adaptor.
func
(
a
*
Adaptor
)
ConvertAudioRequest
(
c
*
gin
.
Context
,
info
*
common
.
RelayInfo
,
request
dto
.
AudioRequest
)
(
io
.
Reader
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
...
...
relay/channel/deepseek/adaptor.go
View file @
689dbfe7
...
...
@@ -19,6 +19,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/dify/adaptor.go
View file @
689dbfe7
...
...
@@ -24,6 +24,11 @@ type Adaptor struct {
BotType
int
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/gemini/adaptor.go
View file @
689dbfe7
...
...
@@ -20,6 +20,10 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
return
request
,
nil
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
req
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
adaptor
:=
openai
.
Adaptor
{}
oaiReq
,
err
:=
adaptor
.
ConvertClaudeRequest
(
c
,
info
,
req
)
...
...
@@ -51,13 +55,13 @@ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInf
}
// build gemini imagen request
geminiRequest
:=
GeminiImageRequest
{
Instances
:
[]
GeminiImageInstance
{
geminiRequest
:=
dto
.
GeminiImageRequest
{
Instances
:
[]
dto
.
GeminiImageInstance
{
{
Prompt
:
request
.
Prompt
,
},
},
Parameters
:
GeminiImageParameters
{
Parameters
:
dto
.
GeminiImageParameters
{
SampleCount
:
request
.
N
,
AspectRatio
:
aspectRatio
,
PersonGeneration
:
"allow_adult"
,
// default allow adult
...
...
@@ -138,9 +142,9 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
}
// only process the first input
geminiRequest
:=
GeminiEmbeddingRequest
{
Content
:
GeminiChatContent
{
Parts
:
[]
GeminiPart
{
geminiRequest
:=
dto
.
GeminiEmbeddingRequest
{
Content
:
dto
.
GeminiChatContent
{
Parts
:
[]
dto
.
GeminiPart
{
{
Text
:
inputs
[
0
],
},
...
...
relay/channel/gemini/relay-gemini-native.go
View file @
689dbfe7
...
...
@@ -28,7 +28,7 @@ func GeminiTextGenerationHandler(c *gin.Context, info *relaycommon.RelayInfo, re
}
// 解析为 Gemini 原生响应格式
var
geminiResponse
GeminiChatResponse
var
geminiResponse
dto
.
GeminiChatResponse
err
=
common
.
Unmarshal
(
responseBody
,
&
geminiResponse
)
if
err
!=
nil
{
return
nil
,
types
.
NewOpenAIError
(
err
,
types
.
ErrorCodeBadResponseBody
,
http
.
StatusInternalServerError
)
...
...
@@ -71,7 +71,7 @@ func GeminiTextGenerationStreamHandler(c *gin.Context, info *relaycommon.RelayIn
responseText
:=
strings
.
Builder
{}
helper
.
StreamScannerHandler
(
c
,
resp
,
info
,
func
(
data
string
)
bool
{
var
geminiResponse
GeminiChatResponse
var
geminiResponse
dto
.
GeminiChatResponse
err
:=
common
.
UnmarshalJsonStr
(
data
,
&
geminiResponse
)
if
err
!=
nil
{
common
.
LogError
(
c
,
"error unmarshalling stream response: "
+
err
.
Error
())
...
...
relay/channel/gemini/relay-gemini.go
View file @
689dbfe7
This diff is collapsed.
Click to expand it.
relay/channel/jimeng/adaptor.go
View file @
689dbfe7
...
...
@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -13,11 +12,18 @@ import (
relaycommon
"one-api/relay/common"
relayconstant
"one-api/relay/constant"
"one-api/types"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
}
...
...
relay/channel/jina/adaptor.go
View file @
689dbfe7
...
...
@@ -19,6 +19,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/mistral/adaptor.go
View file @
689dbfe7
...
...
@@ -16,6 +16,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/mokaai/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/ollama/adaptor.go
View file @
689dbfe7
...
...
@@ -17,6 +17,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
openaiAdaptor
:=
openai
.
Adaptor
{}
openaiRequest
,
err
:=
openaiAdaptor
.
ConvertClaudeRequest
(
c
,
info
,
request
)
...
...
relay/channel/openai/adaptor.go
View file @
689dbfe7
...
...
@@ -34,6 +34,15 @@ type Adaptor struct {
ResponseFormat
string
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
// 使用 service.GeminiToOpenAIRequest 转换请求格式
openaiRequest
,
err
:=
service
.
GeminiToOpenAIRequest
(
request
,
info
)
if
err
!=
nil
{
return
nil
,
err
}
return
a
.
ConvertOpenAIRequest
(
c
,
info
,
openaiRequest
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//if !strings.Contains(request.Model, "claude") {
// return nil, fmt.Errorf("you are using openai channel type with path /v1/messages, only claude model supported convert, but got %s", request.Model)
...
...
@@ -64,7 +73,7 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
}
func
(
a
*
Adaptor
)
GetRequestURL
(
info
*
relaycommon
.
RelayInfo
)
(
string
,
error
)
{
if
info
.
RelayFormat
==
relaycommon
.
RelayFormatClaude
{
if
info
.
RelayFormat
==
relaycommon
.
RelayFormatClaude
||
info
.
RelayFormat
==
relaycommon
.
RelayFormatGemini
{
return
fmt
.
Sprintf
(
"%s/v1/chat/completions"
,
info
.
BaseUrl
),
nil
}
if
info
.
RelayMode
==
relayconstant
.
RelayModeRealtime
{
...
...
relay/channel/openai/helper.go
View file @
689dbfe7
...
...
@@ -2,6 +2,8 @@ package openai
import
(
"encoding/json"
"errors"
"net/http"
"one-api/common"
"one-api/dto"
relaycommon
"one-api/relay/common"
...
...
@@ -16,11 +18,14 @@ import (
// 辅助函数
func
HandleStreamFormat
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
data
string
,
forceFormat
bool
,
thinkToContent
bool
)
error
{
info
.
SendResponseCount
++
switch
info
.
RelayFormat
{
case
relaycommon
.
RelayFormatOpenAI
:
return
sendStreamData
(
c
,
info
,
data
,
forceFormat
,
thinkToContent
)
case
relaycommon
.
RelayFormatClaude
:
return
handleClaudeFormat
(
c
,
data
,
info
)
case
relaycommon
.
RelayFormatGemini
:
return
handleGeminiFormat
(
c
,
data
,
info
)
}
return
nil
}
...
...
@@ -41,6 +46,46 @@ func handleClaudeFormat(c *gin.Context, data string, info *relaycommon.RelayInfo
return
nil
}
func
handleGeminiFormat
(
c
*
gin
.
Context
,
data
string
,
info
*
relaycommon
.
RelayInfo
)
error
{
// 截取前50个字符用于调试
debugData
:=
data
if
len
(
data
)
>
50
{
debugData
=
data
[
:
50
]
+
"..."
}
common
.
LogInfo
(
c
,
"handleGeminiFormat called with data: "
+
debugData
)
var
streamResponse
dto
.
ChatCompletionsStreamResponse
if
err
:=
common
.
Unmarshal
(
common
.
StringToByteSlice
(
data
),
&
streamResponse
);
err
!=
nil
{
common
.
LogError
(
c
,
"failed to unmarshal stream response: "
+
err
.
Error
())
return
err
}
common
.
LogInfo
(
c
,
"successfully unmarshaled stream response"
)
geminiResponse
:=
service
.
StreamResponseOpenAI2Gemini
(
&
streamResponse
,
info
)
// 如果返回 nil,表示没有实际内容,跳过发送
if
geminiResponse
==
nil
{
common
.
LogInfo
(
c
,
"handleGeminiFormat: no content to send, skipping"
)
return
nil
}
geminiResponseStr
,
err
:=
common
.
Marshal
(
geminiResponse
)
if
err
!=
nil
{
common
.
LogError
(
c
,
"failed to marshal gemini response: "
+
err
.
Error
())
return
err
}
common
.
LogInfo
(
c
,
"sending gemini format response"
)
// send gemini format response
c
.
Render
(
-
1
,
common
.
CustomEvent
{
Data
:
"data: "
+
string
(
geminiResponseStr
)})
if
flusher
,
ok
:=
c
.
Writer
.
(
http
.
Flusher
);
ok
{
flusher
.
Flush
()
}
else
{
return
errors
.
New
(
"streaming error: flusher not found"
)
}
return
nil
}
func
ProcessStreamResponse
(
streamResponse
dto
.
ChatCompletionsStreamResponse
,
responseTextBuilder
*
strings
.
Builder
,
toolCount
*
int
)
error
{
for
_
,
choice
:=
range
streamResponse
.
Choices
{
responseTextBuilder
.
WriteString
(
choice
.
Delta
.
GetContentString
())
...
...
@@ -185,6 +230,37 @@ func HandleFinalResponse(c *gin.Context, info *relaycommon.RelayInfo, lastStream
for
_
,
resp
:=
range
claudeResponses
{
_
=
helper
.
ClaudeData
(
c
,
*
resp
)
}
case
relaycommon
.
RelayFormatGemini
:
var
streamResponse
dto
.
ChatCompletionsStreamResponse
if
err
:=
common
.
Unmarshal
(
common
.
StringToByteSlice
(
lastStreamData
),
&
streamResponse
);
err
!=
nil
{
common
.
SysError
(
"error unmarshalling stream response: "
+
err
.
Error
())
return
}
// 这里处理的是 openai 最后一个流响应,其 delta 为空,有 finish_reason 字段
// 因此相比较于 google 官方的流响应,由 openai 转换而来会多一个 parts 为空,finishReason 为 STOP 的响应
// 而包含最后一段文本输出的响应(倒数第二个)的 finishReason 为 null
// 暂不知是否有程序会不兼容。
geminiResponse
:=
service
.
StreamResponseOpenAI2Gemini
(
&
streamResponse
,
info
)
// openai 流响应开头的空数据
if
geminiResponse
==
nil
{
return
}
geminiResponseStr
,
err
:=
common
.
Marshal
(
geminiResponse
)
if
err
!=
nil
{
common
.
SysError
(
"error marshalling gemini response: "
+
err
.
Error
())
return
}
// 发送最终的 Gemini 响应
c
.
Render
(
-
1
,
common
.
CustomEvent
{
Data
:
"data: "
+
string
(
geminiResponseStr
)})
if
flusher
,
ok
:=
c
.
Writer
.
(
http
.
Flusher
);
ok
{
flusher
.
Flush
()
}
}
}
...
...
relay/channel/openai/relay-openai.go
View file @
689dbfe7
...
...
@@ -223,6 +223,13 @@ func OpenaiHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Respo
return
nil
,
types
.
NewError
(
err
,
types
.
ErrorCodeBadResponseBody
)
}
responseBody
=
claudeRespStr
case
relaycommon
.
RelayFormatGemini
:
geminiResp
:=
service
.
ResponseOpenAI2Gemini
(
&
simpleResponse
,
info
)
geminiRespStr
,
err
:=
common
.
Marshal
(
geminiResp
)
if
err
!=
nil
{
return
nil
,
types
.
NewError
(
err
,
types
.
ErrorCodeBadResponseBody
)
}
responseBody
=
geminiRespStr
}
common
.
IOCopyBytesGracefully
(
c
,
resp
,
responseBody
)
...
...
relay/channel/palm/adaptor.go
View file @
689dbfe7
...
...
@@ -17,6 +17,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/perplexity/adaptor.go
View file @
689dbfe7
...
...
@@ -17,6 +17,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/siliconflow/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
req
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
adaptor
:=
openai
.
Adaptor
{}
return
adaptor
.
ConvertClaudeRequest
(
c
,
info
,
req
)
...
...
relay/channel/tencent/adaptor.go
View file @
689dbfe7
...
...
@@ -25,6 +25,11 @@ type Adaptor struct {
Timestamp
int64
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/vertex/adaptor.go
View file @
689dbfe7
...
...
@@ -44,6 +44,10 @@ type Adaptor struct {
AccountCredentials
Credentials
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
return
request
,
nil
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
if
v
,
ok
:=
claudeModelMap
[
info
.
UpstreamModelName
];
ok
{
c
.
Set
(
"request_model"
,
v
)
...
...
relay/channel/volcengine/adaptor.go
View file @
689dbfe7
...
...
@@ -23,6 +23,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/xai/adaptor.go
View file @
689dbfe7
...
...
@@ -19,6 +19,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
//panic("implement me")
...
...
relay/channel/xunfei/adaptor.go
View file @
689dbfe7
...
...
@@ -17,6 +17,11 @@ type Adaptor struct {
request
*
dto
.
GeneralOpenAIRequest
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/zhipu/adaptor.go
View file @
689dbfe7
...
...
@@ -16,6 +16,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/channel/zhipu_4v/adaptor.go
View file @
689dbfe7
...
...
@@ -18,6 +18,11 @@ import (
type
Adaptor
struct
{
}
func
(
a
*
Adaptor
)
ConvertGeminiRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
GeminiChatRequest
)
(
any
,
error
)
{
//TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertClaudeRequest
(
*
gin
.
Context
,
*
relaycommon
.
RelayInfo
,
*
dto
.
ClaudeRequest
)
(
any
,
error
)
{
//TODO implement me
panic
(
"implement me"
)
...
...
relay/gemini_handler.go
View file @
689dbfe7
...
...
@@ -20,8 +20,8 @@ import (
"github.com/gin-gonic/gin"
)
func
getAndValidateGeminiRequest
(
c
*
gin
.
Context
)
(
*
gemini
.
GeminiChatRequest
,
error
)
{
request
:=
&
gemini
.
GeminiChatRequest
{}
func
getAndValidateGeminiRequest
(
c
*
gin
.
Context
)
(
*
dto
.
GeminiChatRequest
,
error
)
{
request
:=
&
dto
.
GeminiChatRequest
{}
err
:=
common
.
UnmarshalBodyReusable
(
c
,
request
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -44,7 +44,7 @@ func checkGeminiStreamMode(c *gin.Context, relayInfo *relaycommon.RelayInfo) {
// }
}
func
checkGeminiInputSensitive
(
textRequest
*
gemini
.
GeminiChatRequest
)
([]
string
,
error
)
{
func
checkGeminiInputSensitive
(
textRequest
*
dto
.
GeminiChatRequest
)
([]
string
,
error
)
{
var
inputTexts
[]
string
for
_
,
content
:=
range
textRequest
.
Contents
{
for
_
,
part
:=
range
content
.
Parts
{
...
...
@@ -61,7 +61,7 @@ func checkGeminiInputSensitive(textRequest *gemini.GeminiChatRequest) ([]string,
return
sensitiveWords
,
err
}
func
getGeminiInputTokens
(
req
*
gemini
.
GeminiChatRequest
,
info
*
relaycommon
.
RelayInfo
)
int
{
func
getGeminiInputTokens
(
req
*
dto
.
GeminiChatRequest
,
info
*
relaycommon
.
RelayInfo
)
int
{
// 计算输入 token 数量
var
inputTexts
[]
string
for
_
,
content
:=
range
req
.
Contents
{
...
...
@@ -78,7 +78,7 @@ func getGeminiInputTokens(req *gemini.GeminiChatRequest, info *relaycommon.Relay
return
inputTokens
}
func
isNoThinkingRequest
(
req
*
gemini
.
GeminiChatRequest
)
bool
{
func
isNoThinkingRequest
(
req
*
dto
.
GeminiChatRequest
)
bool
{
if
req
.
GenerationConfig
.
ThinkingConfig
!=
nil
&&
req
.
GenerationConfig
.
ThinkingConfig
.
ThinkingBudget
!=
nil
{
return
*
req
.
GenerationConfig
.
ThinkingConfig
.
ThinkingBudget
==
0
}
...
...
@@ -202,7 +202,12 @@ func GeminiHelper(c *gin.Context) (newAPIError *types.NewAPIError) {
}
requestBody
=
bytes
.
NewReader
(
body
)
}
else
{
jsonData
,
err
:=
common
.
Marshal
(
req
)
// 使用 ConvertGeminiRequest 转换请求格式
convertedRequest
,
err
:=
adaptor
.
ConvertGeminiRequest
(
c
,
relayInfo
,
req
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
jsonData
,
err
:=
common
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
...
...
service/convert.go
View file @
689dbfe7
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment