perf: model provider show; perf: get init data buffer (#3459)

* pr code

* perf: model table show

* perf: model provider show

* perf: get init data buffer

* perf: get init data buffer

* perf: icon
This commit is contained in:
Archer
2024-12-24 15:12:07 +08:00
committed by GitHub
parent f646ef8595
commit 108e1b92ef
59 changed files with 558 additions and 329 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View File

@@ -13,3 +13,4 @@ weight: 807
1.
2. 新增 - LLM 模型参数支持关闭 max_tokens 和 temperature。
3. 优化 - 知识库搜索参数,滑动条支持输入模式,可以更精准的控制。
4. 优化 - 可用模型展示

View File

@@ -19,17 +19,20 @@ FastGPT 商业版是基于 FastGPT 开源版的增强版本,增加了一些独
| 应用管理与高级编排 | ✅ | ✅ | ✅ |
| 文档知识库 | ✅ | ✅ | ✅ |
| 外部使用 | ✅ | ✅ | ✅ |
| API 知识库 | ✅ | ✅ | ✅ |
| 最大应用数量 | 500 | 无限制 | 由付费套餐决定 |
| 最大知识库数量(单个知识库内容无限制) | 30 | 无限制 | 由付费套餐决定 |
| 自定义版权信息 | ❌ | ✅ | 设计中 |
| 多租户与支付 | ❌ | ✅ | ✅ |
| 团队空间 | ❌ | ✅ | ✅ |
| 团队空间 & 权限 | ❌ | ✅ | ✅ |
| 应用发布安全配置 | ❌ | ✅ | ✅ |
| 内容审核 | ❌ | ✅ | ✅ |
| web站点同步 | ❌ | ✅ | ✅ |
| 管理后台 | ❌ | ✅ | 不需要 |
| 主流文档库接入(目前支持:语雀、飞书) | ❌ | ✅ | |
| 增强训练模式 | ❌ | ✅ | ✅ |
| 第三方应用快速接入(飞书、公众号) | ❌ | ✅ | ✅ |
| 管理后台 | ❌ | ✅ | 不需要 |
| SSO 登录可自定义也可使用内置Github、公众号、钉钉、谷歌等 | ❌ | ✅ | 不需要 |
| 图片知识库 | ❌ | 设计中 | 设计中 |
| 对话日志运营分析 | ❌ | 设计中 | 设计中 |
| 完整商业授权 | ❌ | ✅ | ✅ |
@@ -50,8 +53,8 @@ FastGPT 商业版软件根据不同的部署方式,分为 3 类收费模式。
{{< table "table-hover table-striped-columns" >}}
| 部署方式 | 特有服务 | 上线时长 | 标品价格 |
| ---- | ---- | ---- | ---- |
| Sealos全托管 | 1. 有效期内免费升级。<br>2. 免运维服务&数据库。 | 半天 | 5000元起/月3个月起<br><br>50000元起/年 |
| 自有服务器部署 | 1. 6个版本的升级服务。 | 14天内 | 具体价格可[联系咨询](https://fael3z0zfze.feishu.cn/share/base/form/shrcnRxj3utrzjywsom96Px4sud) |
| Sealos全托管 | 1. 有效期内免费升级。<br>2. 免运维服务&数据库。 | 半天 | 6000元起/月3个月起<br><br>60000元起/年 |
| 自有服务器部署 | 1. 6个版本免费升级支持。 | 14天内 | 具体价格可[联系咨询](https://fael3z0zfze.feishu.cn/share/base/form/shrcnRxj3utrzjywsom96Px4sud) |
{{< /table >}}
{{% alert icon="🤖 " context="success" %}}
@@ -62,6 +65,10 @@ FastGPT 商业版软件根据不同的部署方式,分为 3 类收费模式。
- 高可用版适合对外提供在线服务,包含可视化监控、多副本、负载均衡、数据库自动备份等生产环境的基础设施。
{{% /alert %}}
## 联系方式
请填写[咨询问卷](https://fael3z0zfze.feishu.cn/share/base/form/shrcnRxj3utrzjywsom96Px4sud),我们会尽快与您联系。
## 技术支持
@@ -79,9 +86,6 @@ FastGPT 商业版软件根据不同的部署方式,分为 3 类收费模式。
跨版本更新或复杂更新可参考文档自行更新;或付费支持,标准与技术服务费一致。
## 联系方式
请填写[咨询问卷](https://fael3z0zfze.feishu.cn/share/base/form/shrcnRxj3utrzjywsom96Px4sud),我们会尽快与您联系。
## QA
@@ -95,8 +99,14 @@ FastGPT 商业版软件根据不同的部署方式,分为 3 类收费模式。
可以修改开源版部分代码,不支持修改商业版镜像。完整版本=开源版+商业版镜像,所以是可以修改部分内容的。但是如果二开了,后续则需要自己进行代码合并升级。
## Sealos 费用
### Sealos 运行费用
Sealos 云服务属于按量计费,下面是它的价格表:
![](/imgs/sealos_price.jpg)
![alt text](/imgs/image-58.png)
## 管理后台部分截图
| | | |
| ---- | ---- | ---- |
| ![alt text](/imgs/image-55.png) | ![alt text](/imgs/image-56.png) | ![alt text](/imgs/image-57.png) |

View File

@@ -5,7 +5,7 @@ import type {
LLMModelItemType,
VectorModelItemType,
AudioSpeechModels,
WhisperModelType,
STTModelType,
ReRankModelItemType
} from '../../../core/ai/model.d';
import { SubTypeEnum } from '../../../support/wallet/sub/constants';
@@ -27,7 +27,7 @@ export type FastGPTConfigFileType = {
vectorModels: VectorModelItemType[];
reRankModels: ReRankModelItemType[];
audioSpeechModels: AudioSpeechModelType[];
whisperModel: WhisperModelType;
whisperModel: STTModelType;
};
export type FastGPTFeConfigsType = {

View File

@@ -57,13 +57,15 @@ export type ReRankModelItemType = {
};
export type AudioSpeechModelType = {
provider: ModelProviderIdType;
model: string;
name: string;
charsPointsPrice: number;
voices: { label: string; value: string; bufferId: string }[];
};
export type WhisperModelType = {
export type STTModelType = {
provider: ModelProviderIdType;
model: string;
name: string;
charsPointsPrice: number; // 60s = n points

View File

@@ -1,4 +1,5 @@
import type { LLMModelItemType, VectorModelItemType } from './model.d';
import { i18nT } from '../../../web/i18n/utils';
import type { LLMModelItemType, STTModelType, VectorModelItemType } from './model.d';
import { getModelProvider, ModelProviderIdType } from './provider';
export const defaultQAModels: LLMModelItemType[] = [
@@ -35,6 +36,13 @@ export const defaultVectorModels: VectorModelItemType[] = [
}
];
export const defaultWhisperModel: STTModelType = {
provider: 'OpenAI',
model: 'whisper-1',
name: 'whisper-1',
charsPointsPrice: 0
};
export const getModelFromList = (
modelList: { provider: ModelProviderIdType; name: string; model: string }[],
model: string
@@ -46,3 +54,16 @@ export const getModelFromList = (
avatar: provider.avatar
};
};
export enum ModelTypeEnum {
chat = 'chat',
embedding = 'embedding',
tts = 'tts',
stt = 'stt'
}
export const modelTypeList = [
{ label: i18nT('common:model.type.chat'), value: ModelTypeEnum.chat },
{ label: i18nT('common:model.type.embedding'), value: ModelTypeEnum.embedding },
{ label: i18nT('common:model.type.tts'), value: ModelTypeEnum.tts },
{ label: i18nT('common:model.type.stt'), value: ModelTypeEnum.stt }
];

View File

@@ -5,6 +5,7 @@ export type ModelProviderIdType =
| 'Claude'
| 'Gemini'
| 'MistralAI'
| 'Groq'
| 'Qwen'
| 'Doubao'
| 'ChatGLM'
@@ -44,7 +45,12 @@ export const ModelProviderList: ModelProviderType[] = [
{
id: 'MistralAI',
name: 'MistralAI',
avatar: 'model/huggingface'
avatar: 'model/mistral'
},
{
id: 'Groq',
name: 'Groq',
avatar: 'model/groq'
},
{
id: 'Qwen',
@@ -113,7 +119,7 @@ export const ModelProviderList: ModelProviderType[] = [
}
];
export const ModelProviderMap = Object.fromEntries(
ModelProviderList.map((item) => [item.id, item])
ModelProviderList.map((item, index) => [item.id, { ...item, order: index }])
);
export const getModelProvider = (provider: ModelProviderIdType) => {

View File

@@ -4,7 +4,12 @@ import { FastGPTConfigFileType } from '@fastgpt/global/common/system/types';
import { FastGPTProUrl } from '../constants';
export const getFastGPTConfigFromDB = async () => {
if (!FastGPTProUrl) return {} as FastGPTConfigFileType;
if (!FastGPTProUrl) {
return {
config: {} as FastGPTConfigFileType,
configId: undefined
};
}
const res = await MongoSystemConfigs.findOne({
type: SystemConfigsTypeEnum.fastgpt
@@ -14,5 +19,8 @@ export const getFastGPTConfigFromDB = async () => {
const config = res?.value || {};
return config as FastGPTConfigFileType;
return {
configId: res ? String(res._id) : undefined,
config: config as FastGPTConfigFileType
};
};

View File

@@ -39,8 +39,6 @@ export const computedTemperature = ({
model: LLMModelItemType;
temperature: number;
}) => {
if (temperature < 1) return temperature;
temperature = +(model.maxTemperature * (temperature / 10)).toFixed(2);
temperature = Math.max(temperature, 0.01);

View File

@@ -2,6 +2,5 @@ import { PluginTemplateType } from '@fastgpt/global/core/plugin/type.d';
import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type';
declare global {
var communityPluginsV1: PluginTemplateType[];
var communityPlugins: SystemPluginTemplateItemType[];
}

View File

@@ -2,7 +2,7 @@ import { FastGPTFeConfigsType, SystemEnvType } from '@fastgpt/global/common/syst
import {
AudioSpeechModelType,
ReRankModelItemType,
WhisperModelType,
STTModelType,
VectorModelItemType,
LLMModelItemType
} from '@fastgpt/global/core/ai/model.d';
@@ -12,6 +12,7 @@ import { Worker } from 'worker_threads';
import { TemplateMarketItemType } from '@fastgpt/global/core/workflow/type';
declare global {
var systemInitBufferId: string | undefined;
var systemVersion: string;
var feConfigs: FastGPTFeConfigsType;
var systemEnv: SystemEnvType;
@@ -20,7 +21,7 @@ declare global {
var llmModels: LLMModelItemType[];
var vectorModels: VectorModelItemType[];
var audioSpeechModels: AudioSpeechModelType[];
var whisperModel: WhisperModelType;
var whisperModel: STTModelType;
var reRankModels: ReRankModelItemType[];
var workerPoll: Record<WorkerNameEnum, WorkerPool>;

View File

@@ -56,7 +56,7 @@ export const iconPaths = {
'common/loading': () => import('./icons/common/loading.svg'),
'common/logLight': () => import('./icons/common/logLight.svg'),
'common/microsoft': () => import('./icons/common/microsoft.svg'),
'common/modal': () => import('./icons/common/modal.svg'),
'common/model': () => import('./icons/common/model.svg'),
'common/monitor': () => import('./icons/common/monitor.svg'),
'common/more': () => import('./icons/common/more.svg'),
'common/moreFill': () => import('./icons/common/moreFill.svg'),
@@ -348,9 +348,11 @@ export const iconPaths = {
'model/doubao': () => import('./icons/model/doubao.svg'),
'model/ernie': () => import('./icons/model/ernie.svg'),
'model/gemini': () => import('./icons/model/gemini.svg'),
'model/groq': () => import('./icons/model/groq.svg'),
'model/huggingface': () => import('./icons/model/huggingface.svg'),
'model/hunyuan': () => import('./icons/model/hunyuan.svg'),
'model/minimax': () => import('./icons/model/minimax.svg'),
'model/mistral': () => import('./icons/model/mistral.svg'),
'model/moonshot': () => import('./icons/model/moonshot.svg'),
'model/ollama': () => import('./icons/model/ollama.svg'),
'model/openai': () => import('./icons/model/openai.svg'),
@@ -395,7 +397,6 @@ export const iconPaths = {
'support/team/key': () => import('./icons/support/team/key.svg'),
'support/team/memberLight': () => import('./icons/support/team/memberLight.svg'),
'support/usage/usageRecordLight': () => import('./icons/support/usage/usageRecordLight.svg'),
'support/user/individuation': () => import('./icons/support/user/individuation.svg'),
'support/user/informLight': () => import('./icons/support/user/informLight.svg'),
'support/user/userFill': () => import('./icons/support/user/userFill.svg'),
'support/user/userLight': () => import('./icons/support/user/userLight.svg'),

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
<path d="M10.0289 1.21117C6.70605 1.18232 3.98312 3.85333 3.95427 7.17623C3.92543 10.4991 6.59644 13.2221 9.91933 13.2509H12.0077V10.9953H10.0289C7.95213 11.0183 6.24453 9.35688 6.22146 7.2743C6.19838 5.19172 7.85983 3.48989 9.94241 3.46682H10.0289C12.1058 3.46682 13.7903 5.15134 13.8018 7.22815V12.7721C13.8018 14.8316 12.1231 16.5103 10.0693 16.5334C9.08284 16.5276 8.14251 16.1296 7.45024 15.4316L5.85225 17.0295C6.95988 18.1429 8.4598 18.7775 10.0289 18.7891H10.1097C13.3922 18.7429 16.0286 16.0777 16.0459 12.7952V7.07816C15.9652 3.81872 13.2941 1.21694 10.0289 1.21117Z" fill="#F04E35"/>
</svg>

After

Width:  |  Height:  |  Size: 677 B

View File

@@ -1,13 +1 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_19_417)">
<path d="M8.69132 19.7708L8.43646 10.1106C7.92262 9.92227 9.99843 7.48009 10.8505 7.6956C13.3489 7.06769 16.0648 3.09118 11.1064 0.142151C-3.89673 0.142151 -2.25275 18.589 8.69132 19.7708Z" fill="#B3DDF2"/>
<path d="M8.64384 19.7663C4.17343 18.7386 -0.201612 12.4833 5.14972 6.86892C6.37883 5.78554 3.9237 2.58709 1.91253 4.3511C-3.43099 11.7411 3.5968 19.7863 8.64384 19.7663Z" fill="#0055E9"/>
<path d="M7.92307 10.4705C7.79974 10.5592 7.92307 10.4191 7.92307 10.4705V10.4705ZM7.92307 10.4705V11.2412C7.92307 11.344 7.77919 12.0274 7.71753 12.3203L8.48829 13.9646C8.48829 13.9646 9.00213 14.1187 9.05351 14.1701C9.1049 14.2215 9.35668 14.2575 9.46459 14.2729L10.5436 14.9409L12.3421 14.684L14.6544 13.9646L16.8125 12.1148L17.4805 10.9843L18.0457 8.1068L17.9429 6.77082V5.58898L16.7611 3.43086L16.1445 2.6601L15.0654 1.6838L14.1405 1.11858L13.8836 0.964424L13.5753 0.861657L13.0101 0.656121L11.2116 0.193665C15.1168 1.47826 15.4251 5.43483 14.2947 7.33604C13.1642 9.23725 10.715 10.3348 8.33414 10.1108L7.92307 10.4705Z" fill="#00BCFF"/>
<path d="M8.95026 19.7715C12.4444 20.6959 20.0974 17.3601 19.9978 10.2141C20.2549 7.02775 17.2808 0.68943 12.4444 0.451111C17.8362 1.54919 19.8961 11.4535 12.9079 13.9137C9.41293 14.7872 8.12863 12.1153 8.38607 10.2141C4.79042 10.3958 2.88305 18.1057 8.95026 19.7715Z" fill="#0055DF"/>
</g>
<defs>
<clipPath id="clip0_19_417">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>
<svg t="1735012417413" class="icon" viewBox="0 0 1032 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4293" width="64" height="64"><path d="M3.796984 0h1018.143079v1018.143079h-1018.143079z" fill="#CCCCCC" fill-opacity="0" p-id="4294"></path><path d="M448.476277 1016.17573l-13.151015-498.465883c-26.514143-9.720085 80.597691-135.736502 124.563442-124.61647 128.917065-32.400282 269.060217-237.58793 13.204043-389.757898-774.159938 0-689.33059 951.857722-124.61647 1012.840251z" fill="#B3DDF2" p-id="4295"></path><path d="M446.021067 1015.942405c-230.673041-53.028285-456.425058-375.800853-180.29617-665.504981 63.421829-55.902418-63.262744-220.942351-167.039099-129.919299-275.725873 381.3264 86.908057 796.458332 347.335269 795.42428z" fill="#0055E9" p-id="4296"></path><path d="M408.827028 536.27505c0-2.651414-6.363394 4.576341 0 0z m0 0v39.771214c0 5.302829-7.42396 40.566638-10.605657 55.679699l39.771214 84.845257s26.514143 7.954243 29.165557 10.605657 15.643344 4.507404 21.211314 5.302829l55.6797 34.468385 92.799499-13.257071 119.313642-37.1198 111.359399-95.450914 34.468386-58.331113 29.165557-148.479199-5.302829-68.936771v-60.982529l-60.982528-111.359399-31.816971-39.771214-55.6797-50.376871-47.725457-29.165557-13.257071-7.954243-15.908486-5.302828-29.165557-10.605657-92.799499-23.862729c201.507484 66.285357 217.41597 270.444255 159.084856 368.546583s-184.713426 154.736537-307.564055 143.176371l-21.211314 18.5599z" fill="#00BCFF" p-id="4297"></path><path d="M461.828799 1016.207546c180.29617 47.698943 575.192508-124.425569 570.054068-493.163053 13.267677-164.414199-140.196181-491.471452-389.757898-503.768711 278.218202 56.660723 384.508097 567.720823 23.915757 694.670538-180.338593 45.074043-246.608041-92.799499-233.324456-190.901827-185.535365 9.375401-283.955862 407.209506 29.112529 493.163053z" fill="#0055DF" p-id="4298"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
<path d="M3.84003 3.39999H6.48003V6.03999H3.84003V3.39999ZM14.4 3.39999H17.04V6.03999H14.4V3.39999Z" fill="#FECE00"/>
<path d="M3.84003 6.03999H6.48003V8.67999H3.84003V6.03999Z" fill="#FFA301"/>
<path d="M3.84003 11.32H6.48003V13.96H3.84003V11.32ZM9.12003 11.32H11.76V13.96H9.12003V11.32ZM14.4 11.32H17.04V13.96H14.4V11.32Z" fill="#FE4900"/>
<path d="M11.76 6.03999H14.4V8.67999H11.76V6.03999Z" fill="#FFA301"/>
<path d="M3.84003 8.67999H6.48003V11.32H3.84003V8.67999Z" fill="#FF6F00"/>
<path d="M3.84003 13.96H6.48003V16.6H3.84003V13.96ZM14.4 13.96H17.04V16.6H14.4V13.96Z" fill="#FE0107"/>
<path d="M11.76 8.67999H14.4V11.32H11.76V8.67999Z" fill="#FF6F00"/>
<path d="M6.47998 6.03999H9.11998V8.67999H6.47998V6.03999ZM14.4 6.03999H17.04V8.67999H14.4V6.03999Z" fill="#FFA301"/>
<path d="M6.47998 8.67999H9.11998V11.32H6.47998V8.67999ZM14.4 8.67999H17.04V11.32H14.4V8.67999ZM9.11998 8.67999H11.76V11.32H9.11998V8.67999Z" fill="#FF6F00"/>
<path d="M2.96002 3.39999H3.84002V16.6H2.96002V3.39999ZM13.52 3.39999H14.4V6.03999H13.52V3.39999ZM10.88 6.03999H11.76V8.67999H10.88V6.03999ZM8.24002 11.32H9.12002V13.96H8.24002V11.32ZM13.52 11.32H14.4V16.6H13.52V11.32Z" fill="#191D1D"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,119 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="181px" height="256px" viewBox="0 0 181 256" enable-background="new 0 0 181 256" xml:space="preserve"> <image id="image0" width="181" height="256" x="0" y="0"
xlink:href="data:image/png;base64,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
MDYrMDA6MDAeYvBBAAAAAElFTkSuQmCC" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
<path d="M5.62346 1.55468C4.79534 2.05468 4.27971 3.85937 4.46721 5.57031L4.53753 6.25L4.1469 6.64062C2.88127 7.89062 2.56096 9.82812 3.35784 11.3906L3.56877 11.8047L3.37346 12.2891C2.86565 13.5625 2.90471 15.1016 3.4594 16.2109L3.68596 16.6562L3.54534 16.9453C3.22502 17.6016 3.06877 19.0469 3.25627 19.7031L3.3344 20H4.51409L4.45159 19.7422C4.41253 19.6094 4.38128 19.1406 4.38128 18.7109C4.38128 17.9687 4.3969 17.8984 4.67815 17.3125C4.8344 16.9766 4.96721 16.6406 4.96721 16.5703C4.96721 16.5 4.85784 16.2656 4.71721 16.0469C4.0219 14.9609 4.00627 13.6328 4.66252 12.3281C4.95159 11.75 4.94377 11.5703 4.62346 11.1797C4.18596 10.6641 3.97502 9.82812 4.10784 9.14062C4.29534 8.15625 4.8969 7.32812 5.7094 6.94531C6.10003 6.75781 6.27971 6.71875 6.77971 6.71875H7.38909L7.54534 6.40625C7.90471 5.69531 8.52971 5.20312 9.37346 4.96093C10.4594 4.64062 11.8031 5.25 12.3969 6.33593L12.5844 6.67968L13.2485 6.71875C14.3813 6.79687 15.0688 7.25 15.561 8.24218C16.061 9.25781 15.9985 10.3359 15.3969 11.125C15.061 11.5625 15.061 11.75 15.35 12.3281C16.0063 13.6328 15.9907 14.9609 15.2953 16.0469C15.1547 16.2656 15.0453 16.5 15.0453 16.5703C15.0453 16.6406 15.1782 16.9766 15.3344 17.3125C15.6157 17.8984 15.6313 17.9687 15.6313 18.7109C15.6313 19.1406 15.6 19.6094 15.561 19.7422L15.4985 20H16.6782L16.7563 19.7109C16.9438 19.0469 16.7875 17.6016 16.4672 16.9453L16.3266 16.6562L16.5532 16.2109C17.1078 15.1016 17.1469 13.5625 16.6313 12.2734L16.436 11.7812L16.6469 11.3516C17.1157 10.3828 17.1782 9.22656 16.8032 8.13281C16.5922 7.50781 16.311 7.0625 15.811 6.58593L15.475 6.25L15.5453 5.57031C15.686 4.28125 15.3735 2.67187 14.85 1.98437C14.436 1.4375 13.8813 1.27343 13.3032 1.51562C12.7719 1.73437 12.311 2.52343 12.0922 3.59375C11.9907 4.10156 11.936 4.21093 11.8422 4.17187C11.1782 3.86718 10.6625 3.75 9.99065 3.75C9.30315 3.75 8.95159 3.83593 8.17034 4.17187C8.07659 4.21093 8.0219 4.10156 7.92034 3.59375C7.70159 2.52343 7.24065 1.73437 6.7094 1.51562C6.35002 1.35937 5.90471 1.38281 5.62346 1.55468ZM6.51409 2.99218C6.82659 3.63281 7.04534 5.15625 6.85784 5.4375C6.82659 5.48437 6.59221 5.54687 6.3344 5.57812C6.07659 5.60937 5.80315 5.64843 5.73284 5.67187C5.60784 5.71093 5.59221 5.64062 5.59221 4.94531C5.59221 4.52343 5.6469 3.96093 5.7094 3.6875C5.85003 3.10156 6.11565 2.55468 6.24065 2.60156C6.28752 2.61718 6.41252 2.79687 6.51409 2.99218ZM14.0297 2.89062C14.2797 3.375 14.4203 4.11718 14.4203 4.95312C14.4203 5.55468 14.3969 5.71093 14.3188 5.67968C14.2563 5.65625 13.975 5.61718 13.6938 5.58593C13.0688 5.51562 13.0453 5.47656 13.1157 4.53125C13.186 3.6875 13.5688 2.57812 13.8032 2.57812C13.8422 2.57812 13.9438 2.71875 14.0297 2.89062Z" fill="black"/>
<path d="M8.85785 9.36718C7.98285 9.71874 7.3891 10.2969 7.18598 11C6.88129 12.0547 7.35004 12.9766 8.44379 13.4922C8.8891 13.6953 8.97504 13.7109 10.0063 13.7109C11.0375 13.7109 11.1235 13.6953 11.5688 13.4922C12.3735 13.1172 12.8188 12.5547 12.9125 11.8047C13.0141 10.8984 12.4438 9.99999 11.4672 9.51561C10.9907 9.27343 10.8813 9.2578 10.0844 9.24218C9.39691 9.22655 9.15473 9.24999 8.85785 9.36718ZM10.85 10.125C11.0454 10.1875 11.3657 10.3828 11.561 10.5547C12.2485 11.1641 12.3032 11.8906 11.6938 12.4453C11.2719 12.8281 10.9125 12.9297 10.0063 12.9297C9.10004 12.9297 8.74066 12.8281 8.31879 12.4453C7.70941 11.8906 7.7641 11.1641 8.4516 10.5547C8.64691 10.3828 8.9516 10.1953 9.13129 10.125C9.56879 9.97655 10.4047 9.96874 10.85 10.125Z" fill="black"/>
<path d="M9.38911 10.9141C9.27974 11.0234 9.35005 11.4063 9.49068 11.5C9.58443 11.5703 9.65474 11.7188 9.67036 11.9141C9.6938 12.2188 9.70161 12.2266 10.0063 12.2266C10.311 12.2266 10.3188 12.2188 10.3266 11.9297C10.3266 11.7344 10.3891 11.5859 10.4985 11.4844C10.686 11.3047 10.7251 11.0781 10.5766 10.9609C10.4672 10.875 9.46724 10.8438 9.38911 10.9141ZM6.09224 9.38282C5.73286 9.56251 5.54536 10.2578 5.77193 10.5547C5.91255 10.7344 6.17818 10.8594 6.43599 10.8594C6.77193 10.8594 7.15474 10.4063 7.15474 10.0156C7.15474 9.85938 7.10786 9.67188 7.05318 9.60157C6.83443 9.32032 6.42818 9.22657 6.09224 9.38282ZM13.2094 9.39063C12.9594 9.53126 12.8657 9.70313 12.8579 10.0156C12.8579 10.4063 13.2407 10.8594 13.5766 10.8594C14.0297 10.8594 14.3344 10.5859 14.3422 10.1719C14.3422 9.53126 13.7172 9.10157 13.2094 9.39063Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,10 +1,14 @@
<svg viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="300" cy="300" r="300" fill="white" />
<rect x="409.733" y="340.032" width="42.3862" height="151.648" rx="21.1931" fill="#003425" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M422.005 133.354C413.089 125.771 399.714 126.851 392.131 135.768L273.699 275.021C270.643 278.614 268.994 282.932 268.698 287.302C268.532 288.371 268.446 289.466 268.446 290.581V468.603C268.446 480.308 277.934 489.796 289.639 489.796C301.344 489.796 310.832 480.308 310.832 468.603V296.784L424.419 163.228C432.002 154.312 430.921 140.937 422.005 133.354Z"
fill="#003425" />
<rect x="113.972" y="134.25" width="42.3862" height="174.745" rx="21.1931"
transform="rotate(-39.3441 113.972 134.25)" fill="#003425" />
<circle cx="460.126" cy="279.278" r="25.9027" fill="#00DD20" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
<g clip-path="url(#clip0_12804_895)">
<path d="M10 20C15.5229 20 20 15.5229 20 10C20 4.47712 15.5229 0 10 0C4.47712 0 0 4.47712 0 10C0 15.5229 4.47712 20 10 20Z" fill="#003425"/>
<path d="M15.0706 12.0408C15.0706 11.8535 14.9962 11.6738 14.8637 11.5413C14.7312 11.4088 14.5515 11.3344 14.3642 11.3344C14.1768 11.3344 13.9972 11.4088 13.8647 11.5413C13.7322 11.6738 13.6578 11.8535 13.6578 12.0408V15.6829C13.6578 15.8702 13.7322 16.0499 13.8647 16.1824C13.9972 16.3149 14.1768 16.3893 14.3642 16.3893C14.5515 16.3893 14.7312 16.3149 14.8637 16.1824C14.9962 16.0499 15.0706 15.8702 15.0706 15.6829V12.0408Z" fill="white"/>
<path d="M14.0669 4.44512C13.9962 4.38501 13.9144 4.33941 13.8261 4.31092C13.7378 4.28243 13.6448 4.27162 13.5523 4.27909C13.4598 4.28656 13.3697 4.31218 13.2872 4.35448C13.2046 4.39677 13.1312 4.45492 13.0711 4.5256L9.12338 9.16752C9.02527 9.28249 8.96681 9.426 8.95666 9.5768C8.95106 9.61248 8.94818 9.6488 8.94818 9.68608V15.6202C8.94818 15.8075 9.02261 15.9872 9.15508 16.1197C9.28756 16.2521 9.46723 16.3266 9.65458 16.3266C9.84193 16.3266 10.0216 16.2521 10.1541 16.1197C10.2866 15.9872 10.361 15.8075 10.361 15.6202V9.8928L14.1474 5.44096C14.2075 5.37029 14.2531 5.28847 14.2816 5.20018C14.3101 5.11189 14.3209 5.01885 14.3134 4.92637C14.3059 4.8339 14.2803 4.7438 14.238 4.66123C14.1957 4.57865 14.1376 4.50522 14.0669 4.44512Z" fill="white"/>
<path d="M5.33953 4.12561C5.28072 4.05387 5.20835 3.99441 5.12656 3.95063C5.04477 3.90686 4.95516 3.87962 4.86285 3.87048C4.77053 3.86133 4.67732 3.87046 4.58853 3.89734C4.49974 3.92422 4.41711 3.96832 4.34537 4.02713C4.27363 4.08594 4.21417 4.15831 4.17039 4.2401C4.12662 4.32189 4.09938 4.4115 4.09023 4.50382C4.08109 4.59613 4.09022 4.68935 4.11709 4.77814C4.14397 4.86692 4.18808 4.94955 4.24689 5.02129L7.04401 8.43329C7.16278 8.57821 7.33426 8.67 7.52072 8.68849C7.70717 8.70697 7.89334 8.65063 8.03825 8.53185C8.18316 8.41308 8.27496 8.2416 8.29344 8.05515C8.31193 7.86869 8.25558 7.68253 8.13681 7.53761L5.33937 4.12561H5.33953Z" fill="white"/>
<path d="M15.3376 10.1727C15.5666 10.1727 15.7862 10.0817 15.9482 9.91975C16.1101 9.75783 16.2011 9.53821 16.2011 9.30921C16.2011 9.08021 16.1101 8.86059 15.9482 8.69867C15.7862 8.53674 15.5666 8.44577 15.3376 8.44577C15.1086 8.44577 14.889 8.53674 14.7271 8.69867C14.5652 8.86059 14.4742 9.08021 14.4742 9.30921C14.4742 9.53821 14.5652 9.75783 14.7271 9.91975C14.889 10.0817 15.1086 10.1727 15.3376 10.1727Z" fill="#00FF25"/>
</g>
<defs>
<clipPath id="clip0_12804_895">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 892 B

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M8.95334 16.4281C9.05498 16.5828 8.93673 16.8071 8.75405 16.777C7.16443 16.5146 5.94181 15.8533 5.05187 14.9994C3.73702 13.7379 3.01725 11.931 3.01725 9.9769C3.01725 6.18011 6.09515 3.10221 9.89194 3.10221C13.8727 3.10221 16.9827 5.87983 16.9827 9.50285C16.9827 10.4282 16.7524 10.9955 16.4763 11.3538C16.1992 11.7133 15.7615 12.011 15.0821 12.191C14.485 12.3493 13.879 12.3607 13.0988 12.3754C12.9461 12.3782 12.7868 12.3812 12.6195 12.3855C11.7922 12.4065 10.4224 12.4464 9.36346 13.3001C8.72411 13.8156 8.524 14.5121 8.52868 15.0653C8.5328 15.5521 8.68681 15.9446 8.79908 16.1635C8.84683 16.2566 8.89859 16.3447 8.95334 16.4281ZM15.5091 13.8021C17.4217 13.2951 18.6494 11.9261 18.6494 9.50285C18.6494 4.7856 14.6092 1.43555 9.89194 1.43555C5.17468 1.43555 1.35059 5.25964 1.35059 9.9769C1.35059 14.6942 4.8343 19.0091 11.2788 18.5298C12.2308 18.459 12.5569 17.3597 12.122 16.8903C11.89 16.6399 11.5858 16.4575 11.2857 16.2776C10.8812 16.035 10.4842 15.797 10.2821 15.4029C10.214 15.2701 10.0763 14.8663 10.4095 14.5977C11.0553 14.0771 12.0167 14.0611 13.082 14.0434C13.8631 14.0304 14.7 14.0165 15.5091 13.8021ZM6.85887 9.40095C6.85887 10.1411 6.25883 10.7412 5.51863 10.7412C4.77844 10.7412 4.1784 10.1411 4.1784 9.40095C4.1784 8.66076 4.77844 8.06071 5.51863 8.06071C6.25883 8.06071 6.85887 8.66076 6.85887 9.40095ZM8.09584 7.52192C8.83604 7.52192 9.43608 6.92187 9.43608 6.18168C9.43608 5.44149 8.83604 4.84144 8.09584 4.84144C7.35565 4.84144 6.75561 5.44149 6.75561 6.18168C6.75561 6.92187 7.35565 7.52192 8.09584 7.52192ZM13.4525 6.18168C13.4525 6.92187 12.8525 7.52192 12.1123 7.52192C11.3721 7.52192 10.772 6.92187 10.772 6.18168C10.772 5.44149 11.3721 4.84144 12.1123 4.84144C12.8525 4.84144 13.4525 5.44149 13.4525 6.18168ZM14.4814 10.7412C15.2216 10.7412 15.8216 10.1411 15.8216 9.40095C15.8216 8.66076 15.2216 8.06071 14.4814 8.06071C13.7412 8.06071 13.1411 8.66076 13.1411 9.40095C13.1411 10.1411 13.7412 10.7412 14.4814 10.7412Z" />
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -110,7 +110,7 @@ const MySelect = <T = any,>(
px={3}
rightIcon={<MyIcon name={'core/chat/chevronDown'} w={4} color={'myGray.500'} />}
variant={'whitePrimaryOutline'}
size={'lg'}
size={'md'}
fontSize={'sm'}
textAlign={'left'}
_active={{

View File

@@ -3,6 +3,7 @@
"bills_and_invoices": "Bills",
"confirm_logout": "Confirm to log out?",
"logout": "Sign out",
"model_provider": "Model Provider",
"notifications": "Notify",
"personal_information": "Personal",
"personalization": "Personalization",

View File

@@ -896,6 +896,15 @@
"item_name": "Field Name",
"just_now": "just",
"key_repetition": "Key Repetition",
"model.billing": "Billing",
"model.model_type": "Model type",
"model.name": "Model name",
"model.provider": "Provider",
"model.search_name_placeholder": "Search by model name",
"model.type.chat": "language model",
"model.type.embedding": "Embedding",
"model.type.stt": "speech recognition",
"model.type.tts": "TTS",
"model_baichuan": "Baichuan",
"model_chatglm": "ChatGLM",
"model_doubao": "Doubao",

View File

@@ -22,7 +22,6 @@
"delete.failed": "Delete failed",
"delete.success": "Delete successfully",
"has_chosen": "Selected",
"individuation": "Individuation",
"login.error": "Login Error",
"login.password_condition": "Password can be up to 60 characters",
"login.success": "Login Successful",

View File

@@ -1,12 +1,13 @@
{
"personal_information": "个人信息",
"usage_records": "使用记录",
"bills_and_invoices": "账单与发票",
"promotion_records": "促销记录",
"api_key": "API 密钥",
"personalization": "个性化",
"notifications": "通知",
"logout": "登出",
"bills_and_invoices": "账单与发票",
"confirm_logout": "确认退出登录?",
"team": "团队管理"
"logout": "登出",
"model_provider": "模型提供商",
"notifications": "通知",
"personal_information": "个人信息",
"personalization": "个性化",
"promotion_records": "促销记录",
"team": "团队管理",
"usage_records": "使用记录"
}

View File

@@ -895,13 +895,22 @@
"item_name": "字段名",
"just_now": "刚刚",
"key_repetition": "key 重复",
"model.billing": "模型计费",
"model.model_type": "模型类型",
"model.name": "模型名",
"model.provider": "模型提供商",
"model.search_name_placeholder": "根据模型名搜索",
"model.type.chat": "语言模型",
"model.type.embedding": "索引模型",
"model.type.stt": "语音识别",
"model.type.tts": "语音合成",
"model_baichuan": "百川智能",
"model_chatglm": "ChatGLM",
"model_doubao": "豆包",
"model_ernie": "文心一言",
"model_hunyuan": "腾讯混元",
"model_moonshot": "月之暗面",
"model_other": "自定义",
"model_other": "其他",
"model_qwen": "阿里千问",
"model_sparkdesk": "讯飞星火",
"model_yi": "零一万物",

View File

@@ -22,7 +22,6 @@
"delete.failed": "删除失败",
"delete.success": "删除成功",
"has_chosen": "已选择",
"individuation": "个性化",
"login.error": "登录异常",
"login.password_condition": "密码最多 60 位",
"login.success": "登录成功",

View File

@@ -3,6 +3,7 @@
"bills_and_invoices": "帳單與發票",
"confirm_logout": "確認登出登入?",
"logout": "登出",
"model_provider": "模型提供者",
"notifications": "通知",
"personal_information": "個人資訊",
"personalization": "個人化",

View File

@@ -897,13 +897,21 @@
"item_name": "欄位名稱",
"just_now": "剛剛",
"key_repetition": "鍵值重複",
"model.billing": "模型計費",
"model.model_type": "模型類型",
"model.name": "模型名",
"model.provider": "模型提供者",
"model.search_name_placeholder": "根據模型名搜尋",
"model.type.chat": "語言模型",
"model.type.stt": "語音辨識",
"model.type.tts": "語音合成",
"model_baichuan": "百川智能",
"model_chatglm": "ChatGLM",
"model_doubao": "豆包",
"model_ernie": "文心一言",
"model_hunyuan": "騰訊混元",
"model_moonshot": "月之暗面",
"model_other": "自訂",
"model_other": "其他",
"model_qwen": "阿里千問",
"model_sparkdesk": "訊飛星火",
"model_yi": "零一萬物",

View File

@@ -22,7 +22,6 @@
"delete.failed": "刪除失敗",
"delete.success": "刪除成功",
"has_chosen": "已選擇",
"individuation": "個人化",
"login.error": "登入失敗",
"login.password_condition": "密碼最多可輸入 60 個字元",
"login.success": "登入成功",

View File

@@ -3,7 +3,7 @@ import account_team from '../i18n/zh-CN/account_team.json';
import account from '../i18n/zh-CN/account.json';
import account_promotion from '../i18n/zh-CN/account_promotion.json';
import account_inform from '../i18n/zh-CN/account_inform.json';
import account_individuation from '../i18n/zh-CN/account_individuation.json';
import account_setting from '../i18n/zh-CN/account_setting.json';
import account_apikey from '../i18n/zh-CN/account_apikey.json';
import account_bill from '../i18n/zh-CN/account_bill.json';
import account_usage from '../i18n/zh-CN/account_usage.json';
@@ -32,7 +32,7 @@ export interface I18nNamespaces {
account_usage: typeof account_usage;
account_bill: typeof account_bill;
account_apikey: typeof account_apikey;
account_individuation: typeof account_individuation;
account_setting: typeof account_setting;
account_inform: typeof account_inform;
account_promotion: typeof account_promotion;
account: typeof account;
@@ -66,7 +66,7 @@ declare module 'i18next' {
'account_usage',
'account_bill',
'account_apikey',
'account_individuation',
'account_setting',
'account_inform',
'account_promotion',
'account',

View File

@@ -61,7 +61,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
// System hook
const { data, refetch: refetchUnRead } = useQuery(['getUnreadCount'], getUnreadCount, {
enabled: !!userInfo && !!feConfigs.isPlus,
refetchInterval: 10000
refetchInterval: 30000
});
const unread = data?.unReadCount || 0;
const importantInforms = data?.importantInforms || [];

View File

@@ -83,9 +83,10 @@ const Navbar = ({ unread }: { unread: number }) => {
'/account/team',
'/account/usage',
'/account/apikey',
'/account/individuation',
'/account/setting',
'/account/inform',
'/account/promotion'
'/account/promotion',
'/account/model'
]
}
],

View File

@@ -55,9 +55,10 @@ const NavbarPhone = ({ unread }: { unread: number }) => {
'/account/team',
'/account/usage',
'/account/apikey',
'/account/individuation',
'/account/setting',
'/account/inform',
'/account/promotion'
'/account/promotion',
'/account/model'
],
unread
}

View File

@@ -12,8 +12,8 @@ import { ModelProviderList } from '@fastgpt/global/core/ai/provider';
import MultipleRowSelect from '@fastgpt/web/components/common/MySelect/MultipleRowSelect';
import { getModelFromList } from '@fastgpt/global/core/ai/model';
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
type Props = SelectProps & {
@@ -103,7 +103,7 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => {
/>
</MyTooltip>
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Box>
);
};
@@ -212,7 +212,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
/>
</MyTooltip>
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Box>
);
};

View File

@@ -33,8 +33,8 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import dynamic from 'next/dynamic';
import InputSlider from '@fastgpt/web/components/common/MySlider/InputSlider';
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
const FlexItemStyles: FlexProps = {
@@ -328,7 +328,7 @@ const AIChatSettingsModal = ({
</Button>
</ModalFooter>
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</MyModal>
);
};

View File

@@ -0,0 +1,251 @@
import {
Box,
Flex,
HStack,
ModalBody,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr
} from '@chakra-ui/react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import React, { useMemo, useRef, useState } from 'react';
import {
ModelProviderList,
ModelProviderIdType,
getModelProvider
} from '@fastgpt/global/core/ai/provider';
import MySelect from '@fastgpt/web/components/common/MySelect';
import { modelTypeList, ModelTypeEnum } from '@fastgpt/global/core/ai/model';
import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTag from '@fastgpt/web/components/common/Tag/index';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
const ModelTable = () => {
const { t } = useTranslation();
const [provider, setProvider] = useState<ModelProviderIdType | ''>('');
const providerList = useRef<{ label: any; value: ModelProviderIdType | '' }[]>([
{ label: t('common:common.All'), value: '' },
...ModelProviderList.map((item) => ({
label: (
<HStack>
<Avatar src={item.avatar} w={'1rem'} />
<Box>{t(item.name as any)}</Box>
</HStack>
),
value: item.id
}))
]);
const [modelType, setModelType] = useState<ModelTypeEnum | ''>('');
const selectModelTypeList = useRef<{ label: string; value: ModelTypeEnum | '' }[]>([
{ label: t('common:common.All'), value: '' },
...modelTypeList.map((item) => ({ label: t(item.label), value: item.value }))
]);
const [search, setSearch] = useState('');
const { llmModelList, audioSpeechModelList, vectorModelList, whisperModel } = useSystemStore();
const modelList = useMemo(() => {
const formatLLMModelList = llmModelList.map((item) => ({
...item,
typeLabel: t('common:model.type.chat'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
</Box>
{`${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
),
tagColor: 'blue'
}));
const formatVectorModelList = vectorModelList.map((item) => ({
...item,
typeLabel: t('common:model.type.embedding'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
),
tagColor: 'yellow'
}));
const formatAudioSpeechModelList = audioSpeechModelList.map((item) => ({
...item,
typeLabel: t('common:model.type.tts'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K ${t('common:unit.character')}`}
</Flex>
),
tagColor: 'green'
}));
const formatWhisperModel = {
...whisperModel,
typeLabel: t('common:model.type.stt'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{whisperModel.charsPointsPrice}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 60${t('common:unit.seconds')}`}
</Flex>
),
tagColor: 'purple'
};
const list = (() => {
if (modelType === ModelTypeEnum.chat) return formatLLMModelList;
if (modelType === ModelTypeEnum.embedding) return formatVectorModelList;
if (modelType === ModelTypeEnum.tts) return formatAudioSpeechModelList;
if (modelType === ModelTypeEnum.stt) return [formatWhisperModel];
return [
...formatLLMModelList,
...formatVectorModelList,
...formatAudioSpeechModelList,
formatWhisperModel
];
})();
const formatList = list.map((item) => {
const provider = getModelProvider(item.provider);
return {
name: item.name,
avatar: provider.avatar,
providerId: provider.id,
providerName: t(provider.name as any),
typeLabel: item.typeLabel,
priceLabel: item.priceLabel,
order: provider.order,
tagColor: item.tagColor
};
});
formatList.sort((a, b) => a.order - b.order);
const filterList = formatList.filter((item) => {
const providerFilter = provider ? item.providerId === provider : true;
const regx = new RegExp(search, 'i');
const nameFilter = search ? regx.test(item.name) : true;
return providerFilter && nameFilter;
});
return filterList;
}, [
provider,
modelType,
llmModelList,
vectorModelList,
audioSpeechModelList,
whisperModel,
t,
search
]);
return (
<Flex flexDirection={'column'} h={'100%'}>
<Flex>
<HStack flexShrink={0}>
<Box fontSize={'sm'} color={'myGray.900'}>
{t('common:model.provider')}
</Box>
<MySelect
w={'200px'}
bg={'myGray.50'}
value={provider}
onchange={setProvider}
list={providerList.current}
/>
</HStack>
<HStack flexShrink={0} ml={6}>
<Box fontSize={'sm'} color={'myGray.900'}>
{t('common:model.model_type')}
</Box>
<MySelect
w={'150px'}
bg={'myGray.50'}
value={modelType}
onchange={setModelType}
list={selectModelTypeList.current}
/>
</HStack>
<Box flex={1} />
<Box flex={'0 0 250px'}>
<SearchInput
bg={'myGray.50'}
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder={t('common:model.search_name_placeholder')}
/>
</Box>
</Flex>
<TableContainer mt={5} flex={'1 0 0'} h={0} overflowY={'auto'}>
<Table>
<Thead>
<Tr color={'myGray.600'}>
<Th fontSize={'xs'}>{t('common:model.name')}</Th>
<Th fontSize={'xs'}>{t('common:model.model_type')}</Th>
<Th fontSize={'xs'}>{t('common:model.billing')}</Th>
</Tr>
</Thead>
<Tbody>
{modelList.map((item) => (
<Tr key={item.name} _hover={{ bg: 'myGray.50' }}>
<Td fontSize={'sm'}>
<MyTooltip title={item.providerName}>
<HStack>
<Avatar src={item.avatar} w={'1.2rem'} />
<Box color={'myGray.900'}>{item.name}</Box>
</HStack>
</MyTooltip>
</Td>
<Td>
<MyTag colorSchema={item.tagColor as any}>{item.typeLabel}</MyTag>
</Td>
<Td fontSize={'sm'}>{item.priceLabel}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</Flex>
);
};
export default ModelTable;
export const ModelPriceModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation();
return (
<MyModal
isCentered
iconSrc="/imgs/modal/bill.svg"
title={t('common:support.wallet.subscription.Ai points')}
isOpen
onClose={onClose}
w={'100%'}
h={'100%'}
maxW={'90vw'}
maxH={'90vh'}
>
<ModalBody flex={'1 0 0'}>
<ModelTable />
</ModalBody>
</MyModal>
);
};

View File

@@ -8,8 +8,8 @@ import { useTranslation } from 'next-i18next';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import dynamic from 'next/dynamic';
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
const StandardPlanContentList = ({
@@ -127,7 +127,7 @@ const StandardPlanContentList = ({
<Box color={'myGray.600'}>{t('common:support.wallet.subscription.web_site_sync')}</Box>
</Flex>
)}
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Grid>
) : null;
};

View File

@@ -2,7 +2,7 @@ import type {
LLMModelItemType,
VectorModelItemType,
AudioSpeechModels,
WhisperModelType,
STTModelType,
ReRankModelItemType
} from '@fastgpt/global/core/ai/model.d';
@@ -10,11 +10,12 @@ import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/i
import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type';
export type InitDateResponse = {
bufferId?: string;
llmModels: LLMModelItemType[];
vectorModels: VectorModelItemType[];
audioSpeechModels: AudioSpeechModels[];
reRankModels: ReRankModelItemType[];
whisperModel: WhisperModelType;
whisperModel: STTModelType;
feConfigs: FastGPTFeConfigsType;
subPlans?: SubPlanType;
systemVersion: string;

View File

@@ -8,9 +8,7 @@ import PageContainer from '@/components/PageContainer';
import SideTabs from '@/components/SideTabs';
import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
import { useTranslation } from 'next-i18next';
import Script from 'next/script';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
export enum TabEnum {
'info' = 'info',
@@ -18,10 +16,11 @@ export enum TabEnum {
'usage' = 'usage',
'bill' = 'bill',
'inform' = 'inform',
'individuation' = 'individuation',
'setting' = 'setting',
'apikey' = 'apikey',
'loginout' = 'loginout',
'team' = 'team'
'team' = 'team',
'model' = 'model'
}
const AccountContainer = ({
@@ -71,6 +70,11 @@ const AccountContainer = ({
}
]
: []),
{
icon: 'common/model',
label: t('account:model_provider'),
value: TabEnum.model
},
...(feConfigs?.show_promotion && userInfo?.team?.permission.isOwner
? [
{
@@ -89,11 +93,7 @@ const AccountContainer = ({
}
]
: []),
{
icon: 'support/user/individuation',
label: t('account:personalization'),
value: TabEnum.individuation
},
...(feConfigs.isPlus
? [
{
@@ -103,6 +103,11 @@ const AccountContainer = ({
}
]
: []),
{
icon: 'common/settingLight',
label: t('common:common.Setting'),
value: TabEnum.setting
},
{
icon: 'support/account/loginoutLight',
label: t('account:logout'),

View File

@@ -48,15 +48,16 @@ import { serviceSideProps } from '@fastgpt/web/common/system/nextjs';
import { useRouter } from 'next/router';
import TeamSelector from '../components/TeamSelector';
const StandDetailModal = dynamic(() => import('./components/standardDetailModal'));
const StandDetailModal = dynamic(() => import('./components/standardDetailModal'), { ssr: false });
const ConversionModal = dynamic(() => import('./components/ConversionModal'));
const UpdatePswModal = dynamic(() => import('./components/UpdatePswModal'));
const UpdateNotification = dynamic(() => import('./components/UpdateNotificationModal'));
const OpenAIAccountModal = dynamic(() => import('./components/OpenAIAccountModal'));
const LafAccountModal = dynamic(() => import('@/components/support/laf/LafAccountModal'));
const CommunityModal = dynamic(() => import('@/components/CommunityModal'));
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
const Info = () => {
@@ -583,7 +584,7 @@ const PlanUsage = () => {
</Box>
</Box>
{isOpenStandardModal && <StandDetailModal onClose={onCloseStandardModal} />}
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Box>
) : null;
};

View File

@@ -0,0 +1,25 @@
import { serviceSideProps } from '@fastgpt/web/common/system/nextjs';
import React from 'react';
import AccountContainer from '../components/AccountContainer';
import { Box } from '@chakra-ui/react';
import ModelTable from '@/components/core/ai/ModelTable';
const ModelProvider = () => {
return (
<AccountContainer>
<Box h={'100%'} py={4} px={6}>
<ModelTable />
</Box>
</AccountContainer>
);
};
export async function getServerSideProps(content: any) {
return {
props: {
...(await serviceSideProps(content, ['account']))
}
};
}
export default ModelProvider;

View File

@@ -28,7 +28,7 @@ const Individuation = () => {
});
reset(data);
toast({
title: t('account_individuation:update_data_success'),
title: t('account_setting:update_data_success'),
status: 'success'
});
},
@@ -39,19 +39,19 @@ const Individuation = () => {
<AccountContainer>
<Box py={[3, '28px']} px={['5vw', '64px']}>
<Flex alignItems={'center'} fontSize={'lg'} h={'30px'}>
<MyIcon mr={2} name={'support/user/individuation'} w={'20px'} />
{t('account_individuation:personalization')}
<MyIcon mr={2} name={'common/settingLight'} w={'20px'} />
{t('common:common.Setting')}
</Flex>
<Card mt={6} px={[3, 10]} py={[3, 7]} fontSize={'sm'}>
<Flex alignItems={'center'} w={['85%', '350px']}>
<Box flex={'0 0 80px'}>{t('account_individuation:language')}:&nbsp;</Box>
<Box flex={'0 0 80px'}>{t('account_setting:language')}:&nbsp;</Box>
<Box flex={'1 0 0'}>
<I18nLngSelector />
</Box>
</Flex>
<Flex mt={6} alignItems={'center'} w={['85%', '350px']}>
<Box flex={'0 0 80px'}>{t('account_individuation:timezone')}:&nbsp;</Box>
<Box flex={'0 0 80px'}>{t('account_setting:timezone')}:&nbsp;</Box>
<TimezoneSelect
value={userInfo?.timezone}
onChange={(e) => {
@@ -69,7 +69,7 @@ const Individuation = () => {
export async function getServerSideProps(content: any) {
return {
props: {
...(await serviceSideProps(content, ['account', 'account_individuation']))
...(await serviceSideProps(content, ['account', 'account_setting']))
}
};
}

View File

@@ -1,33 +1,38 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import type { InitDateResponse } from '@/global/common/api/systemRes';
import { connectToDatabase } from '@/service/mongo';
import { jsonRes } from '@fastgpt/service/common/response';
import type { NextApiResponse } from 'next';
import { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
async function handler(req: NextApiRequest, res: NextApiResponse) {
await connectToDatabase();
async function handler(req: ApiRequestProps<{}, { bufferId?: string }>, res: NextApiResponse) {
const { bufferId } = req.query;
jsonRes<InitDateResponse>(res, {
data: {
feConfigs: global.feConfigs,
subPlans: global.subPlans,
llmModels: global.llmModels.map((model) => ({
...model,
customCQPrompt: '',
customExtractPrompt: '',
defaultSystemChatPrompt: ''
})),
vectorModels: global.vectorModels,
reRankModels:
global.reRankModels?.map((item) => ({
...item,
requestUrl: '',
requestAuth: ''
})) || [],
whisperModel: global.whisperModel,
audioSpeechModels: global.audioSpeechModels,
systemVersion: global.systemVersion || '0.0.0'
}
});
// If bufferId is the same as the current bufferId, return directly
if (bufferId && global.systemInitBufferId && global.systemInitBufferId === bufferId) {
return {
bufferId: global.systemInitBufferId
};
}
return {
bufferId: global.systemInitBufferId,
feConfigs: global.feConfigs,
subPlans: global.subPlans,
llmModels: global.llmModels.map((model) => ({
...model,
customCQPrompt: '',
customExtractPrompt: '',
defaultSystemChatPrompt: ''
})),
vectorModels: global.vectorModels,
reRankModels:
global.reRankModels?.map((item) => ({
...item,
requestUrl: '',
requestAuth: ''
})) || [],
whisperModel: global.whisperModel,
audioSpeechModels: global.audioSpeechModels,
systemVersion: global.systemVersion || '0.0.0'
};
}
export default handler;
export default NextAPI(handler);

View File

@@ -109,7 +109,7 @@ const ExtraPlan = () => {
return (
<Flex
mt={['40px', '200px']}
mt={['40px', '100px']}
flexDirection={'column'}
alignItems={'center'}
position={'relative'}

View File

@@ -41,7 +41,7 @@ const FAQ = () => {
return (
<Flex
mt={['40px', '200px']}
mt={['40px', '100px']}
pb={'10vh'}
flexDirection={'column'}
alignItems={'center'}

View File

@@ -1,15 +1,15 @@
import React from 'react';
import { Box, Flex, Grid, Link, ModalBody } from '@chakra-ui/react';
import { Box, Flex, Grid, Link } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MyModal from '@fastgpt/web/components/common/MyModal';
import ModelTable from '@/components/core/ai/ModelTable';
const Points = () => {
const { t } = useTranslation();
return (
<Flex
mt={['40px', '200px']}
mt={['40px', '100px']}
flexDirection={'column'}
alignItems={'center'}
position={'relative'}
@@ -17,10 +17,12 @@ const Points = () => {
<Box id="point-card" fontWeight={'bold'} fontSize={['24px', '36px']} color={'myGray.900'}>
{t('common:support.wallet.subscription.Ai points')}
</Box>
<Link href="https://tiktokenizer.vercel.app/" target="_blank" mb={['30px', 14]}>
<Link href="https://tiktokenizer.vercel.app/" target="_blank" mb={['30px', 10]}>
{t('common:support.wallet.subscription.token_compute')}
</Link>
<AiPointsTable />
<Box p={5} w={'100%'} h={'666px'} bg={'white'} borderRadius={'lg'} boxShadow={'md'}>
<ModelTable />
</Box>
</Flex>
);
};
@@ -150,24 +152,3 @@ export const AiPointsTable = () => {
</Grid>
);
};
export const AiPointsModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation();
return (
<MyModal
isCentered
iconSrc="/imgs/modal/bill.svg"
title={t('common:support.wallet.subscription.Ai points')}
isOpen
onClose={onClose}
w={'100%'}
maxW={'90vw'}
maxH={'90vh'}
>
<ModalBody>
<AiPointsTable />
</ModalBody>
</MyModal>
);
};

View File

@@ -52,8 +52,7 @@ export async function getInitConfig() {
getSystemVersion(),
// abandon
getSystemPlugin(),
getSystemPluginV1()
getSystemPlugin()
]);
}
@@ -79,7 +78,7 @@ const defaultFeConfigs: FastGPTFeConfigsType = {
export async function initSystemConfig() {
// load config
const [dbConfig, fileConfig] = await Promise.all([
const [{ config: dbConfig, configId }, fileConfig] = await Promise.all([
getFastGPTConfigFromDB(),
readConfigData('config.json')
]);
@@ -106,7 +105,9 @@ export async function initSystemConfig() {
};
// set config
global.systemInitBufferId = configId;
initFastGPTConfig(config);
console.log({
feConfigs: global.feConfigs,
systemEnv: global.systemEnv,
@@ -162,32 +163,6 @@ function getSystemPlugin() {
global.communityPlugins = fileTemplates;
}
function getSystemPluginV1() {
if (global.communityPluginsV1 && global.communityPluginsV1.length > 0) return;
const basePath =
process.env.NODE_ENV === 'development'
? 'data/pluginTemplates/v1'
: '/app/data/pluginTemplates/v1';
// read data/pluginTemplates directory, get all json file
const files = readdirSync(basePath);
// filter json file
const filterFiles = files.filter((item) => item.endsWith('.json'));
// read json file
const fileTemplates: (PluginTemplateType & { weight: number })[] = filterFiles.map((filename) => {
const content = readFileSync(`${basePath}/${filename}`, 'utf-8');
return {
...JSON.parse(content),
id: `${PluginSourceEnum.community}-${filename.replace('.json', '')}`,
source: PluginSourceEnum.community
};
});
fileTemplates.sort((a, b) => b.weight - a.weight);
global.communityPluginsV1 = fileTemplates;
}
export async function initSystemPlugins() {
try {

View File

@@ -5,7 +5,7 @@ import {
LLMModelItemType,
ReRankModelItemType,
VectorModelItemType,
WhisperModelType
STTModelType
} from '@fastgpt/global/core/ai/model.d';
import { TrackEventName } from '@/web/common/system/constants';
import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type';

View File

@@ -1,4 +1,7 @@
import type { InitDateResponse } from '@/global/common/api/systemRes';
import { GET } from '@/web/common/api/request';
export const getSystemInitData = () => GET<InitDateResponse>('/common/system/getInitData');
export const getSystemInitData = (bufferId?: string) =>
GET<InitDateResponse>('/common/system/getInitData', {
bufferId
});

View File

@@ -10,7 +10,7 @@ export const clientInitData = async (
feConfigs: FastGPTFeConfigsType;
}> => {
try {
const res = await getSystemInitData();
const res = await getSystemInitData(useSystemStore.getState().initDataBufferId);
useSystemStore.getState().initStaticData(res);
return {

View File

@@ -8,11 +8,12 @@ import type {
LLMModelItemType,
ReRankModelItemType,
VectorModelItemType,
WhisperModelType
STTModelType
} from '@fastgpt/global/core/ai/model.d';
import { InitDateResponse } from '@/global/common/api/systemRes';
import { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types';
import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type';
import { defaultWhisperModel } from '@fastgpt/global/core/ai/model';
type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string };
@@ -35,6 +36,7 @@ type State = {
isNotSufficientModal: boolean;
setIsNotSufficientModal: (val: boolean) => void;
initDataBufferId?: string;
feConfigs: FastGPTFeConfigsType;
subPlans?: SubPlanType;
systemVersion: string;
@@ -43,7 +45,7 @@ type State = {
vectorModelList: VectorModelItemType[];
audioSpeechModelList: AudioSpeechModelType[];
reRankModelList: ReRankModelItemType[];
whisperModel?: WhisperModelType;
whisperModel: STTModelType;
initStaticData: (e: InitDateResponse) => void;
appType?: string;
setAppType: (e?: string) => void;
@@ -110,6 +112,7 @@ export const useSystemStore = create<State>()(
});
},
initDataBufferId: undefined,
feConfigs: {},
subPlans: undefined,
systemVersion: '0.0.0',
@@ -118,26 +121,38 @@ export const useSystemStore = create<State>()(
vectorModelList: [],
audioSpeechModelList: [],
reRankModelList: [],
whisperModel: undefined,
whisperModel: defaultWhisperModel,
initStaticData(res) {
set((state) => {
state.feConfigs = res.feConfigs || {};
state.subPlans = res.subPlans;
state.systemVersion = res.systemVersion;
state.initDataBufferId = res.bufferId;
state.feConfigs = res.feConfigs ?? state.feConfigs;
state.subPlans = res.subPlans ?? state.subPlans;
state.systemVersion = res.systemVersion ?? state.systemVersion;
state.llmModelList = res.llmModels ?? state.llmModelList;
state.datasetModelList = state.llmModelList.filter((item) => item.datasetProcess);
state.vectorModelList = res.vectorModels ?? state.vectorModelList;
state.audioSpeechModelList = res.audioSpeechModels ?? state.audioSpeechModelList;
state.reRankModelList = res.reRankModels ?? state.reRankModelList;
state.whisperModel = res.whisperModel;
state.whisperModel = res.whisperModel ?? state.whisperModel;
});
}
})),
{
name: 'globalStore',
partialize: (state) => ({
loginStore: state.loginStore
loginStore: state.loginStore,
initDataBufferId: state.initDataBufferId,
feConfigs: state.feConfigs,
subPlans: state.subPlans,
systemVersion: state.systemVersion,
llmModelList: state.llmModelList,
datasetModelList: state.datasetModelList,
vectorModelList: state.vectorModelList,
audioSpeechModelList: state.audioSpeechModelList,
reRankModelList: state.reRankModelList,
whisperModel: state.whisperModel
})
}
)

View File

@@ -5,6 +5,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d';
import { useMemoizedFn, useMount } from 'ahooks';
import { TrackEventName } from '../common/system/constants';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
export const useInitApp = () => {
const router = useRouter();
@@ -41,8 +42,6 @@ export const useInitApp = () => {
});
useMount(() => {
initFetch();
const errorTrack = (event: ErrorEvent) => {
window.umami?.track(TrackEventName.windowError, {
device: {
@@ -62,6 +61,11 @@ export const useInitApp = () => {
};
});
useRequest2(initFetch, {
manual: false,
pollingInterval: 300000
});
useEffect(() => {
hiId && localStorage.setItem('inviterId', hiId);
bd_vid && sessionStorage.setItem('bd_vid', bd_vid);