mirror of
https://github.com/linux-do/new-api.git
synced 2025-09-17 16:06:38 +08:00
feat: 记录流模式首字时间 (close #323)
This commit is contained in:
parent
4d3b57e19b
commit
79010dbfc5
@ -52,7 +52,7 @@ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, request
|
|||||||
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage *dto.Usage, err *dto.OpenAIErrorWithStatusCode) {
|
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage *dto.Usage, err *dto.OpenAIErrorWithStatusCode) {
|
||||||
if info.IsStream {
|
if info.IsStream {
|
||||||
var responseText string
|
var responseText string
|
||||||
err, responseText, _ = openai.OpenaiStreamHandler(c, resp, info.RelayMode)
|
err, responseText, _ = openai.OpenaiStreamHandler(c, resp, info)
|
||||||
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
||||||
} else {
|
} else {
|
||||||
if info.RelayMode == relayconstant.RelayModeEmbeddings {
|
if info.RelayMode == relayconstant.RelayModeEmbeddings {
|
||||||
|
@ -82,7 +82,7 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
|
|||||||
if info.IsStream {
|
if info.IsStream {
|
||||||
var responseText string
|
var responseText string
|
||||||
var toolCount int
|
var toolCount int
|
||||||
err, responseText, toolCount = OpenaiStreamHandler(c, resp, info.RelayMode)
|
err, responseText, toolCount = OpenaiStreamHandler(c, resp, info)
|
||||||
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
||||||
usage.CompletionTokens += toolCount * 7
|
usage.CompletionTokens += toolCount * 7
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"one-api/common"
|
"one-api/common"
|
||||||
"one-api/dto"
|
"one-api/dto"
|
||||||
|
relaycommon "one-api/relay/common"
|
||||||
relayconstant "one-api/relay/constant"
|
relayconstant "one-api/relay/constant"
|
||||||
"one-api/service"
|
"one-api/service"
|
||||||
"strings"
|
"strings"
|
||||||
@ -16,7 +17,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*dto.OpenAIErrorWithStatusCode, string, int) {
|
func OpenaiStreamHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (*dto.OpenAIErrorWithStatusCode, string, int) {
|
||||||
//checkSensitive := constant.ShouldCheckCompletionSensitive()
|
//checkSensitive := constant.ShouldCheckCompletionSensitive()
|
||||||
var responseTextBuilder strings.Builder
|
var responseTextBuilder strings.Builder
|
||||||
toolCount := 0
|
toolCount := 0
|
||||||
@ -57,7 +58,7 @@ func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
streamResp := "[" + strings.Join(streamItems, ",") + "]"
|
streamResp := "[" + strings.Join(streamItems, ",") + "]"
|
||||||
switch relayMode {
|
switch info.RelayMode {
|
||||||
case relayconstant.RelayModeChatCompletions:
|
case relayconstant.RelayModeChatCompletions:
|
||||||
var streamResponses []dto.ChatCompletionsStreamResponseSimple
|
var streamResponses []dto.ChatCompletionsStreamResponseSimple
|
||||||
err := json.Unmarshal(common.StringToByteSlice(streamResp), &streamResponses)
|
err := json.Unmarshal(common.StringToByteSlice(streamResp), &streamResponses)
|
||||||
@ -126,9 +127,14 @@ func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*d
|
|||||||
common.SafeSendBool(stopChan, true)
|
common.SafeSendBool(stopChan, true)
|
||||||
}()
|
}()
|
||||||
service.SetEventStreamHeaders(c)
|
service.SetEventStreamHeaders(c)
|
||||||
|
isFirst := true
|
||||||
c.Stream(func(w io.Writer) bool {
|
c.Stream(func(w io.Writer) bool {
|
||||||
select {
|
select {
|
||||||
case data := <-dataChan:
|
case data := <-dataChan:
|
||||||
|
if isFirst {
|
||||||
|
isFirst = false
|
||||||
|
info.FirstResponseTime = time.Now()
|
||||||
|
}
|
||||||
if strings.HasPrefix(data, "data: [DONE]") {
|
if strings.HasPrefix(data, "data: [DONE]") {
|
||||||
data = data[:12]
|
data = data[:12]
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, request
|
|||||||
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage *dto.Usage, err *dto.OpenAIErrorWithStatusCode) {
|
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage *dto.Usage, err *dto.OpenAIErrorWithStatusCode) {
|
||||||
if info.IsStream {
|
if info.IsStream {
|
||||||
var responseText string
|
var responseText string
|
||||||
err, responseText, _ = openai.OpenaiStreamHandler(c, resp, info.RelayMode)
|
err, responseText, _ = openai.OpenaiStreamHandler(c, resp, info)
|
||||||
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
||||||
} else {
|
} else {
|
||||||
err, usage = openai.OpenaiHandler(c, resp, info.PromptTokens, info.UpstreamModelName)
|
err, usage = openai.OpenaiHandler(c, resp, info.PromptTokens, info.UpstreamModelName)
|
||||||
|
@ -48,7 +48,7 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
|
|||||||
if info.IsStream {
|
if info.IsStream {
|
||||||
var responseText string
|
var responseText string
|
||||||
var toolCount int
|
var toolCount int
|
||||||
err, responseText, toolCount = openai.OpenaiStreamHandler(c, resp, info.RelayMode)
|
err, responseText, toolCount = openai.OpenaiStreamHandler(c, resp, info)
|
||||||
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
usage, _ = service.ResponseText2Usage(responseText, info.UpstreamModelName, info.PromptTokens)
|
||||||
usage.CompletionTokens += toolCount * 7
|
usage.CompletionTokens += toolCount * 7
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,7 @@ type RelayInfo struct {
|
|||||||
Group string
|
Group string
|
||||||
TokenUnlimited bool
|
TokenUnlimited bool
|
||||||
StartTime time.Time
|
StartTime time.Time
|
||||||
|
FirstResponseTime time.Time
|
||||||
ApiType int
|
ApiType int
|
||||||
IsStream bool
|
IsStream bool
|
||||||
RelayMode int
|
RelayMode int
|
||||||
|
@ -332,14 +332,7 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, textRe
|
|||||||
logModel = "gpt-4-gizmo-*"
|
logModel = "gpt-4-gizmo-*"
|
||||||
logContent += fmt.Sprintf(",模型 %s", textRequest.Model)
|
logContent += fmt.Sprintf(",模型 %s", textRequest.Model)
|
||||||
}
|
}
|
||||||
other := make(map[string]interface{})
|
other := service.GenerateTextOtherInfo(ctx, relayInfo, modelRatio, groupRatio, completionRatio, modelPrice)
|
||||||
other["model_ratio"] = modelRatio
|
|
||||||
other["group_ratio"] = groupRatio
|
|
||||||
other["completion_ratio"] = completionRatio
|
|
||||||
other["model_price"] = modelPrice
|
|
||||||
adminInfo := make(map[string]interface{})
|
|
||||||
adminInfo["use_channel"] = ctx.GetStringSlice("use_channel")
|
|
||||||
other["admin_info"] = adminInfo
|
|
||||||
model.RecordConsumeLog(ctx, relayInfo.UserId, relayInfo.ChannelId, promptTokens, completionTokens, logModel, tokenName, quota, logContent, relayInfo.TokenId, userQuota, int(useTimeSeconds), relayInfo.IsStream, other)
|
model.RecordConsumeLog(ctx, relayInfo.UserId, relayInfo.ChannelId, promptTokens, completionTokens, logModel, tokenName, quota, logContent, relayInfo.TokenId, userQuota, int(useTimeSeconds), relayInfo.IsStream, other)
|
||||||
|
|
||||||
//if quota != 0 {
|
//if quota != 0 {
|
||||||
|
19
service/log.go
Normal file
19
service/log.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
relaycommon "one-api/relay/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenerateTextOtherInfo(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, modelRatio, groupRatio, completionRatio, modelPrice float64) map[string]interface{} {
|
||||||
|
other := make(map[string]interface{})
|
||||||
|
other["model_ratio"] = modelRatio
|
||||||
|
other["group_ratio"] = groupRatio
|
||||||
|
other["completion_ratio"] = completionRatio
|
||||||
|
other["model_price"] = modelPrice
|
||||||
|
other["frt"] = float64(relayInfo.FirstResponseTime.UnixMilli() - relayInfo.StartTime.UnixMilli())
|
||||||
|
adminInfo := make(map[string]interface{})
|
||||||
|
adminInfo["use_channel"] = ctx.GetStringSlice("use_channel")
|
||||||
|
other["admin_info"] = adminInfo
|
||||||
|
return other
|
||||||
|
}
|
@ -29,6 +29,7 @@ import {
|
|||||||
stringToColor,
|
stringToColor,
|
||||||
} from '../helpers/render';
|
} from '../helpers/render';
|
||||||
import Paragraph from '@douyinfe/semi-ui/lib/es/typography/paragraph';
|
import Paragraph from '@douyinfe/semi-ui/lib/es/typography/paragraph';
|
||||||
|
import {getLogOther} from "../helpers/other.js";
|
||||||
|
|
||||||
const { Header } = Layout;
|
const { Header } = Layout;
|
||||||
|
|
||||||
@ -141,6 +142,33 @@ function renderUseTime(type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderFirstUseTime(type) {
|
||||||
|
let time = parseFloat(type) / 1000.0;
|
||||||
|
time = time.toFixed(1)
|
||||||
|
if (time < 3) {
|
||||||
|
return (
|
||||||
|
<Tag color='green' size='large'>
|
||||||
|
{' '}
|
||||||
|
{time} s{' '}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
} else if (time < 10) {
|
||||||
|
return (
|
||||||
|
<Tag color='orange' size='large'>
|
||||||
|
{' '}
|
||||||
|
{time} s{' '}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Tag color='red' size='large'>
|
||||||
|
{' '}
|
||||||
|
{time} s{' '}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const LogsTable = () => {
|
const LogsTable = () => {
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@ -247,17 +275,30 @@ const LogsTable = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用时',
|
title: '用时/首字',
|
||||||
dataIndex: 'use_time',
|
dataIndex: 'use_time',
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
if (record.is_stream) {
|
||||||
<div>
|
let other = getLogOther(record.other);
|
||||||
<Space>
|
return (
|
||||||
{renderUseTime(text)}
|
<div>
|
||||||
{renderIsStream(record.is_stream)}
|
<Space>
|
||||||
</Space>
|
{renderUseTime(text)}
|
||||||
</div>
|
{renderFirstUseTime(other.frt)}
|
||||||
);
|
{renderIsStream(record.is_stream)}
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Space>
|
||||||
|
{renderUseTime(text)}
|
||||||
|
{renderIsStream(record.is_stream)}
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -325,10 +366,7 @@ const LogsTable = () => {
|
|||||||
title: '详情',
|
title: '详情',
|
||||||
dataIndex: 'content',
|
dataIndex: 'content',
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
if (record.other === '') {
|
let other = getLogOther(record.other);
|
||||||
record.other = '{}'
|
|
||||||
}
|
|
||||||
let other = JSON.parse(record.other);
|
|
||||||
if (other == null) {
|
if (other == null) {
|
||||||
return (
|
return (
|
||||||
<Paragraph
|
<Paragraph
|
||||||
|
7
web/src/helpers/other.js
Normal file
7
web/src/helpers/other.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export function getLogOther(otherStr) {
|
||||||
|
if (otherStr === undefined || otherStr === '') {
|
||||||
|
otherStr = '{}'
|
||||||
|
}
|
||||||
|
let other = JSON.parse(otherStr)
|
||||||
|
return other
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user