Compare commits

..

36 Commits

Author SHA1 Message Date
JustSong
20435fcbfc fix: simplify Docker build configuration by removing unnecessary platform and architecture settings 2025-02-09 14:33:25 +08:00
JustSong
6e7a1c2323 fix: format channel options for consistency and improve tips for user guidance 2025-02-09 12:42:31 +08:00
JustSong
dd65b997dd feat: add Baidu V2 channel support and improve model handling 2025-02-09 12:37:26 +08:00
JustSong
0b6d03d6c6 fix: update channel name from '火山引擎' to '字节火山引擎' for consistency 2025-02-09 12:08:40 +08:00
JustSong
4375246e24 feat: enhance channel options with tips and descriptions for better user guidance 2025-02-09 12:03:31 +08:00
longkeyy
3e3b8230ac fix: add read/write locks for ModelRatio and GroupRatio to prevent concurrent map read/write issues (#2067)
Some checks are pending
CI / Unit tests (push) Waiting to run
CI / commit_lint (push) Waiting to run
2025-02-09 11:02:45 +08:00
JustSong
07808122a6 fix: fix Debugf not using DebugEnabled (close #2068) 2025-02-09 10:57:22 +08:00
牡丹凤凰
c96895e35b docs: add related project CherryStudio (#2059)
Some checks failed
CI / Unit tests (push) Has been cancelled
CI / commit_lint (push) Has been cancelled
* Update README.md

增加相关项目CherryStudio

* Update README.en.md

* Update README.ja.md
2025-02-08 00:07:55 +08:00
JustSong
2552c68249 fix: update doubao channel name
Some checks are pending
CI / Unit tests (push) Waiting to run
CI / commit_lint (push) Waiting to run
2025-02-07 01:51:28 +08:00
JustSong
5c81e40612 fix: update Dockerfile and workflow for improved multi-architecture support 2025-02-07 01:35:53 +08:00
JustSong
0d5318b1b7 revert: fix: revert sqlite build related changes
This reverts commit db65db2807.
2025-02-07 01:15:33 +08:00
JustSong
db65db2807 fix: revert sqlite build related changes 2025-02-07 00:48:23 +08:00
JustSong
e0b7e6a9e2 fix: unify version retrieval in Dockerfile build commands 2025-02-07 00:39:55 +08:00
JustSong
27c2abe80f fix: update Docker setup actions to latest versions 2025-02-07 00:33:15 +08:00
JustSong
2c867251b5 fix: improve code formatting and readability in Dashboard component 2025-02-07 00:23:13 +08:00
JustSong
108111ebd3 fix: exclude preview tags from release workflows 2025-02-07 00:19:23 +08:00
JustSong
293ba93ad6 fix: remove outdated model from ModelList and add new deepseek models 2025-02-07 00:13:57 +08:00
JustSong
faced40d5b fix: update Docker image workflow to conditionally include arm64 platform 2025-02-07 00:06:32 +08:00
JustSong
2ae9997f29 fix: enhance error handling for Gemini API key validation 2025-02-07 00:03:00 +08:00
JustSong
e146b14d46 fix: add default API version handling and enhance error message checks for Gemini 2025-02-07 00:01:38 +08:00
JustSong
e19045f925 chore: add deepseek-reasoner 2025-02-06 23:38:29 +08:00
JustSong
d2903b673d fix: update SiliconCloud link in README
Some checks failed
CI / Unit tests (push) Has been cancelled
CI / commit_lint (push) Has been cancelled
2025-02-04 20:07:05 +08:00
JustSong
33edcf604c feat: add balance_not_supported translation to English and Chinese locales
Some checks are pending
CI / Unit tests (push) Waiting to run
CI / commit_lint (push) Waiting to run
2025-02-03 18:22:59 +08:00
JustSong
78fd6ef161 fix: update README for clarity on stable and alpha image addresses 2025-02-03 18:15:44 +08:00
JustSong
9b6d5f76e0 fix: enhance douban_notice_2 for clarity on model name conversion
Some checks are pending
CI / Unit tests (push) Waiting to run
CI / commit_lint (push) Waiting to run
2025-02-03 00:11:43 +08:00
JustSong
2250f311e1 feat: add latest version of Claude model to constants 2025-02-02 22:25:52 +08:00
lyj
e43f758623 Update model.go (#1963) 2025-02-02 22:24:31 +08:00
江南一根葱
6ded638f70 fix: audio transcription 400 error (#1882) (#2003) 2025-02-02 22:22:42 +08:00
jiz4oh
ea3331b79a fix: remove duplicated model (#2012)
the model `llama-3.2-11b-vision-preview` was declared at 3915ce9814/relay/adaptor/groq/constants.go (L11)
2025-02-02 22:21:30 +08:00
Jeremy JIANG
7a97ddc03c fix: fix hunyuan paramete & update price (#2019)
* fix: omit null TopP and Temperature fields in request body

* feat: update Hunyuan model ratios
2025-02-02 22:20:38 +08:00
JustSong
d7028b55fd feat: update model list in Zhipu constants for expanded options 2025-02-02 22:15:42 +08:00
Jeremy JIANG
36a03f465b feat: update Zhipu model prices (#2020) 2025-02-02 22:06:07 +08:00
JustSong
ae16647047 fix: change settings tab item color for improved visibility 2025-02-02 21:32:49 +08:00
JustSong
4dbc2ad86d fix: update tooltip keys in Dashboard for consistency in statistics display 2025-02-02 20:25:14 +08:00
JustSong
94479c2800 fix: add success message for completed operations in translation files 2025-02-02 20:07:08 +08:00
JustSong
614903b524 feat: comment out stat value displays in Dashboard for cleaner UI 2025-02-02 19:58:51 +08:00
37 changed files with 324 additions and 152 deletions

View File

@@ -32,10 +32,10 @@ jobs:
git describe --tags > VERSION
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2
@@ -62,8 +62,7 @@ jobs:
uses: docker/build-push-action@v3
with:
context: .
# platforms: linux/amd64,linux/arm64
platforms: linux/amd64 # TODO disable arm64 for now, because it cause error
platforms: ${{ contains(github.ref, 'alpha') && 'linux/amd64' || 'linux/amd64' }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -7,6 +7,7 @@ on:
tags:
- 'v*.*.*'
- '!*-alpha*'
- '!*-preview*'
workflow_dispatch:
inputs:
name:

View File

@@ -7,6 +7,7 @@ on:
tags:
- 'v*.*.*'
- '!*-alpha*'
- '!*-preview*'
workflow_dispatch:
inputs:
name:

View File

@@ -7,6 +7,7 @@ on:
tags:
- 'v*.*.*'
- '!*-alpha*'
- '!*-preview*'
workflow_dispatch:
inputs:
name:

View File

@@ -9,23 +9,22 @@ RUN npm install --prefix /web/default & \
npm install --prefix /web/air & \
wait
RUN DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat /web/default/VERSION) npm run build --prefix /web/default & \
DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat /web/berry/VERSION) npm run build --prefix /web/berry & \
DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat /web/air/VERSION) npm run build --prefix /web/air & \
RUN DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ./VERSION) npm run build --prefix /web/default & \
DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ./VERSION) npm run build --prefix /web/berry & \
DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ./VERSION) npm run build --prefix /web/air & \
wait
FROM golang AS builder2
FROM golang:alpine AS builder2
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
sqlite3 libsqlite3-dev \
&& rm -rf /var/lib/apt/lists/*
RUN apk add --no-cache \
gcc \
musl-dev \
sqlite-dev \
build-base
ENV GO111MODULE=on \
CGO_ENABLED=1 \
GOOS=linux \
CGO_CFLAGS="-I/usr/include" \
CGO_LDFLAGS="-L/usr/lib"
GOOS=linux
WORKDIR /build
@@ -35,14 +34,11 @@ RUN go mod download
COPY . .
COPY --from=builder /web/build ./web/build
RUN go build -trimpath -ldflags "-s -w -X 'github.com/songquanpeng/one-api/common.Version=$(cat VERSION)'" -o one-api
RUN go build -trimpath -ldflags "-s -w -X 'github.com/songquanpeng/one-api/common.Version=$(cat VERSION)' -linkmode external -extldflags '-static'" -o one-api
# Final runtime image
FROM ubuntu:22.04
FROM alpine:latest
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates tzdata bash \
&& rm -rf /var/lib/apt/lists/*
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder2 /build/one-api /

View File

@@ -315,6 +315,7 @@ If the channel ID is not provided, load balancing will be used to distribute the
* [FastGPT](https://github.com/labring/FastGPT): Knowledge question answering system based on the LLM
* [VChart](https://github.com/VisActor/VChart): More than just a cross-platform charting library, but also an expressive data storyteller.
* [VMind](https://github.com/VisActor/VMind): Not just automatic, but also fantastic. Open-source solution for intelligent visualization.
* * [CherryStudio](https://github.com/CherryHQ/cherry-studio): A cross-platform AI client that integrates multiple service providers and supports local knowledge base management.
## Note
This project is an open-source project. Please use it in compliance with OpenAI's [Terms of Use](https://openai.com/policies/terms-of-use) and **applicable laws and regulations**. It must not be used for illegal purposes.

View File

@@ -287,8 +287,8 @@ graph LR
+ インターフェイスアドレスと API Key が正しいか再確認してください。
## 関連プロジェクト
[FastGPT](https://github.com/labring/FastGPT): LLM に基づく知識質問応答システム
* [FastGPT](https://github.com/labring/FastGPT): LLM に基づく知識質問応答システム
* [CherryStudio](https://github.com/CherryHQ/cherry-studio): マルチプラットフォーム対応のAIクライアント。複数のサービスプロバイダーを統合管理し、ローカル知識ベースをサポートします。
## 注
本プロジェクトはオープンソースプロジェクトです。OpenAI の[利用規約](https://openai.com/policies/terms-of-use)および**適用される法令**を遵守してご利用ください。違法な目的での利用はご遠慮ください。

View File

@@ -57,10 +57,10 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用
> 根据[《生成式人工智能服务管理暂行办法》](http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm)的要求,请勿对中国地区公众提供一切未经备案的生成式人工智能服务。
> [!NOTE]
> 稳定版镜像地址:[justsong/one-api](https://hub.docker.com/repository/docker/justsong/one-api)
> 稳定版 / 预览版镜像地址:[justsong/one-api](https://hub.docker.com/repository/docker/justsong/one-api)
> 或者 [ghcr.io/songquanpeng/one-api](https://github.com/songquanpeng/one-api/pkgs/container/one-api)
>
> 预览版镜像地址:[justsong/one-api-alpha](https://hub.docker.com/repository/docker/justsong/one-api-alpha)
> alpha 版镜像地址:[justsong/one-api-alpha](https://hub.docker.com/repository/docker/justsong/one-api-alpha)
> 或者 [ghcr.io/songquanpeng/one-api-alpha](https://github.com/songquanpeng/one-api/pkgs/container/one-api-alpha)
> [!WARNING]
@@ -93,7 +93,7 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用
+ [x] [DeepL](https://www.deepl.com/)
+ [x] [together.ai](https://www.together.ai/)
+ [x] [novita.ai](https://www.novita.ai/)
+ [x] [硅基流动 SiliconCloud](https://siliconflow.cn/siliconcloud)
+ [x] [硅基流动 SiliconCloud](https://cloud.siliconflow.cn/i/rKXmRobW)
+ [x] [xAI](https://x.ai/)
2. 支持配置镜像以及众多[第三方代理服务](https://iamazing.cn/page/openai-api-third-party-services)。
3. 支持通过**负载均衡**的方式访问多个渠道。
@@ -469,6 +469,7 @@ https://openai.justsong.cn
* [ChatGPT Next Web](https://github.com/Yidadaa/ChatGPT-Next-Web): 一键拥有你自己的跨平台 ChatGPT 应用
* [VChart](https://github.com/VisActor/VChart): 不只是开箱即用的多端图表库,更是生动灵活的数据故事讲述者。
* [VMind](https://github.com/VisActor/VMind): 不仅自动,还很智能。开源智能可视化解决方案。
* [CherryStudio](https://github.com/CherryHQ/cherry-studio): 全平台支持的AI客户端, 多服务商集成管理、本地知识库支持。
## 注意

View File

@@ -3,10 +3,11 @@ package common
import (
"bytes"
"encoding/json"
"github.com/gin-gonic/gin"
"github.com/songquanpeng/one-api/common/ctxkey"
"io"
"strings"
"github.com/gin-gonic/gin"
"github.com/songquanpeng/one-api/common/ctxkey"
)
func GetRequestBody(c *gin.Context) ([]byte, error) {
@@ -31,7 +32,6 @@ func UnmarshalBodyReusable(c *gin.Context, v any) error {
contentType := c.Request.Header.Get("Content-Type")
if strings.HasPrefix(contentType, "application/json") {
err = json.Unmarshal(requestBody, &v)
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
} else {
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
err = c.ShouldBind(&v)
@@ -40,6 +40,7 @@ func UnmarshalBodyReusable(c *gin.Context, v any) error {
return err
}
// Reset request body
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
return nil
}

View File

@@ -93,6 +93,9 @@ func Error(ctx context.Context, msg string) {
}
func Debugf(ctx context.Context, format string, a ...any) {
if !config.DebugEnabled {
return
}
logHelper(ctx, loggerDEBUG, fmt.Sprintf(format, a...))
}

13
common/utils/array.go Normal file
View File

@@ -0,0 +1,13 @@
package utils
func DeDuplication(slice []string) []string {
m := make(map[string]bool)
for _, v := range slice {
m[v] = true
}
result := make([]string, 0, len(m))
for v := range m {
result = append(result, v)
}
return result
}

View File

@@ -2,10 +2,13 @@ package model
import (
"context"
"github.com/songquanpeng/one-api/common"
"gorm.io/gorm"
"sort"
"strings"
"gorm.io/gorm"
"github.com/songquanpeng/one-api/common"
"github.com/songquanpeng/one-api/common/utils"
)
type Ability struct {
@@ -49,6 +52,7 @@ func GetRandomSatisfiedChannel(group string, model string, ignoreFirstPriority b
func (channel *Channel) AddAbilities() error {
models_ := strings.Split(channel.Models, ",")
models_ = utils.DeDuplication(models_)
groups_ := strings.Split(channel.Group, ",")
abilities := make([]Ability, 0, len(models_))
for _, model := range models_ {

View File

@@ -35,6 +35,8 @@ func ShouldDisableChannel(err *model.Error, statusCode int) bool {
strings.Contains(lowerMessage, "balance") ||
strings.Contains(lowerMessage, "permission denied") ||
strings.Contains(lowerMessage, "organization has been restricted") || // groq
strings.Contains(lowerMessage, "api key not valid") || // gemini
strings.Contains(lowerMessage, "api key expired") || // gemini
strings.Contains(lowerMessage, "已欠费") {
return true
}

View File

@@ -4,6 +4,7 @@ var ModelList = []string{
"claude-instant-1.2", "claude-2.0", "claude-2.1",
"claude-3-haiku-20240307",
"claude-3-5-haiku-20241022",
"claude-3-5-haiku-latest",
"claude-3-sonnet-20240229",
"claude-3-opus-20240229",
"claude-3-5-sonnet-20240620",

View File

@@ -0,0 +1,30 @@
package baiduv2
// https://console.bce.baidu.com/support/?_=1692863460488&timestamp=1739074632076#/api?product=QIANFAN&project=%E5%8D%83%E5%B8%86ModelBuilder&parent=%E5%AF%B9%E8%AF%9DChat%20V2&api=v2%2Fchat%2Fcompletions&method=post
// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu#%E6%94%AF%E6%8C%81%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8
var ModelList = []string{
"ernie-4.0-8k-latest",
"ernie-4.0-8k-preview",
"ernie-4.0-8k",
"ernie-4.0-turbo-8k-latest",
"ernie-4.0-turbo-8k-preview",
"ernie-4.0-turbo-8k",
"ernie-4.0-turbo-128k",
"ernie-3.5-8k-preview",
"ernie-3.5-8k",
"ernie-3.5-128k",
"ernie-speed-8k",
"ernie-speed-128k",
"ernie-speed-pro-128k",
"ernie-lite-8k",
"ernie-lite-pro-128k",
"ernie-tiny-8k",
"ernie-char-8k",
"ernie-char-fiction-8k",
"ernie-novel-8k",
"deepseek-v3",
"deepseek-r1",
"deepseek-r1-distill-qwen-32b",
"deepseek-r1-distill-qwen-14b",
}

View File

@@ -0,0 +1,17 @@
package baiduv2
import (
"fmt"
"github.com/songquanpeng/one-api/relay/meta"
"github.com/songquanpeng/one-api/relay/relaymode"
)
func GetRequestURL(meta *meta.Meta) (string, error) {
switch meta.Mode {
case relaymode.ChatCompletions:
return fmt.Sprintf("%s/v2/chat/completions", meta.BaseURL), nil
default:
}
return "", fmt.Errorf("unsupported relay mode %d for baidu v2", meta.Mode)
}

View File

@@ -2,5 +2,5 @@ package deepseek
var ModelList = []string{
"deepseek-chat",
"deepseek-coder",
"deepseek-reasoner",
}

View File

@@ -7,6 +7,7 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/songquanpeng/one-api/common/helper"
channelhelper "github.com/songquanpeng/one-api/relay/adaptor"
"github.com/songquanpeng/one-api/relay/adaptor/openai"
@@ -29,6 +30,8 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
"gemini-2.0-flash-thinking-exp",
"gemini-2.0-flash-thinking-exp-01-21":
defaultVersion = "v1beta"
default:
defaultVersion = "v1beta"
}
version := helper.AssignOrDefault(meta.Config.APIVersion, defaultVersion)

View File

@@ -3,7 +3,6 @@ package groq
// https://console.groq.com/docs/models
var ModelList = []string{
"gemma-7b-it",
"gemma2-9b-it",
"llama-3.1-70b-versatile",
"llama-3.1-8b-instant",
@@ -11,7 +10,6 @@ var ModelList = []string{
"llama-3.2-11b-vision-preview",
"llama-3.2-1b-preview",
"llama-3.2-3b-preview",
"llama-3.2-11b-vision-preview",
"llama-3.2-90b-text-preview",
"llama-3.2-90b-vision-preview",
"llama-guard-3-8b",
@@ -24,4 +22,6 @@ var ModelList = []string{
"distil-whisper-large-v3-en",
"whisper-large-v3",
"whisper-large-v3-turbo",
"deepseek-r1-distill-llama-70b-specdec",
"deepseek-r1-distill-llama-70b",
}

View File

@@ -8,7 +8,9 @@ import (
"strings"
"github.com/gin-gonic/gin"
"github.com/songquanpeng/one-api/relay/adaptor"
"github.com/songquanpeng/one-api/relay/adaptor/baiduv2"
"github.com/songquanpeng/one-api/relay/adaptor/doubao"
"github.com/songquanpeng/one-api/relay/adaptor/minimax"
"github.com/songquanpeng/one-api/relay/adaptor/novita"
@@ -52,6 +54,8 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
return doubao.GetRequestURL(meta)
case channeltype.Novita:
return novita.GetRequestURL(meta)
case channeltype.BaiduV2:
return baiduv2.GetRequestURL(meta)
default:
return GetFullRequestURL(meta.BaseURL, meta.RequestURLPath, meta.ChannelType), nil
}

View File

@@ -3,6 +3,7 @@ package openai
import (
"github.com/songquanpeng/one-api/relay/adaptor/ai360"
"github.com/songquanpeng/one-api/relay/adaptor/baichuan"
"github.com/songquanpeng/one-api/relay/adaptor/baiduv2"
"github.com/songquanpeng/one-api/relay/adaptor/deepseek"
"github.com/songquanpeng/one-api/relay/adaptor/doubao"
"github.com/songquanpeng/one-api/relay/adaptor/groq"
@@ -34,6 +35,7 @@ var CompatibleChannels = []int{
channeltype.Novita,
channeltype.SiliconFlow,
channeltype.XAI,
channeltype.BaiduV2,
}
func GetCompatibleChannelMeta(channelType int) (string, []string) {
@@ -68,6 +70,8 @@ func GetCompatibleChannelMeta(channelType int) (string, []string) {
return "siliconflow", siliconflow.ModelList
case channeltype.XAI:
return "xai", xai.ModelList
case channeltype.BaiduV2:
return "baiduv2", baiduv2.ModelList
default:
return "openai", ModelList
}

View File

@@ -1,7 +1,14 @@
package zhipu
// https://open.bigmodel.cn/pricing
var ModelList = []string{
"chatglm_turbo", "chatglm_pro", "chatglm_std", "chatglm_lite",
"glm-4", "glm-4v", "glm-3-turbo", "embedding-2",
"cogview-3",
"glm-zero-preview", "glm-4-plus", "glm-4-0520", "glm-4-airx",
"glm-4-air", "glm-4-long", "glm-4-flashx", "glm-4-flash",
"glm-4", "glm-3-turbo",
"glm-4v-plus", "glm-4v", "glm-4v-flash",
"cogview-3-plus", "cogview-3", "cogview-3-flash",
"cogviewx", "cogviewx-flash",
"charglm-4", "emohaa", "codegeex-4",
"embedding-2", "embedding-3",
}

View File

@@ -3,8 +3,10 @@ package ratio
import (
"encoding/json"
"github.com/songquanpeng/one-api/common/logger"
"sync"
)
var groupRatioLock sync.RWMutex
var GroupRatio = map[string]float64{
"default": 1,
"vip": 1,
@@ -20,11 +22,15 @@ func GroupRatio2JSONString() string {
}
func UpdateGroupRatioByJSONString(jsonStr string) error {
groupRatioLock.Lock()
defer groupRatioLock.Unlock()
GroupRatio = make(map[string]float64)
return json.Unmarshal([]byte(jsonStr), &GroupRatio)
}
func GetGroupRatio(name string) float64 {
groupRatioLock.RLock()
defer groupRatioLock.RUnlock()
ratio, ok := GroupRatio[name]
if !ok {
logger.SysError("group ratio not found: " + name)

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"strings"
"sync"
"github.com/songquanpeng/one-api/common/logger"
)
@@ -15,6 +16,8 @@ const (
RMB = USD / USD2RMB
)
var modelRatioLock sync.RWMutex
// ModelRatio
// https://platform.openai.com/docs/models/model-endpoint-compatibility
// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Blfmc9dlf
@@ -82,15 +85,17 @@ var ModelRatio = map[string]float64{
"text-moderation-latest": 0.1,
"dall-e-2": 0.02 * USD, // $0.016 - $0.020 / image
"dall-e-3": 0.04 * USD, // $0.040 - $0.120 / image
// https://www.anthropic.com/api#pricing
// https://docs.anthropic.com/en/docs/about-claude/models
"claude-instant-1.2": 0.8 / 1000 * USD,
"claude-2.0": 8.0 / 1000 * USD,
"claude-2.1": 8.0 / 1000 * USD,
"claude-3-haiku-20240307": 0.25 / 1000 * USD,
"claude-3-5-haiku-20241022": 1.0 / 1000 * USD,
"claude-3-5-haiku-latest": 1.0 / 1000 * USD,
"claude-3-sonnet-20240229": 3.0 / 1000 * USD,
"claude-3-5-sonnet-20240620": 3.0 / 1000 * USD,
"claude-3-5-sonnet-20241022": 3.0 / 1000 * USD,
"claude-3-5-sonnet-latest": 3.0 / 1000 * USD,
"claude-3-opus-20240229": 15.0 / 1000 * USD,
// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/hlrk4akp7
"ERNIE-4.0-8K": 0.120 * RMB,
@@ -121,15 +126,29 @@ var ModelRatio = map[string]float64{
"gemini-2.0-flash-thinking-exp-01-21": 1,
"aqa": 1,
// https://open.bigmodel.cn/pricing
"glm-4": 0.1 * RMB,
"glm-4v": 0.1 * RMB,
"glm-3-turbo": 0.005 * RMB,
"embedding-2": 0.0005 * RMB,
"chatglm_turbo": 0.3572, // ¥0.005 / 1k tokens
"chatglm_pro": 0.7143, // ¥0.01 / 1k tokens
"chatglm_std": 0.3572, // ¥0.005 / 1k tokens
"chatglm_lite": 0.1429, // ¥0.002 / 1k tokens
"cogview-3": 0.25 * RMB,
"glm-zero-preview": 0.01 * RMB,
"glm-4-plus": 0.05 * RMB,
"glm-4-0520": 0.1 * RMB,
"glm-4-airx": 0.01 * RMB,
"glm-4-air": 0.0005 * RMB,
"glm-4-long": 0.001 * RMB,
"glm-4-flashx": 0.0001 * RMB,
"glm-4-flash": 0,
"glm-4": 0.1 * RMB, // deprecated model, available until 2025/06
"glm-3-turbo": 0.001 * RMB, // deprecated model, available until 2025/06
"glm-4v-plus": 0.004 * RMB,
"glm-4v": 0.05 * RMB,
"glm-4v-flash": 0,
"cogview-3-plus": 0.06 * RMB,
"cogview-3": 0.1 * RMB,
"cogview-3-flash": 0,
"cogviewx": 0.5 * RMB,
"cogviewx-flash": 0,
"charglm-4": 0.001 * RMB,
"emohaa": 0.015 * RMB,
"codegeex-4": 0.0001 * RMB,
"embedding-2": 0.0005 * RMB,
"embedding-3": 0.0005 * RMB,
// https://help.aliyun.com/zh/dashscope/developer-reference/tongyi-thousand-questions-metering-and-billing
"qwen-turbo": 1.4286, // ¥0.02 / 1k tokens
"qwen-turbo-latest": 1.4286,
@@ -216,9 +235,19 @@ var ModelRatio = map[string]float64{
"embedding-bert-512-v1": 0.0715, // ¥0.001 / 1k tokens
"embedding_s1_v1": 0.0715, // ¥0.001 / 1k tokens
"semantic_similarity_s1_v1": 0.0715, // ¥0.001 / 1k tokens
"hunyuan": 7.143, // ¥0.1 / 1k tokens // https://cloud.tencent.com/document/product/1729/97731#e0e6be58-60c8-469f-bdeb-6c264ce3b4d0
"ChatStd": 0.01 * RMB,
"ChatPro": 0.1 * RMB,
// https://cloud.tencent.com/document/product/1729/97731#e0e6be58-60c8-469f-bdeb-6c264ce3b4d0
"hunyuan-turbo": 0.015 * RMB,
"hunyuan-large": 0.004 * RMB,
"hunyuan-large-longcontext": 0.006 * RMB,
"hunyuan-standard": 0.0008 * RMB,
"hunyuan-standard-256K": 0.0005 * RMB,
"hunyuan-translation-lite": 0.005 * RMB,
"hunyuan-role": 0.004 * RMB,
"hunyuan-functioncall": 0.004 * RMB,
"hunyuan-code": 0.004 * RMB,
"hunyuan-turbo-vision": 0.08 * RMB,
"hunyuan-vision": 0.018 * RMB,
"hunyuan-embedding": 0.0007 * RMB,
// https://platform.moonshot.cn/pricing
"moonshot-v1-8k": 0.012 * RMB,
"moonshot-v1-32k": 0.024 * RMB,
@@ -391,11 +420,15 @@ func ModelRatio2JSONString() string {
}
func UpdateModelRatioByJSONString(jsonStr string) error {
modelRatioLock.Lock()
defer modelRatioLock.Unlock()
ModelRatio = make(map[string]float64)
return json.Unmarshal([]byte(jsonStr), &ModelRatio)
}
func GetModelRatio(name string, channelType int) float64 {
modelRatioLock.RLock()
defer modelRatioLock.RUnlock()
if strings.HasPrefix(name, "qwen-") && strings.HasSuffix(name, "-internet") {
name = strings.TrimSuffix(name, "-internet")
}

View File

@@ -48,5 +48,6 @@ const (
SiliconFlow
XAI
Replicate
BaiduV2
Dummy
)

View File

@@ -48,6 +48,7 @@ var ChannelBaseURLs = []string{
"https://api.siliconflow.cn", // 44
"https://api.x.ai", // 45
"https://api.replicate.com/v1/models/", // 46
"https://qianfan.baidubce.com", // 47
}
func init() {

View File

@@ -1,11 +1,12 @@
package model
type Message struct {
Role string `json:"role,omitempty"`
Content any `json:"content,omitempty"`
Name *string `json:"name,omitempty"`
ToolCalls []Tool `json:"tool_calls,omitempty"`
ToolCallId string `json:"tool_call_id,omitempty"`
Role string `json:"role,omitempty"`
Content any `json:"content,omitempty"`
ReasoningContent any `json:"reasoning_content,omitempty"`
Name *string `json:"name,omitempty"`
ToolCalls []Tool `json:"tool_calls,omitempty"`
ToolCallId string `json:"tool_call_id,omitempty"`
}
func (m Message) IsStringContent() bool {

View File

@@ -7,7 +7,7 @@ export const CHANNEL_OPTIONS = [
{ key: 24, text: 'Google Gemini', value: 24, color: 'orange' },
{ key: 28, text: 'Mistral AI', value: 28, color: 'orange' },
{ key: 41, text: 'Novita', value: 41, color: 'purple' },
{ key: 40, text: '字节跳动豆包', value: 40, color: 'blue' },
{key: 40, text: '字节火山引擎', value: 40, color: 'blue'},
{ key: 15, text: '百度文心千帆', value: 15, color: 'blue' },
{ key: 17, text: '阿里通义千问', value: 17, color: 'orange' },
{ key: 18, text: '讯飞星火认知', value: 18, color: 'blue' },

View File

@@ -49,7 +49,7 @@ export const CHANNEL_OPTIONS = {
},
40: {
key: 40,
text: '字节跳动豆包',
text: '字节火山引擎',
value: 40,
color: 'primary'
},

View File

@@ -1,48 +1,67 @@
export const CHANNEL_OPTIONS = [
{ key: 1, text: 'OpenAI', value: 1, color: 'green' },
{ key: 14, text: 'Anthropic Claude', value: 14, color: 'black' },
{ key: 33, text: 'AWS', value: 33, color: 'black' },
{ key: 3, text: 'Azure OpenAI', value: 3, color: 'olive' },
{ key: 11, text: 'Google PaLM2', value: 11, color: 'orange' },
{ key: 24, text: 'Google Gemini', value: 24, color: 'orange' },
{ key: 28, text: 'Mistral AI', value: 28, color: 'orange' },
{ key: 41, text: 'Novita', value: 41, color: 'purple' },
{ key: 40, text: '字节跳动豆包', value: 40, color: 'blue' },
{ key: 15, text: '百度文心千帆', value: 15, color: 'blue' },
{ key: 17, text: '阿里通义千问', value: 17, color: 'orange' },
{ key: 18, text: '讯飞星火认知', value: 18, color: 'blue' },
{ key: 16, text: '智谱 ChatGLM', value: 16, color: 'violet' },
{ key: 19, text: '360 智脑', value: 19, color: 'blue' },
{ key: 25, text: 'Moonshot AI', value: 25, color: 'black' },
{ key: 23, text: '腾讯混元', value: 23, color: 'teal' },
{ key: 26, text: '百川大模型', value: 26, color: 'orange' },
{ key: 27, text: 'MiniMax', value: 27, color: 'red' },
{ key: 29, text: 'Groq', value: 29, color: 'orange' },
{ key: 30, text: 'Ollama', value: 30, color: 'black' },
{ key: 31, text: '零一万物', value: 31, color: 'green' },
{ key: 32, text: '阶跃星辰', value: 32, color: 'blue' },
{ key: 34, text: 'Coze', value: 34, color: 'blue' },
{ key: 35, text: 'Cohere', value: 35, color: 'blue' },
{ key: 36, text: 'DeepSeek', value: 36, color: 'black' },
{ key: 37, text: 'Cloudflare', value: 37, color: 'orange' },
{ key: 38, text: 'DeepL', value: 38, color: 'black' },
{ key: 39, text: 'together.ai', value: 39, color: 'blue' },
{ key: 42, text: 'VertexAI', value: 42, color: 'blue' },
{ key: 43, text: 'Proxy', value: 43, color: 'blue' },
{ key: 44, text: 'SiliconFlow', value: 44, color: 'blue' },
{ key: 45, text: 'xAI', value: 45, color: 'blue' },
{ key: 46, text: 'Replicate', value: 46, color: 'blue' },
{ key: 8, text: '自定义渠道', value: 8, color: 'pink' },
{ key: 22, text: '知识库FastGPT', value: 22, color: 'blue' },
{ key: 21, text: '知识库AI Proxy', value: 21, color: 'purple' },
{ key: 20, text: '代理OpenRouter', value: 20, color: 'black' },
{ key: 2, text: '代理API2D', value: 2, color: 'blue' },
{ key: 5, text: '代理OpenAI-SB', value: 5, color: 'brown' },
{ key: 7, text: '代理OhMyGPT', value: 7, color: 'purple' },
{ key: 10, text: '代理AI Proxy', value: 10, color: 'purple' },
{ key: 4, text: '代理CloseAI', value: 4, color: 'teal' },
{ key: 6, text: '代理OpenAI Max', value: 6, color: 'violet' },
{ key: 9, text: '代理AI.LS', value: 9, color: 'yellow' },
{ key: 12, text: '代理API2GPT', value: 12, color: 'blue' },
{ key: 13, text: '代理AIGC2D', value: 13, color: 'purple' }
{key: 1, text: 'OpenAI', value: 1, color: 'green'},
{key: 14, text: 'Anthropic Claude', value: 14, color: 'black'},
{key: 33, text: 'AWS', value: 33, color: 'black'},
{key: 3, text: 'Azure OpenAI', value: 3, color: 'olive'},
{key: 11, text: 'Google PaLM2', value: 11, color: 'orange'},
{key: 24, text: 'Google Gemini', value: 24, color: 'orange'},
{key: 28, text: 'Mistral AI', value: 28, color: 'orange'},
{key: 41, text: 'Novita', value: 41, color: 'purple'},
{
key: 40,
text: '字节火山引擎',
value: 40,
color: 'blue',
description: '原字节跳动豆包',
},
{
key: 15,
text: '百度文心千帆',
value: 15,
color: 'blue',
tip: '请前往<a href="https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application/v1" target="_blank">此处</a>获取 AKAPI Key以及 SKSecret Key注意V2 版本接口请使用 <strong>百度文心千帆 V2 </strong>渠道类型',
},
{
key: 47,
text: '百度文心千帆 V2',
value: 47,
color: 'blue',
tip: '请前往<a href="https://console.bce.baidu.com/iam/#/iam/apikey/list" target="_blank">此处</a>获取 API Key注意本渠道仅支持<a target="_blank" href="https://cloud.baidu.com/doc/WENXINWORKSHOP/s/em4tsqo3v">推理服务 V2</a>相关模型',
},
{key: 17, text: '阿里通义千问', value: 17, color: 'orange'},
{key: 18, text: '讯飞星火认知', value: 18, color: 'blue'},
{key: 16, text: '智谱 ChatGLM', value: 16, color: 'violet'},
{key: 19, text: '360 智脑', value: 19, color: 'blue'},
{key: 25, text: 'Moonshot AI', value: 25, color: 'black'},
{key: 23, text: '腾讯混元', value: 23, color: 'teal'},
{key: 26, text: '百川大模型', value: 26, color: 'orange'},
{key: 27, text: 'MiniMax', value: 27, color: 'red'},
{key: 29, text: 'Groq', value: 29, color: 'orange'},
{key: 30, text: 'Ollama', value: 30, color: 'black'},
{key: 31, text: '零一万物', value: 31, color: 'green'},
{key: 32, text: '阶跃星辰', value: 32, color: 'blue'},
{key: 34, text: 'Coze', value: 34, color: 'blue'},
{key: 35, text: 'Cohere', value: 35, color: 'blue'},
{key: 36, text: 'DeepSeek', value: 36, color: 'black'},
{key: 37, text: 'Cloudflare', value: 37, color: 'orange'},
{key: 38, text: 'DeepL', value: 38, color: 'black'},
{key: 39, text: 'together.ai', value: 39, color: 'blue'},
{key: 42, text: 'VertexAI', value: 42, color: 'blue'},
{key: 43, text: 'Proxy', value: 43, color: 'blue'},
{key: 44, text: 'SiliconFlow', value: 44, color: 'blue'},
{key: 45, text: 'xAI', value: 45, color: 'blue'},
{key: 46, text: 'Replicate', value: 46, color: 'blue'},
{key: 8, text: '自定义渠道', value: 8, color: 'pink'},
{key: 22, text: '知识库FastGPT', value: 22, color: 'blue'},
{key: 21, text: '知识库AI Proxy', value: 21, color: 'purple'},
{key: 20, text: '代理OpenRouter', value: 20, color: 'black'},
{key: 2, text: '代理API2D', value: 2, color: 'blue'},
{key: 5, text: '代理OpenAI-SB', value: 5, color: 'brown'},
{key: 7, text: '代理OhMyGPT', value: 7, color: 'purple'},
{key: 10, text: '代理AI Proxy', value: 10, color: 'purple'},
{key: 4, text: '代理CloseAI', value: 4, color: 'teal'},
{key: 6, text: '代理OpenAI Max', value: 6, color: 'violet'},
{key: 9, text: '代理AI.LS', value: 9, color: 'yellow'},
{key: 12, text: '代理API2GPT', value: 12, color: 'blue'},
{key: 13, text: '代理AIGC2D', value: 13, color: 'purple'},
];

View File

@@ -0,0 +1,13 @@
import {CHANNEL_OPTIONS} from '../constants';
let channelMap = undefined;
export function getChannelOption(channelId) {
if (channelMap === undefined) {
channelMap = {};
CHANNEL_OPTIONS.forEach((option) => {
channelMap[option.key] = option;
});
}
return channelMap[channelId];
}

View File

@@ -1,5 +1,6 @@
import { Label } from 'semantic-ui-react';
import { useTranslation } from 'react-i18next';
import {Label, Message} from 'semantic-ui-react';
import {getChannelOption} from './helper';
import React from 'react';
export function renderText(text, limit) {
if (text.length > limit) {
@@ -98,3 +99,15 @@ export function renderColorLabel(text) {
</Label>
);
}
export function renderChannelTip(channelId) {
let channel = getChannelOption(channelId);
if (channel === undefined || channel.tip === undefined) {
return <></>;
}
return (
<Message>
<div dangerouslySetInnerHTML={{__html: channel.tip}}></div>
</Message>
);
}

View File

@@ -62,7 +62,8 @@
"not_tested": "Not Tested",
"priority_tip": "Channel selection priority, higher is preferred",
"select_test_model": "Please select test model",
"click_to_update": "Click to update"
"click_to_update": "Click to update",
"balance_not_supported": "-"
},
"buttons": {
"test": "Test",
@@ -85,7 +86,8 @@
"test_all_started": "Channel testing started successfully, please refresh page to see results.",
"delete_disabled_success": "Deleted all disabled channels, total: {{count}}",
"balance_update_success": "Channel {{name}} balance updated successfully!",
"all_balance_updated": "All enabled channel balances have been updated!"
"all_balance_updated": "All enabled channel balances have been updated!",
"operation_success": "Operation completed successfully!"
},
"edit": {
"title_edit": "Update Channel Information",

View File

@@ -62,7 +62,8 @@
"not_tested": "未测试",
"priority_tip": "渠道选择优先级,越高越优先",
"select_test_model": "请选择测试模型",
"click_to_update": "点击更新"
"click_to_update": "点击更新",
"balance_not_supported": "-"
},
"buttons": {
"test": "测试",
@@ -85,7 +86,8 @@
"test_all_started": "已成功开始测试渠道,请刷新页面查看结果。",
"delete_disabled_success": "已删除所有禁用渠道,共计 {{count}} 个",
"balance_update_success": "渠道 {{name}} 余额更新成功!",
"all_balance_updated": "已更新完毕所有已启用渠道余额!"
"all_balance_updated": "已更新完毕所有已启用渠道余额!",
"operation_success": "操作成功完成!"
},
"edit": {
"title_edit": "更新渠道信息",
@@ -133,7 +135,7 @@
"coze_notice": "对于 Coze 而言,模型名称即 Bot ID你可以添加一个前缀 `bot-`,例如:`bot-123456`。",
"douban_notice": "对于豆包而言,需要手动去",
"douban_notice_link": "模型推理页面",
"douban_notice_2": "创建推理接入点,以接入点名称作为模型名称,例如:`ep-20240608051426-tkxvl`。",
"douban_notice_2": "创建推理接入点,以接入点名称作为模型名称,例如:`ep-20240608051426-tkxvl`。你可以结合模型重定向功能将其转换为常规的模型名称例如doubao-lite-4k -> ep-20240608051426-tkxvl前者作为 JSON 的 key后者作为 value。注意doubao-lite-4k 和 ep-20240608051426-tkxvl 都需要通过自定义模型的方式填入到本渠道的模型列表中。",
"aws_region_placeholder": "region例如us-west-2",
"aws_ak_placeholder": "AWS IAM Access Key",
"aws_sk_placeholder": "AWS IAM Secret Key",

View File

@@ -1,25 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Button,
Form,
Header,
Input,
Message,
Segment,
Card,
} from 'semantic-ui-react';
import { useNavigate, useParams } from 'react-router-dom';
import {
API,
copy,
getChannelModels,
showError,
showInfo,
showSuccess,
verifyJSON,
} from '../../helpers';
import { CHANNEL_OPTIONS } from '../../constants';
import React, {useEffect, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {Button, Card, Form, Input, Message,} from 'semantic-ui-react';
import {useNavigate, useParams} from 'react-router-dom';
import {API, copy, getChannelModels, showError, showInfo, showSuccess, verifyJSON,} from '../../helpers';
import {CHANNEL_OPTIONS} from '../../constants';
import {renderChannelTip} from '../../helpers/render';
const MODEL_MAPPING_EXAMPLE = {
'gpt-3.5-turbo-0301': 'gpt-3.5-turbo',
@@ -310,6 +295,7 @@ const EditChannel = () => {
options={groupOptions}
/>
</Form.Field>
{renderChannelTip(inputs.type)}
{/* Azure OpenAI specific fields */}
{inputs.type === 3 && (

View File

@@ -91,7 +91,7 @@
}
.settings-tab .item {
color: #2B3674 !important;
color: #000 !important;
font-weight: 500 !important;
padding: 0.8rem 1.2rem !important;
}

View File

@@ -1,19 +1,17 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Card, Grid, Header, Segment, Statistic } from 'semantic-ui-react';
import { API, showError } from '../../helpers';
import moment from 'moment';
import { Card, Grid } from 'semantic-ui-react';
import {
LineChart,
Bar,
BarChart,
CartesianGrid,
Legend,
Line,
LineChart,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
BarChart,
Bar,
Legend,
} from 'recharts';
import axios from 'axios';
import './Dashboard.css';
@@ -244,7 +242,7 @@ const Dashboard = () => {
<Card.Content>
<Card.Header>
{t('dashboard.charts.requests.title')}
<span className='stat-value'>{summaryData.todayRequests}</span>
{/* <span className='stat-value'>{summaryData.todayRequests}</span> */}
</Card.Header>
<div className='chart-container'>
<ResponsiveContainer
@@ -273,7 +271,9 @@ const Dashboard = () => {
t('dashboard.charts.requests.tooltip'),
]}
labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}`
`${t(
'dashboard.statistics.tooltip.date'
)}: ${formatDate(label)}`
}
/>
<Line
@@ -296,9 +296,9 @@ const Dashboard = () => {
<Card.Content>
<Card.Header>
{t('dashboard.charts.quota.title')}
<span className='stat-value'>
{/* <span className='stat-value'>
${summaryData.todayQuota.toFixed(3)}
</span>
</span> */}
</Card.Header>
<div className='chart-container'>
<ResponsiveContainer
@@ -323,11 +323,13 @@ const Dashboard = () => {
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
}}
formatter={(value) => [
value,
value.toFixed(6),
t('dashboard.charts.quota.tooltip'),
]}
labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}`
`${t(
'dashboard.statistics.tooltip.date'
)}: ${formatDate(label)}`
}
/>
<Line
@@ -350,7 +352,7 @@ const Dashboard = () => {
<Card.Content>
<Card.Header>
{t('dashboard.charts.tokens.title')}
<span className='stat-value'>{summaryData.todayTokens}</span>
{/* <span className='stat-value'>{summaryData.todayTokens}</span> */}
</Card.Header>
<div className='chart-container'>
<ResponsiveContainer
@@ -379,7 +381,9 @@ const Dashboard = () => {
t('dashboard.charts.tokens.tooltip'),
]}
labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}`
`${t(
'dashboard.statistics.tooltip.date'
)}: ${formatDate(label)}`
}
/>
<Line
@@ -424,7 +428,9 @@ const Dashboard = () => {
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
}}
labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}`
`${t('dashboard.statistics.tooltip.date')}: ${formatDate(
label
)}`
}
/>
<Legend