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
4cc1f2b4
authored
May 04, 2025
by
Calcium-Ion
Committed by
GitHub
May 04, 2025
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1020 from QuantumNous/v1responses
feat: support /v1/responses API
parents
fa89410e
209265e6
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
597 additions
and
27 deletions
+597
-27
controller/relay.go
+5
-2
dto/openai_request.go
+46
-0
dto/openai_response.go
+62
-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
+101
-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/helper/common.go
+8
-0
relay/relay-responses.go
+171
-0
router/relay-router.go
+3
-1
No files found.
controller/relay.go
View file @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -370,3 +370,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 @
4cc1f2b4
package
dto
import
"encoding/json"
type
SimpleResponse
struct
{
Usage
`json:"usage"`
Error
*
OpenAIError
`json:"error"`
...
...
@@ -191,3 +193,63 @@ 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"`
}
const
(
BuildInTools_WebSearch
=
"web_search_preview"
BuildInTools_FileSearch
=
"file_search"
)
const
(
ResponsesOutputTypeItemAdded
=
"response.output_item.added"
ResponsesOutputTypeItemDone
=
"response.output_item.done"
)
// ResponsesStreamResponse 用于处理 /v1/responses 流式响应
type
ResponsesStreamResponse
struct
{
Type
string
`json:"type"`
Response
*
OpenAIResponsesResponse
`json:"response"`
Delta
string
`json:"delta,omitempty"`
}
relay/channel/adapter.go
View file @
4cc1f2b4
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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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
=
OaiResponsesStreamHandler
(
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 @
4cc1f2b4
...
...
@@ -644,3 +644,104 @@ 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
}
func
OaiResponsesStreamHandler
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
*
dto
.
OpenAIErrorWithStatusCode
,
*
dto
.
Usage
)
{
if
resp
==
nil
||
resp
.
Body
==
nil
{
common
.
LogError
(
c
,
"invalid response or response body"
)
return
service
.
OpenAIErrorWrapper
(
fmt
.
Errorf
(
"invalid response"
),
"invalid_response"
,
http
.
StatusInternalServerError
),
nil
}
var
usage
=
&
dto
.
Usage
{}
var
responseTextBuilder
strings
.
Builder
helper
.
StreamScannerHandler
(
c
,
resp
,
info
,
func
(
data
string
)
bool
{
// 检查当前数据是否包含 completed 状态和 usage 信息
var
streamResponse
dto
.
ResponsesStreamResponse
if
err
:=
common
.
DecodeJsonStr
(
data
,
&
streamResponse
);
err
==
nil
{
sendResponsesStreamData
(
c
,
streamResponse
,
data
)
switch
streamResponse
.
Type
{
case
"response.completed"
:
usage
.
PromptTokens
=
streamResponse
.
Response
.
Usage
.
InputTokens
usage
.
CompletionTokens
=
streamResponse
.
Response
.
Usage
.
OutputTokens
usage
.
TotalTokens
=
streamResponse
.
Response
.
Usage
.
TotalTokens
case
"response.output_text.delta"
:
// 处理输出文本
responseTextBuilder
.
WriteString
(
streamResponse
.
Delta
)
}
}
return
true
})
helper
.
Done
(
c
)
if
usage
.
CompletionTokens
==
0
{
// 计算输出文本的 token 数量
tempStr
:=
responseTextBuilder
.
String
()
if
len
(
tempStr
)
>
0
{
// 非正常结束,使用输出文本的 token 数量
completionTokens
,
_
:=
service
.
CountTextToken
(
tempStr
,
info
.
UpstreamModelName
)
usage
.
CompletionTokens
=
completionTokens
}
}
return
nil
,
usage
}
func
sendResponsesStreamData
(
c
*
gin
.
Context
,
streamResponse
dto
.
ResponsesStreamResponse
,
data
string
)
{
if
data
==
""
{
return
}
helper
.
ResponseChunkData
(
c
,
streamResponse
,
data
)
}
relay/channel/palm/adaptor.go
View file @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"io"
"net/http"
"one-api/dto"
...
...
@@ -15,6 +14,8 @@ import (
"one-api/setting/model_setting"
relaycommon
"one-api/relay/common"
"strings"
"github.com/gin-gonic/gin"
)
const
(
...
...
@@ -174,6 +175,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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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 @
4cc1f2b4
...
...
@@ -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/helper/common.go
View file @
4cc1f2b4
...
...
@@ -43,6 +43,14 @@ func ClaudeChunkData(c *gin.Context, resp dto.ClaudeResponse, data string) {
}
}
func
ResponseChunkData
(
c
*
gin
.
Context
,
resp
dto
.
ResponsesStreamResponse
,
data
string
)
{
c
.
Render
(
-
1
,
common
.
CustomEvent
{
Data
:
fmt
.
Sprintf
(
"event: %s
\n
"
,
resp
.
Type
)})
c
.
Render
(
-
1
,
common
.
CustomEvent
{
Data
:
fmt
.
Sprintf
(
"data: %s
\n
"
,
data
)})
if
flusher
,
ok
:=
c
.
Writer
.
(
http
.
Flusher
);
ok
{
flusher
.
Flush
()
}
}
func
StringData
(
c
*
gin
.
Context
,
str
string
)
error
{
//str = strings.TrimPrefix(str, "data: ")
//str = strings.TrimSuffix(str, "\r")
...
...
relay/relay-responses.go
0 → 100644
View file @
4cc1f2b4
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 @
4cc1f2b4
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