feat: publish v1.0.0-rc.36-custom.1
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 9m20s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 55m7s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 9m20s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 55m7s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
This commit is contained in:
commit
bb7968b612
2381 files changed
+551494
No files matched your search
@@ -0,0 +1,119 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/QuantumNous/new-api/common"
|
||||
)
|
||||
|
||||
type StatusChannel struct {
|
||||
Id int
|
||||
Group string
|
||||
Status int
|
||||
}
|
||||
|
||||
type GroupCacheStats struct {
|
||||
Requests int64 `json:"requests"`
|
||||
CachedRequests int64 `json:"cached_requests"`
|
||||
InputTokens int64 `json:"input_tokens"`
|
||||
CachedTokens int64 `json:"cached_tokens"`
|
||||
FirstResponseMs float64 `json:"first_response_ms,omitempty"`
|
||||
}
|
||||
|
||||
func GetStatusChannels(ctx context.Context) ([]StatusChannel, error) {
|
||||
var channels []StatusChannel
|
||||
err := DB.WithContext(ctx).Model(&Channel{}).Select("id", "group", "status").
|
||||
Where("status IN ?", []int{common.ChannelStatusEnabled, common.ChannelStatusAutoDisabled}).
|
||||
Order("id").Find(&channels).Error
|
||||
return channels, err
|
||||
}
|
||||
|
||||
// Channels retain their identity when a public group is renamed.
|
||||
func GetGroupCacheStats(ctx context.Context, channels []StatusChannel, start, end time.Time) (map[string]GroupCacheStats, error) {
|
||||
stats := make(map[string]GroupCacheStats)
|
||||
firstResponseTotals := make(map[string]struct {
|
||||
total float64
|
||||
count int64
|
||||
})
|
||||
channelGroups := make(map[int][]string)
|
||||
ids := make([]int, 0, len(channels))
|
||||
for _, channel := range channels {
|
||||
ids = append(ids, channel.Id)
|
||||
for _, group := range strings.Split(channel.Group, ",") {
|
||||
group = strings.TrimSpace(group)
|
||||
if group != "" && !common.StringsContains(channelGroups[channel.Id], group) {
|
||||
channelGroups[channel.Id] = append(channelGroups[channel.Id], group)
|
||||
stats[group] = GroupCacheStats{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return stats, nil
|
||||
}
|
||||
rows, err := LOG_DB.WithContext(ctx).Model(&Log{}).Select("channel_id", "prompt_tokens", "other").
|
||||
Where("type = ? AND token_id > 0 AND created_at >= ? AND created_at < ?", LogTypeConsume, start.Unix(), end.Unix()).
|
||||
Where("channel_id IN ?", ids).Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var channelID int
|
||||
var prompt int64
|
||||
var raw string
|
||||
if err := rows.Scan(&channelID, &prompt, &raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var usage struct {
|
||||
Cached int64 `json:"cache_tokens"`
|
||||
Created int64 `json:"cache_creation_tokens"`
|
||||
Created5m int64 `json:"cache_creation_tokens_5m"`
|
||||
Created1h int64 `json:"cache_creation_tokens_1h"`
|
||||
Written int64 `json:"cache_write_tokens"`
|
||||
InputTotal int64 `json:"input_tokens_total"`
|
||||
Semantic string `json:"usage_semantic"`
|
||||
Claude bool `json:"claude"`
|
||||
FirstResponseMs float64 `json:"frt"`
|
||||
}
|
||||
if strings.TrimSpace(raw) != "" && common.UnmarshalJsonStr(raw, &usage) != nil {
|
||||
continue
|
||||
}
|
||||
input := max(prompt, 0)
|
||||
cached := max(usage.Cached, 0)
|
||||
if usage.InputTotal > 0 {
|
||||
input = usage.InputTotal
|
||||
} else if usage.Semantic == "anthropic" || (usage.Semantic == "" && usage.Claude) {
|
||||
input += cached + max(usage.Written, usage.Created, max(usage.Created5m, 0)+max(usage.Created1h, 0), 0)
|
||||
}
|
||||
if input == 0 {
|
||||
continue
|
||||
}
|
||||
cached = min(cached, input)
|
||||
for _, group := range channelGroups[channelID] {
|
||||
total := stats[group]
|
||||
total.Requests++
|
||||
if cached > 0 {
|
||||
total.CachedRequests++
|
||||
}
|
||||
total.InputTokens += input
|
||||
total.CachedTokens += cached
|
||||
stats[group] = total
|
||||
if usage.FirstResponseMs > 0 {
|
||||
frt := firstResponseTotals[group]
|
||||
frt.total += usage.FirstResponseMs
|
||||
frt.count++
|
||||
firstResponseTotals[group] = frt
|
||||
}
|
||||
}
|
||||
}
|
||||
for group, total := range firstResponseTotals {
|
||||
if total.count > 0 {
|
||||
groupStats := stats[group]
|
||||
groupStats.FirstResponseMs = total.total / float64(total.count)
|
||||
stats[group] = groupStats
|
||||
}
|
||||
}
|
||||
return stats, rows.Err()
|
||||
}
|
||||
Reference in new issue
Block a user