Compare commits

...

19 Commits

Author SHA1 Message Date
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
22 changed files with 87 additions and 51 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,9 @@ 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,linux/arm64' }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
TARGETARCH=${{ startsWith(matrix.platform, 'linux/arm64') && 'arm64' || 'amd64' }}

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,23 @@ 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"
GOARCH=$TARGETARCH
WORKDIR /build
@@ -35,14 +35,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

@@ -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...))
}

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

@@ -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",
@@ -23,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

@@ -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
@@ -88,11 +91,11 @@ var ModelRatio = map[string]float64{
"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-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-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,
@@ -417,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

@@ -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

@@ -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

@@ -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",

View File

@@ -62,7 +62,8 @@
"not_tested": "未测试",
"priority_tip": "渠道选择优先级,越高越优先",
"select_test_model": "请选择测试模型",
"click_to_update": "点击更新"
"click_to_update": "点击更新",
"balance_not_supported": "-"
},
"buttons": {
"test": "测试",

View File

@@ -1,6 +1,6 @@
import React, {useEffect, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {Card, Grid} from 'semantic-ui-react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Card, Grid } from 'semantic-ui-react';
import {
Bar,
BarChart,
@@ -242,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
@@ -271,7 +271,9 @@ const Dashboard = () => {
t('dashboard.charts.requests.tooltip'),
]}
labelFormatter={(label) =>
`${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
`${t(
'dashboard.statistics.tooltip.date'
)}: ${formatDate(label)}`
}
/>
<Line
@@ -294,7 +296,7 @@ const Dashboard = () => {
<Card.Content>
<Card.Header>
{t('dashboard.charts.quota.title')}
{/* <span className='stat-value'>
{/* <span className='stat-value'>
${summaryData.todayQuota.toFixed(3)}
</span> */}
</Card.Header>
@@ -321,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.statistics.tooltip.date')}: ${formatDate(label)}`
`${t(
'dashboard.statistics.tooltip.date'
)}: ${formatDate(label)}`
}
/>
<Line
@@ -348,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
@@ -377,7 +381,9 @@ const Dashboard = () => {
t('dashboard.charts.tokens.tooltip'),
]}
labelFormatter={(label) =>
`${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
`${t(
'dashboard.statistics.tooltip.date'
)}: ${formatDate(label)}`
}
/>
<Line
@@ -422,7 +428,9 @@ const Dashboard = () => {
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
}}
labelFormatter={(label) =>
`${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
`${t('dashboard.statistics.tooltip.date')}: ${formatDate(
label
)}`
}
/>
<Legend