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
4febdff3
authored
May 31, 2025
by
Calcium-Ion
Committed by
GitHub
May 31, 2025
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1122 from akkuman/feat/stream-tts
feat: streaming response for tts
parents
641d30af
2e5943c1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
13 additions
and
24 deletions
+13
-24
relay/channel/openai/relay-openai.go
+13
-24
No files found.
relay/channel/openai/relay-openai.go
View file @
4febdff3
...
@@ -273,36 +273,25 @@ func OpenaiHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayI
...
@@ -273,36 +273,25 @@ func OpenaiHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayI
}
}
func
OpenaiTTSHandler
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
*
dto
.
OpenAIErrorWithStatusCode
,
*
dto
.
Usage
)
{
func
OpenaiTTSHandler
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
*
dto
.
OpenAIErrorWithStatusCode
,
*
dto
.
Usage
)
{
responseBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
// the status code has been judged before, if there is a body reading failure,
if
err
!=
nil
{
// it should be regarded as a non-recoverable error, so it should not return err for external retry.
return
service
.
OpenAIErrorWrapper
(
err
,
"read_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
// Analogous to nginx's load balancing, it will only retry if it can't be requested or
}
// if the upstream returns a specific status code, once the upstream has already written the header,
err
=
resp
.
Body
.
Close
()
// the subsequent failure of the response body should be regarded as a non-recoverable error,
if
err
!=
nil
{
// and can be terminated directly.
return
service
.
OpenAIErrorWrapper
(
err
,
"close_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
defer
resp
.
Body
.
Close
()
}
usage
:=
&
dto
.
Usage
{}
// Reset response body
usage
.
PromptTokens
=
info
.
PromptTokens
resp
.
Body
=
io
.
NopCloser
(
bytes
.
NewBuffer
(
responseBody
))
usage
.
TotalTokens
=
info
.
PromptTokens
// 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
{
for
k
,
v
:=
range
resp
.
Header
{
c
.
Writer
.
Header
()
.
Set
(
k
,
v
[
0
])
c
.
Writer
.
Header
()
.
Set
(
k
,
v
[
0
])
}
}
c
.
Writer
.
WriteHeader
(
resp
.
StatusCode
)
c
.
Writer
.
WriteHeader
(
resp
.
StatusCode
)
_
,
err
=
io
.
Copy
(
c
.
Writer
,
resp
.
Body
)
c
.
Writer
.
WriteHeaderNow
()
_
,
err
:=
io
.
Copy
(
c
.
Writer
,
resp
.
Body
)
if
err
!=
nil
{
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"copy_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
common
.
LogError
(
c
,
err
.
Error
())
}
}
err
=
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"close_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
usage
:=
&
dto
.
Usage
{}
usage
.
PromptTokens
=
info
.
PromptTokens
usage
.
TotalTokens
=
info
.
PromptTokens
return
nil
,
usage
return
nil
,
usage
}
}
...
...
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