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
8ea4c76f
authored
May 02, 2025
by
creamlike1024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support /v1/responses API
parent
f5c2fda2
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
521 additions
and
27 deletions
+521
-27
controller/relay.go
+5
-2
dto/openai_request.go
+46
-0
dto/openai_response.go
+45
-0
relay/channel/adapter.go
+3
-1
relay/channel/ali/adaptor.go
+7
-1
relay/channel/aws/adaptor.go
+7
-1
relay/channel/baidu/adaptor.go
+7
-1
relay/channel/baidu_v2/adaptor.go
+7
-1
relay/channel/claude/adaptor.go
+7
-1
relay/channel/cloudflare/adaptor.go
+5
-0
relay/channel/cohere/adaptor.go
+7
-1
relay/channel/deepseek/adaptor.go
+7
-1
relay/channel/dify/adaptor.go
+7
-1
relay/channel/gemini/adaptor.go
+5
-0
relay/channel/jina/adaptor.go
+7
-1
relay/channel/mistral/adaptor.go
+7
-1
relay/channel/mokaai/adaptor.go
+7
-1
relay/channel/ollama/adaptor.go
+7
-1
relay/channel/openai/adaptor.go
+26
-1
relay/channel/openai/relay-openai.go
+50
-0
relay/channel/palm/adaptor.go
+7
-1
relay/channel/perplexity/adaptor.go
+7
-1
relay/channel/siliconflow/adaptor.go
+7
-1
relay/channel/tencent/adaptor.go
+7
-1
relay/channel/vertex/adaptor.go
+7
-1
relay/channel/volcengine/adaptor.go
+7
-1
relay/channel/xai/adaptor.go
+7
-1
relay/channel/xunfei/adaptor.go
+7
-1
relay/channel/zhipu/adaptor.go
+7
-1
relay/channel/zhipu_4v/adaptor.go
+7
-1
relay/common/relay_info.go
+4
-0
relay/constant/relay_mode.go
+4
-0
relay/relay-responses.go
+171
-0
router/relay-router.go
+3
-1
No files found.
controller/relay.go
View file @
8ea4c76f
...
...
@@ -4,8 +4,6 @@ import (
"bytes"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"io"
"log"
"net/http"
...
...
@@ -20,6 +18,9 @@ import (
"one-api/relay/helper"
"one-api/service"
"strings"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
func
relayHandler
(
c
*
gin
.
Context
,
relayMode
int
)
*
dto
.
OpenAIErrorWithStatusCode
{
...
...
@@ -37,6 +38,8 @@ func relayHandler(c *gin.Context, relayMode int) *dto.OpenAIErrorWithStatusCode
err
=
relay
.
RerankHelper
(
c
,
relayMode
)
case
relayconstant
.
RelayModeEmbeddings
:
err
=
relay
.
EmbeddingHelper
(
c
)
case
relayconstant
.
RelayModeResponses
:
err
=
relay
.
ResponsesHelper
(
c
)
default
:
err
=
relay
.
TextHelper
(
c
)
}
...
...
dto/openai_request.go
View file @
8ea4c76f
...
...
@@ -355,3 +355,49 @@ func (m *Message) ParseContent() []MediaContent {
}
return
contentList
}
type
OpenAIResponsesRequest
struct
{
Model
string
`json:"model"`
Input
json
.
RawMessage
`json:"input,omitempty"`
Include
json
.
RawMessage
`json:"include,omitempty"`
Instructions
json
.
RawMessage
`json:"instructions,omitempty"`
MaxOutputTokens
uint
`json:"max_output_tokens,omitempty"`
Metadata
json
.
RawMessage
`json:"metadata,omitempty"`
ParallelToolCalls
bool
`json:"parallel_tool_calls,omitempty"`
PreviousResponseID
string
`json:"previous_response_id,omitempty"`
Reasoning
*
Reasoning
`json:"reasoning,omitempty"`
ServiceTier
string
`json:"service_tier,omitempty"`
Store
bool
`json:"store,omitempty"`
Stream
bool
`json:"stream,omitempty"`
Temperature
float64
`json:"temperature,omitempty"`
Text
json
.
RawMessage
`json:"text,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
Tools
[]
ResponsesToolsCall
`json:"tools,omitempty"`
TopP
float64
`json:"top_p,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
User
string
`json:"user,omitempty"`
}
type
Reasoning
struct
{
Effort
string
`json:"effort,omitempty"`
Summary
string
`json:"summary,omitempty"`
}
type
ResponsesToolsCall
struct
{
Type
string
`json:"type"`
// Web Search
UserLocation
json
.
RawMessage
`json:"user_location,omitempty"`
SearchContextSize
string
`json:"search_context_size,omitempty"`
// File Search
VectorStoreIds
[]
string
`json:"vector_store_ids,omitempty"`
MaxNumResults
uint
`json:"max_num_results,omitempty"`
Filters
json
.
RawMessage
`json:"filters,omitempty"`
// Computer Use
DisplayWidth
uint
`json:"display_width,omitempty"`
DisplayHeight
uint
`json:"display_height,omitempty"`
Environment
string
`json:"environment,omitempty"`
// Function
Name
string
`json:"name,omitempty"`
Description
string
`json:"description,omitempty"`
Parameters
json
.
RawMessage
`json:"parameters,omitempty"`
}
dto/openai_response.go
View file @
8ea4c76f
package
dto
import
"encoding/json"
type
SimpleResponse
struct
{
Usage
`json:"usage"`
Error
*
OpenAIError
`json:"error"`
...
...
@@ -191,3 +193,46 @@ type OutputTokenDetails struct {
AudioTokens
int
`json:"audio_tokens"`
ReasoningTokens
int
`json:"reasoning_tokens"`
}
type
OpenAIResponsesResponse
struct
{
ID
string
`json:"id"`
Object
string
`json:"object"`
CreatedAt
int
`json:"created_at"`
Status
string
`json:"status"`
Error
*
OpenAIError
`json:"error,omitempty"`
IncompleteDetails
*
IncompleteDetails
`json:"incomplete_details,omitempty"`
Instructions
string
`json:"instructions"`
MaxOutputTokens
int
`json:"max_output_tokens"`
Model
string
`json:"model"`
Output
[]
ResponsesOutput
`json:"output"`
ParallelToolCalls
bool
`json:"parallel_tool_calls"`
PreviousResponseID
string
`json:"previous_response_id"`
Reasoning
*
Reasoning
`json:"reasoning"`
Store
bool
`json:"store"`
Temperature
float64
`json:"temperature"`
ToolChoice
string
`json:"tool_choice"`
Tools
[]
interface
{}
`json:"tools"`
TopP
float64
`json:"top_p"`
Truncation
string
`json:"truncation"`
Usage
Usage
`json:"usage"`
User
json
.
RawMessage
`json:"user"`
Metadata
json
.
RawMessage
`json:"metadata"`
}
type
IncompleteDetails
struct
{
Reasoning
string
`json:"reasoning"`
}
type
ResponsesOutput
struct
{
Type
string
`json:"type"`
ID
string
`json:"id"`
Status
string
`json:"status"`
Role
string
`json:"role"`
Content
[]
ResponsesOutputContent
`json:"content"`
}
type
ResponsesOutputContent
struct
{
Type
string
`json:"type"`
Text
string
`json:"text"`
Annotations
[]
interface
{}
`json:"annotations"`
}
relay/channel/adapter.go
View file @
8ea4c76f
package
channel
import
(
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
relaycommon
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
type
Adaptor
interface
{
...
...
@@ -18,6 +19,7 @@ type Adaptor interface {
ConvertEmbeddingRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
EmbeddingRequest
)
(
any
,
error
)
ConvertAudioRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
AudioRequest
)
(
io
.
Reader
,
error
)
ConvertImageRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
ImageRequest
)
(
any
,
error
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
DoResponse
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
usage
any
,
err
*
dto
.
OpenAIErrorWithStatusCode
)
GetModelList
()
[]
string
...
...
relay/channel/ali/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package ali
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -11,6 +10,8 @@ import (
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -79,6 +80,11 @@ func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInf
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/aws/adaptor.go
View file @
8ea4c76f
...
...
@@ -2,13 +2,14 @@ package aws
import
(
"errors"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel/claude"
relaycommon
"one-api/relay/common"
"one-api/setting/model_setting"
"github.com/gin-gonic/gin"
)
const
(
...
...
@@ -74,6 +75,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
nil
,
nil
}
...
...
relay/channel/baidu/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package baidu
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -11,6 +10,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -130,6 +131,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
baiduEmbeddingRequest
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/baidu_v2/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,13 +3,14 @@ package baidu_v2
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -60,6 +61,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/claude/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package claude
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -11,6 +10,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/setting/model_setting"
"strings"
"github.com/gin-gonic/gin"
)
const
(
...
...
@@ -84,6 +85,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/cloudflare/adaptor.go
View file @
8ea4c76f
...
...
@@ -55,6 +55,11 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
}
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/cohere/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,13 +3,14 @@ package cohere
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -52,6 +53,11 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
return
requestOpenAI2Cohere
(
*
request
),
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/deepseek/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package deepseek
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -12,6 +11,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -71,6 +72,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/dify/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,12 +3,13 @@ package dify
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
relaycommon
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
const
(
...
...
@@ -86,6 +87,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/gemini/adaptor.go
View file @
8ea4c76f
...
...
@@ -155,6 +155,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
geminiRequest
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/jina/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package jina
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -12,6 +11,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/relay/common_handler"
"one-api/relay/constant"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -55,6 +56,11 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
return
request
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/mistral/adaptor.go
View file @
8ea4c76f
...
...
@@ -2,13 +2,14 @@ package mistral
import
(
"errors"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -59,6 +60,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/mokaai/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package mokaai
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -11,6 +10,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -74,6 +75,11 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
return
nil
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/ollama/adaptor.go
View file @
8ea4c76f
...
...
@@ -2,7 +2,6 @@ package ollama
import
(
"errors"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -10,6 +9,8 @@ import (
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
relayconstant
"one-api/relay/constant"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -64,6 +65,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
requestOpenAI2Embeddings
(
request
),
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/openai/adaptor.go
View file @
8ea4c76f
...
...
@@ -25,8 +25,9 @@ import (
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"net/textproto"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -67,6 +68,9 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
if
info
.
RelayFormat
==
relaycommon
.
RelayFormatClaude
{
return
fmt
.
Sprintf
(
"%s/v1/chat/completions"
,
info
.
BaseUrl
),
nil
}
if
info
.
RelayMode
==
constant
.
RelayModeResponses
{
return
fmt
.
Sprintf
(
"%s/v1/responses"
,
info
.
BaseUrl
),
nil
}
if
info
.
RelayMode
==
constant
.
RelayModeRealtime
{
if
strings
.
HasPrefix
(
info
.
BaseUrl
,
"https://"
)
{
baseUrl
:=
strings
.
TrimPrefix
(
info
.
BaseUrl
,
"https://"
)
...
...
@@ -380,6 +384,21 @@ func detectImageMimeType(filename string) string {
}
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// 模型后缀转换 reasoning effort
if
strings
.
HasSuffix
(
request
.
Model
,
"-high"
)
{
request
.
Reasoning
.
Effort
=
"high"
request
.
Model
=
strings
.
TrimSuffix
(
request
.
Model
,
"-high"
)
}
else
if
strings
.
HasSuffix
(
request
.
Model
,
"-low"
)
{
request
.
Reasoning
.
Effort
=
"low"
request
.
Model
=
strings
.
TrimSuffix
(
request
.
Model
,
"-low"
)
}
else
if
strings
.
HasSuffix
(
request
.
Model
,
"-medium"
)
{
request
.
Reasoning
.
Effort
=
"medium"
request
.
Model
=
strings
.
TrimSuffix
(
request
.
Model
,
"-medium"
)
}
return
request
,
nil
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
if
info
.
RelayMode
==
constant
.
RelayModeAudioTranscription
||
info
.
RelayMode
==
constant
.
RelayModeAudioTranslation
||
...
...
@@ -406,6 +425,12 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
err
,
usage
=
OpenaiHandlerWithUsage
(
c
,
resp
,
info
)
case
constant
.
RelayModeRerank
:
err
,
usage
=
common_handler
.
RerankHandler
(
c
,
info
,
resp
)
case
constant
.
RelayModeResponses
:
if
info
.
IsStream
{
err
,
usage
=
OaiStreamHandler
(
c
,
resp
,
info
)
}
else
{
err
,
usage
=
OpenaiResponsesHandler
(
c
,
resp
,
info
)
}
default
:
if
info
.
IsStream
{
err
,
usage
=
OaiStreamHandler
(
c
,
resp
,
info
)
...
...
relay/channel/openai/relay-openai.go
View file @
8ea4c76f
...
...
@@ -644,3 +644,53 @@ func OpenaiHandlerWithUsage(c *gin.Context, resp *http.Response, info *relaycomm
}
return
nil
,
&
usageResp
.
Usage
}
func
OpenaiResponsesHandler
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
*
dto
.
OpenAIErrorWithStatusCode
,
*
dto
.
Usage
)
{
// read response body
var
responsesResponse
dto
.
OpenAIResponsesResponse
responseBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"read_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
err
=
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"close_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
err
=
common
.
DecodeJson
(
responseBody
,
&
responsesResponse
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"unmarshal_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
if
responsesResponse
.
Error
!=
nil
{
return
&
dto
.
OpenAIErrorWithStatusCode
{
Error
:
dto
.
OpenAIError
{
Message
:
responsesResponse
.
Error
.
Message
,
Type
:
"openai_error"
,
Code
:
responsesResponse
.
Error
.
Code
,
},
StatusCode
:
resp
.
StatusCode
,
},
nil
}
// reset response body
resp
.
Body
=
io
.
NopCloser
(
bytes
.
NewBuffer
(
responseBody
))
// We shouldn't set the header before we parse the response body, because the parse part may fail.
// And then we will have to send an error response, but in this case, the header has already been set.
// So the httpClient will be confused by the response.
// For example, Postman will report error, and we cannot check the response at all.
for
k
,
v
:=
range
resp
.
Header
{
c
.
Writer
.
Header
()
.
Set
(
k
,
v
[
0
])
}
c
.
Writer
.
WriteHeader
(
resp
.
StatusCode
)
// copy response body
_
,
err
=
io
.
Copy
(
c
.
Writer
,
resp
.
Body
)
if
err
!=
nil
{
common
.
SysError
(
"error copying response body: "
+
err
.
Error
())
}
resp
.
Body
.
Close
()
// compute usage
usage
:=
dto
.
Usage
{}
usage
.
PromptTokens
=
responsesResponse
.
Usage
.
InputTokens
usage
.
CompletionTokens
=
responsesResponse
.
Usage
.
OutputTokens
usage
.
TotalTokens
=
responsesResponse
.
Usage
.
TotalTokens
return
nil
,
&
usage
}
relay/channel/palm/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,13 +3,14 @@ package palm
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
relaycommon
"one-api/relay/common"
"one-api/service"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -60,6 +61,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/perplexity/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,13 +3,14 @@ package perplexity
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -63,6 +64,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/siliconflow/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package siliconflow
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -11,6 +10,8 @@ import (
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -58,6 +59,11 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
return
request
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/tencent/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package tencent
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/common"
...
...
@@ -13,6 +12,8 @@ import (
"one-api/service"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -84,6 +85,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/vertex/adaptor.go
View file @
8ea4c76f
...
...
@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -14,6 +13,8 @@ import (
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
"strings"
"github.com/gin-gonic/gin"
)
const
(
...
...
@@ -164,6 +165,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/volcengine/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package volcengine
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -12,6 +11,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/relay/constant"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -71,6 +72,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
request
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/xai/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,13 +3,14 @@ package xai
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
relaycommon
"one-api/relay/common"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -78,6 +79,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not available"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/channel/xunfei/adaptor.go
View file @
8ea4c76f
...
...
@@ -2,7 +2,6 @@ package xunfei
import
(
"errors"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -10,6 +9,8 @@ import (
relaycommon
"one-api/relay/common"
"one-api/service"
"strings"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -61,6 +62,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
// xunfei's request is not http request, so we don't need to do anything here
dummyResp
:=
&
http
.
Response
{}
...
...
relay/channel/zhipu/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,12 +3,13 @@ package zhipu
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
"one-api/relay/channel"
relaycommon
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -71,6 +72,11 @@ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, request
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoResponse
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
usage
any
,
err
*
dto
.
OpenAIErrorWithStatusCode
)
{
if
info
.
IsStream
{
err
,
usage
=
zhipuStreamHandler
(
c
,
resp
)
...
...
relay/channel/zhipu_4v/adaptor.go
View file @
8ea4c76f
...
...
@@ -3,7 +3,6 @@ package zhipu_4v
import
(
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -11,6 +10,8 @@ import (
"one-api/relay/channel/openai"
relaycommon
"one-api/relay/common"
relayconstant
"one-api/relay/constant"
"github.com/gin-gonic/gin"
)
type
Adaptor
struct
{
...
...
@@ -70,6 +71,11 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
return
request
,
nil
}
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// TODO implement me
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
a
*
Adaptor
)
DoRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
requestBody
io
.
Reader
)
(
any
,
error
)
{
return
channel
.
DoApiRequest
(
a
,
c
,
info
,
requestBody
)
}
...
...
relay/common/relay_info.go
View file @
8ea4c76f
...
...
@@ -200,6 +200,10 @@ func GenRelayInfo(c *gin.Context) *RelayInfo {
if
streamSupportedChannels
[
info
.
ChannelType
]
{
info
.
SupportStreamOptions
=
true
}
// responses 模式不支持 StreamOptions
if
relayconstant
.
RelayModeResponses
==
info
.
RelayMode
{
info
.
SupportStreamOptions
=
false
}
return
info
}
...
...
relay/constant/relay_mode.go
View file @
8ea4c76f
...
...
@@ -40,6 +40,8 @@ const (
RelayModeRerank
RelayModeResponses
RelayModeRealtime
)
...
...
@@ -61,6 +63,8 @@ func Path2RelayMode(path string) int {
relayMode
=
RelayModeImagesEdits
}
else
if
strings
.
HasPrefix
(
path
,
"/v1/edits"
)
{
relayMode
=
RelayModeEdits
}
else
if
strings
.
HasPrefix
(
path
,
"/v1/responses"
)
{
relayMode
=
RelayModeResponses
}
else
if
strings
.
HasPrefix
(
path
,
"/v1/audio/speech"
)
{
relayMode
=
RelayModeAudioSpeech
}
else
if
strings
.
HasPrefix
(
path
,
"/v1/audio/transcriptions"
)
{
...
...
relay/relay-responses.go
0 → 100644
View file @
8ea4c76f
package
relay
import
(
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"one-api/common"
"one-api/dto"
relaycommon
"one-api/relay/common"
"one-api/relay/helper"
"one-api/service"
"one-api/setting"
"one-api/setting/model_setting"
"strings"
"github.com/gin-gonic/gin"
)
func
getAndValidateResponsesRequest
(
c
*
gin
.
Context
,
relayInfo
*
relaycommon
.
RelayInfo
)
(
*
dto
.
OpenAIResponsesRequest
,
error
)
{
request
:=
&
dto
.
OpenAIResponsesRequest
{}
err
:=
common
.
UnmarshalBodyReusable
(
c
,
request
)
if
err
!=
nil
{
return
nil
,
err
}
if
request
.
Model
==
""
{
return
nil
,
errors
.
New
(
"model is required"
)
}
if
len
(
request
.
Input
)
==
0
{
return
nil
,
errors
.
New
(
"input is required"
)
}
relayInfo
.
IsStream
=
request
.
Stream
return
request
,
nil
}
func
checkInputSensitive
(
textRequest
*
dto
.
OpenAIResponsesRequest
,
info
*
relaycommon
.
RelayInfo
)
([]
string
,
error
)
{
sensitiveWords
,
err
:=
service
.
CheckSensitiveInput
(
textRequest
.
Input
)
return
sensitiveWords
,
err
}
func
getInputTokens
(
req
*
dto
.
OpenAIResponsesRequest
,
info
*
relaycommon
.
RelayInfo
)
(
int
,
error
)
{
inputTokens
,
err
:=
service
.
CountTokenInput
(
req
.
Input
,
req
.
Model
)
info
.
PromptTokens
=
inputTokens
return
inputTokens
,
err
}
func
ResponsesHelper
(
c
*
gin
.
Context
)
(
openaiErr
*
dto
.
OpenAIErrorWithStatusCode
)
{
relayInfo
:=
relaycommon
.
GenRelayInfo
(
c
)
req
,
err
:=
getAndValidateResponsesRequest
(
c
,
relayInfo
)
if
err
!=
nil
{
common
.
LogError
(
c
,
fmt
.
Sprintf
(
"getAndValidateResponsesRequest error: %s"
,
err
.
Error
()))
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"invalid_responses_request"
,
http
.
StatusBadRequest
)
}
if
setting
.
ShouldCheckPromptSensitive
()
{
sensitiveWords
,
err
:=
checkInputSensitive
(
req
,
relayInfo
)
if
err
!=
nil
{
common
.
LogWarn
(
c
,
fmt
.
Sprintf
(
"user sensitive words detected: %s"
,
strings
.
Join
(
sensitiveWords
,
", "
)))
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"check_request_sensitive_error"
,
http
.
StatusBadRequest
)
}
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusBadRequest
)
}
req
.
Model
=
relayInfo
.
UpstreamModelName
if
value
,
exists
:=
c
.
Get
(
"prompt_tokens"
);
exists
{
promptTokens
:=
value
.
(
int
)
relayInfo
.
SetPromptTokens
(
promptTokens
)
}
else
{
promptTokens
,
err
:=
getInputTokens
(
req
,
relayInfo
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"count_input_tokens_error"
,
http
.
StatusBadRequest
)
}
c
.
Set
(
"prompt_tokens"
,
promptTokens
)
}
priceData
,
err
:=
helper
.
ModelPriceHelper
(
c
,
relayInfo
,
relayInfo
.
PromptTokens
,
int
(
req
.
MaxOutputTokens
))
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_price_error"
,
http
.
StatusInternalServerError
)
}
// pre consume quota
preConsumedQuota
,
userQuota
,
openaiErr
:=
preConsumeQuota
(
c
,
priceData
.
ShouldPreConsumedQuota
,
relayInfo
)
if
openaiErr
!=
nil
{
return
openaiErr
}
defer
func
()
{
if
openaiErr
!=
nil
{
returnPreConsumedQuota
(
c
,
relayInfo
,
userQuota
,
preConsumedQuota
)
}
}()
adaptor
:=
GetAdaptor
(
relayInfo
.
ApiType
)
if
adaptor
==
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
fmt
.
Errorf
(
"invalid api type: %d"
,
relayInfo
.
ApiType
),
"invalid_api_type"
,
http
.
StatusBadRequest
)
}
adaptor
.
Init
(
relayInfo
)
var
requestBody
io
.
Reader
if
model_setting
.
GetGlobalSettings
()
.
PassThroughRequestEnabled
{
body
,
err
:=
common
.
GetRequestBody
(
c
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"get_request_body_error"
,
http
.
StatusInternalServerError
)
}
requestBody
=
bytes
.
NewBuffer
(
body
)
}
else
{
convertedRequest
,
err
:=
adaptor
.
ConvertOpenAIResponsesRequest
(
c
,
relayInfo
,
*
req
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"convert_request_error"
,
http
.
StatusBadRequest
)
}
jsonData
,
err
:=
json
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"marshal_request_error"
,
http
.
StatusInternalServerError
)
}
// apply param override
if
len
(
relayInfo
.
ParamOverride
)
>
0
{
reqMap
:=
make
(
map
[
string
]
interface
{})
err
=
json
.
Unmarshal
(
jsonData
,
&
reqMap
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"param_override_unmarshal_failed"
,
http
.
StatusInternalServerError
)
}
for
key
,
value
:=
range
relayInfo
.
ParamOverride
{
reqMap
[
key
]
=
value
}
jsonData
,
err
=
json
.
Marshal
(
reqMap
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"param_override_marshal_failed"
,
http
.
StatusInternalServerError
)
}
}
if
common
.
DebugEnabled
{
println
(
"requestBody: "
,
string
(
jsonData
))
}
requestBody
=
bytes
.
NewBuffer
(
jsonData
)
}
var
httpResp
*
http
.
Response
resp
,
err
:=
adaptor
.
DoRequest
(
c
,
relayInfo
,
requestBody
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"do_request_failed"
,
http
.
StatusInternalServerError
)
}
statusCodeMappingStr
:=
c
.
GetString
(
"status_code_mapping"
)
if
resp
!=
nil
{
httpResp
=
resp
.
(
*
http
.
Response
)
if
httpResp
.
StatusCode
!=
http
.
StatusOK
{
openaiErr
=
service
.
RelayErrorHandler
(
httpResp
,
false
)
// reset status code 重置状态码
service
.
ResetStatusCode
(
openaiErr
,
statusCodeMappingStr
)
return
openaiErr
}
}
usage
,
openaiErr
:=
adaptor
.
DoResponse
(
c
,
httpResp
,
relayInfo
)
if
openaiErr
!=
nil
{
// reset status code 重置状态码
service
.
ResetStatusCode
(
openaiErr
,
statusCodeMappingStr
)
return
openaiErr
}
if
strings
.
HasPrefix
(
relayInfo
.
OriginModelName
,
"gpt-4o-audio"
)
{
service
.
PostAudioConsumeQuota
(
c
,
relayInfo
,
usage
.
(
*
dto
.
Usage
),
preConsumedQuota
,
userQuota
,
priceData
,
""
)
}
else
{
postConsumeQuota
(
c
,
relayInfo
,
usage
.
(
*
dto
.
Usage
),
preConsumedQuota
,
userQuota
,
priceData
,
""
)
}
return
nil
}
router/relay-router.go
View file @
8ea4c76f
package
router
import
(
"github.com/gin-gonic/gin"
"one-api/controller"
"one-api/middleware"
"one-api/relay"
"github.com/gin-gonic/gin"
)
func
SetRelayRouter
(
router
*
gin
.
Engine
)
{
...
...
@@ -47,6 +48,7 @@ func SetRelayRouter(router *gin.Engine) {
httpRouter
.
POST
(
"/audio/transcriptions"
,
controller
.
Relay
)
httpRouter
.
POST
(
"/audio/translations"
,
controller
.
Relay
)
httpRouter
.
POST
(
"/audio/speech"
,
controller
.
Relay
)
httpRouter
.
POST
(
"/responses"
,
controller
.
Relay
)
httpRouter
.
GET
(
"/files"
,
controller
.
RelayNotImplemented
)
httpRouter
.
POST
(
"/files"
,
controller
.
RelayNotImplemented
)
httpRouter
.
DELETE
(
"/files/:id"
,
controller
.
RelayNotImplemented
)
...
...
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