V4.8.20 feature (#3686)
* Aiproxy (#3649) * model config * feat: model config ui * perf: rename variable * feat: custom request url * perf: model buffer * perf: init model * feat: json model config * auto login * fix: ts * update packages * package * fix: dockerfile * feat: usage filter & export & dashbord (#3538) * feat: usage filter & export & dashbord * adjust ui * fix tmb scroll * fix code & selecte all * merge * perf: usages list;perf: move components (#3654) * perf: usages list * team sub plan load * perf: usage dashboard code * perf: dashboard ui * perf: move components * add default model config (#3653) * 4.8.20 test (#3656) * provider * perf: model config * model perf (#3657) * fix: model * dataset quote * perf: model config * model tag * doubao model config * perf: config model * feat: model test * fix: POST 500 error on dingtalk bot (#3655) * feat: default model (#3662) * move model config * feat: default model * fix: false triggerd org selection (#3661) * export usage csv i18n (#3660) * export usage csv i18n * fix build * feat: markdown extension (#3663) * feat: markdown extension * media cros * rerank test * default price * perf: default model * fix: cannot custom provider * fix: default model select * update bg * perf: default model selector * fix: usage export * i18n * fix: rerank * update init extension * perf: ip limit check * doubao model order * web default modle * perf: tts selector * perf: tts error * qrcode package * reload buffer (#3665) * reload buffer * reload buffer * tts selector * fix: err tip (#3666) * fix: err tip * perf: training queue * doc * fix interactive edge (#3659) * fix interactive edge * fix * comment * add gemini model * fix: chat model select * perf: supplement assistant empty response (#3669) * perf: supplement assistant empty response * check array * perf: max_token count;feat: support resoner output;fix: member scroll (#3681) * perf: supplement assistant empty response * check array * perf: max_token count * feat: support resoner output * member scroll * update provider order * i18n * fix: stream response (#3682) * perf: supplement assistant empty response * check array * fix: stream response * fix: model config cannot set to null * fix: reasoning response (#3684) * perf: supplement assistant empty response * check array * fix: reasoning response * fix: reasoning response * doc (#3685) * perf: supplement assistant empty response * check array * doc * lock * animation * update doc * update compose * doc * doc --------- Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: a.e. <49438478+I-Info@users.noreply.github.com>
This commit is contained in:
@@ -186,6 +186,12 @@ export const streamFetch = ({
|
||||
text: item
|
||||
});
|
||||
}
|
||||
|
||||
const reasoningText = parseJson.choices?.[0]?.delta?.reasoning_content || '';
|
||||
onMessage({
|
||||
event,
|
||||
reasoningText
|
||||
});
|
||||
} else if (event === SseResponseEventEnum.fastAnswer) {
|
||||
const text = parseJson.choices?.[0]?.delta?.content || '';
|
||||
pushDataToQueue({
|
||||
|
||||
@@ -101,6 +101,7 @@ function checkRes(data: ResponseDataType) {
|
||||
*/
|
||||
function responseError(err: any) {
|
||||
console.log('error->', '请求错误', err);
|
||||
const data = err?.response?.data || err;
|
||||
|
||||
if (!err) {
|
||||
return Promise.reject({ message: '未知错误' });
|
||||
@@ -108,8 +109,12 @@ function responseError(err: any) {
|
||||
if (typeof err === 'string') {
|
||||
return Promise.reject({ message: err });
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
return Promise.reject(data);
|
||||
}
|
||||
|
||||
// 有报错响应
|
||||
if (err?.code in TOKEN_ERROR_CODE || err?.response?.data?.code in TOKEN_ERROR_CODE) {
|
||||
if (data?.code in TOKEN_ERROR_CODE) {
|
||||
if (!['/chat/share', '/chat/team', '/login'].includes(window.location.pathname)) {
|
||||
clearToken();
|
||||
window.location.replace(
|
||||
@@ -120,18 +125,18 @@ function responseError(err: any) {
|
||||
return Promise.reject({ message: i18nT('common:unauth_token') });
|
||||
}
|
||||
if (
|
||||
err?.statusText === TeamErrEnum.aiPointsNotEnough ||
|
||||
err?.statusText === TeamErrEnum.datasetSizeNotEnough ||
|
||||
err?.statusText === TeamErrEnum.datasetAmountNotEnough ||
|
||||
err?.statusText === TeamErrEnum.appAmountNotEnough
|
||||
data?.statusText === TeamErrEnum.aiPointsNotEnough ||
|
||||
data?.statusText === TeamErrEnum.datasetSizeNotEnough ||
|
||||
data?.statusText === TeamErrEnum.datasetAmountNotEnough ||
|
||||
data?.statusText === TeamErrEnum.appAmountNotEnough ||
|
||||
data?.statusText === TeamErrEnum.pluginAmountNotEnough ||
|
||||
data?.statusText === TeamErrEnum.websiteSyncNotEnough ||
|
||||
data?.statusText === TeamErrEnum.reRankNotEnough
|
||||
) {
|
||||
useSystemStore.getState().setNotSufficientModalType(err.statusText);
|
||||
return Promise.reject(err);
|
||||
useSystemStore.getState().setNotSufficientModalType(data.statusText);
|
||||
return Promise.reject(data);
|
||||
}
|
||||
if (err?.response?.data) {
|
||||
return Promise.reject(err?.response?.data);
|
||||
}
|
||||
return Promise.reject(err);
|
||||
return Promise.reject(data);
|
||||
}
|
||||
|
||||
/* 创建请求实例 */
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useCallback } from 'react';
|
||||
import { hasHttps } from '@fastgpt/web/common/system/utils';
|
||||
import { isProduction } from '@fastgpt/global/common/system/constants';
|
||||
|
||||
/**
|
||||
* copy text data
|
||||
*/
|
||||
export const useCopyData = () => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
|
||||
const copyData = useCallback(
|
||||
async (
|
||||
data: string,
|
||||
title: string | null = t('common:common.Copy Successful'),
|
||||
duration = 1000
|
||||
) => {
|
||||
data = data.trim();
|
||||
|
||||
try {
|
||||
if ((hasHttps() || !isProduction) && navigator.clipboard) {
|
||||
await navigator.clipboard.writeText(data);
|
||||
} else {
|
||||
throw new Error('');
|
||||
}
|
||||
} catch (error) {
|
||||
// console.log(error);
|
||||
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = data;
|
||||
textarea.style.position = 'absolute';
|
||||
textarea.style.opacity = '0';
|
||||
document.body.appendChild(textarea);
|
||||
|
||||
textarea.select();
|
||||
const res = document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
|
||||
if (!res) {
|
||||
return toast({
|
||||
title: t('common:common.Copy_failed'),
|
||||
status: 'error',
|
||||
duration
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (title) {
|
||||
toast({
|
||||
title,
|
||||
status: 'success',
|
||||
duration
|
||||
});
|
||||
}
|
||||
},
|
||||
[t, toast]
|
||||
);
|
||||
|
||||
return {
|
||||
copyData
|
||||
};
|
||||
};
|
||||
@@ -4,17 +4,18 @@ import { immer } from 'zustand/middleware/immer';
|
||||
import axios from 'axios';
|
||||
import { OAuthEnum } from '@fastgpt/global/support/user/constant';
|
||||
import type {
|
||||
AudioSpeechModelType,
|
||||
TTSModelType,
|
||||
LLMModelItemType,
|
||||
ReRankModelItemType,
|
||||
VectorModelItemType,
|
||||
EmbeddingModelItemType,
|
||||
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';
|
||||
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { SystemDefaultModelType } from '@fastgpt/service/core/ai/type';
|
||||
|
||||
type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string };
|
||||
|
||||
@@ -49,12 +50,13 @@ type State = {
|
||||
feConfigs: FastGPTFeConfigsType;
|
||||
subPlans?: SubPlanType;
|
||||
systemVersion: string;
|
||||
defaultModels: SystemDefaultModelType;
|
||||
llmModelList: LLMModelItemType[];
|
||||
datasetModelList: LLMModelItemType[];
|
||||
vectorModelList: VectorModelItemType[];
|
||||
audioSpeechModelList: AudioSpeechModelType[];
|
||||
embeddingModelList: EmbeddingModelItemType[];
|
||||
ttsModelList: TTSModelType[];
|
||||
reRankModelList: ReRankModelItemType[];
|
||||
whisperModel: STTModelType;
|
||||
sttModelList: STTModelType[];
|
||||
initStaticData: (e: InitDateResponse) => void;
|
||||
appType?: string;
|
||||
setAppType: (e?: string) => void;
|
||||
@@ -125,12 +127,13 @@ export const useSystemStore = create<State>()(
|
||||
feConfigs: {},
|
||||
subPlans: undefined,
|
||||
systemVersion: '0.0.0',
|
||||
defaultModels: {},
|
||||
llmModelList: [],
|
||||
datasetModelList: [],
|
||||
vectorModelList: [],
|
||||
audioSpeechModelList: [],
|
||||
embeddingModelList: [],
|
||||
ttsModelList: [],
|
||||
reRankModelList: [],
|
||||
whisperModel: defaultWhisperModel,
|
||||
sttModelList: [],
|
||||
initStaticData(res) {
|
||||
set((state) => {
|
||||
state.initDataBufferId = res.bufferId;
|
||||
@@ -139,12 +142,24 @@ export const useSystemStore = create<State>()(
|
||||
state.subPlans = res.subPlans ?? state.subPlans;
|
||||
state.systemVersion = res.systemVersion ?? state.systemVersion;
|
||||
|
||||
state.llmModelList = res.llmModels ?? state.llmModelList;
|
||||
state.llmModelList =
|
||||
res.activeModelList?.filter((item) => item.type === ModelTypeEnum.llm) ??
|
||||
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;
|
||||
state.embeddingModelList =
|
||||
res.activeModelList?.filter((item) => item.type === ModelTypeEnum.embedding) ??
|
||||
state.embeddingModelList;
|
||||
state.ttsModelList =
|
||||
res.activeModelList?.filter((item) => item.type === ModelTypeEnum.tts) ??
|
||||
state.ttsModelList;
|
||||
state.reRankModelList =
|
||||
res.activeModelList?.filter((item) => item.type === ModelTypeEnum.rerank) ??
|
||||
state.reRankModelList;
|
||||
state.sttModelList =
|
||||
res.activeModelList?.filter((item) => item.type === ModelTypeEnum.stt) ??
|
||||
state.sttModelList;
|
||||
|
||||
state.defaultModels = res.defaultModels ?? state.defaultModels;
|
||||
});
|
||||
}
|
||||
})),
|
||||
@@ -156,12 +171,13 @@ export const useSystemStore = create<State>()(
|
||||
feConfigs: state.feConfigs,
|
||||
subPlans: state.subPlans,
|
||||
systemVersion: state.systemVersion,
|
||||
defaultModels: state.defaultModels,
|
||||
llmModelList: state.llmModelList,
|
||||
datasetModelList: state.datasetModelList,
|
||||
vectorModelList: state.vectorModelList,
|
||||
audioSpeechModelList: state.audioSpeechModelList,
|
||||
embeddingModelList: state.embeddingModelList,
|
||||
ttsModelList: state.ttsModelList,
|
||||
reRankModelList: state.reRankModelList,
|
||||
whisperModel: state.whisperModel
|
||||
sttModelList: state.sttModelList
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,15 +1,58 @@
|
||||
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||
import { useSystemStore } from './useSystemStore';
|
||||
|
||||
export const downloadFetch = async ({ url, filename }: { url: string; filename: string }) => {
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
export const downloadFetch = async ({
|
||||
url,
|
||||
filename,
|
||||
body
|
||||
}: {
|
||||
url: string;
|
||||
filename: string;
|
||||
body?: Record<string, any>;
|
||||
}) => {
|
||||
if (body) {
|
||||
// fetch data with POST method if body exists
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
const blob = await response.blob();
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
// clean up the blob URL
|
||||
window.URL.revokeObjectURL(downloadUrl);
|
||||
} else {
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
};
|
||||
|
||||
export const getWebLLMModel = (model?: string) => {
|
||||
const list = useSystemStore.getState().llmModelList;
|
||||
return list.find((item) => item.model === model || item.name === model) ?? list[0];
|
||||
const defaultModels = useSystemStore.getState().defaultModels;
|
||||
|
||||
return list.find((item) => item.model === model || item.name === model) ?? defaultModels.llm!;
|
||||
};
|
||||
export const getWebDefaultModel = (llmList: LLMModelItemType[] = []) => {
|
||||
const list = llmList.length > 0 ? llmList : useSystemStore.getState().llmModelList;
|
||||
const defaultModels = useSystemStore.getState().defaultModels;
|
||||
|
||||
return defaultModels.llm && list.find((item) => item.model === defaultModels.llm?.model)
|
||||
? defaultModels.llm
|
||||
: list[0];
|
||||
};
|
||||
|
||||
@@ -69,10 +69,6 @@ export const useAudioPlay = (
|
||||
|
||||
if (!response.body || !response.ok) {
|
||||
const data = await response.json();
|
||||
toast({
|
||||
status: 'error',
|
||||
title: getErrText(data, t('common:core.chat.Audio Speech Error'))
|
||||
});
|
||||
return Promise.reject(data);
|
||||
}
|
||||
return response.body;
|
||||
|
||||
@@ -63,7 +63,7 @@ export const useInitApp = () => {
|
||||
|
||||
useRequest2(initFetch, {
|
||||
manual: false,
|
||||
pollingInterval: 300000
|
||||
pollingInterval: 300000 // 5 minutes refresh
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
27
projects/app/src/web/core/ai/config.ts
Normal file
27
projects/app/src/web/core/ai/config.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { GET, PUT, DELETE, POST } from '@/web/common/api/request';
|
||||
import type { listResponse } from '@/pages/api/core/ai/model/list';
|
||||
import type { updateBody } from '@/pages/api/core/ai/model/update';
|
||||
import type { deleteQuery } from '@/pages/api/core/ai/model/delete';
|
||||
import type { SystemModelItemType } from '@fastgpt/service/core/ai/type';
|
||||
import type { updateWithJsonBody } from '@/pages/api/core/ai/model/updateWithJson';
|
||||
import type { updateDefaultBody } from '@/pages/api/core/ai/model/updateDefault';
|
||||
|
||||
export const getSystemModelList = () => GET<listResponse>('/core/ai/model/list');
|
||||
export const getSystemModelDetail = (model: string) =>
|
||||
GET<SystemModelItemType>('/core/ai/model/detail', { model });
|
||||
|
||||
export const getSystemModelDefaultConfig = (model: string) =>
|
||||
GET<SystemModelItemType>('/core/ai/model/getDefaultConfig', { model });
|
||||
|
||||
export const putSystemModel = (data: updateBody) => PUT('/core/ai/model/update', data);
|
||||
|
||||
export const deleteSystemModel = (data: deleteQuery) => DELETE('/core/ai/model/delete', data);
|
||||
|
||||
export const getModelConfigJson = () => GET<string>('/core/ai/model/getConfigJson');
|
||||
export const putUpdateWithJson = (data: updateWithJsonBody) =>
|
||||
PUT('/core/ai/model/updateWithJson', data);
|
||||
|
||||
export const getTestModel = (model: String) => GET('/core/ai/model/test', { model });
|
||||
|
||||
export const putUpdateDefaultModels = (data: updateDefaultBody) =>
|
||||
PUT('/core/ai/model/updateDefault', data);
|
||||
@@ -1,7 +1,7 @@
|
||||
import { parseCurl } from '@fastgpt/global/common/string/http';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { AppSchema } from '@fastgpt/global/core/app/type';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import {
|
||||
FlowNodeInputTypeEnum,
|
||||
FlowNodeOutputTypeEnum,
|
||||
@@ -150,7 +150,7 @@ export const emptyTemplates: Record<
|
||||
key: 'temperature',
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
label: '',
|
||||
value: 0,
|
||||
value: undefined,
|
||||
valueType: WorkflowIOValueTypeEnum.number,
|
||||
min: 0,
|
||||
max: 10,
|
||||
@@ -160,7 +160,7 @@ export const emptyTemplates: Record<
|
||||
key: 'maxToken',
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
label: '',
|
||||
value: 2000,
|
||||
value: undefined,
|
||||
valueType: WorkflowIOValueTypeEnum.number,
|
||||
min: 100,
|
||||
max: 4000,
|
||||
@@ -221,6 +221,13 @@ export const emptyTemplates: Record<
|
||||
debugLabel: i18nT('common:core.module.Dataset quote.label'),
|
||||
description: '',
|
||||
valueType: WorkflowIOValueTypeEnum.datasetQuote
|
||||
},
|
||||
{
|
||||
key: NodeInputKeyEnum.aiChatReasoning,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
label: '',
|
||||
valueType: WorkflowIOValueTypeEnum.boolean,
|
||||
value: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
|
||||
@@ -190,6 +190,13 @@ export function form2AppWorkflow(
|
||||
label: '',
|
||||
valueType: WorkflowIOValueTypeEnum.boolean,
|
||||
value: true
|
||||
},
|
||||
{
|
||||
key: NodeInputKeyEnum.aiChatReasoning,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
label: '',
|
||||
valueType: WorkflowIOValueTypeEnum.boolean,
|
||||
value: formData.aiSettings.aiChatReasoning
|
||||
}
|
||||
],
|
||||
outputs: AiChatModule.outputs
|
||||
|
||||
@@ -65,6 +65,7 @@ import type {
|
||||
listExistIdQuery,
|
||||
listExistIdResponse
|
||||
} from '@/pages/api/core/dataset/apiDataset/listExistId';
|
||||
import { GetQuoteDataResponse } from '@/pages/api/core/dataset/data/getQuoteData';
|
||||
|
||||
/* ======================== dataset ======================= */
|
||||
export const getDatasets = (data: GetDatasetListBody) =>
|
||||
@@ -203,6 +204,10 @@ export const putDatasetDataById = (data: UpdateDatasetDataProps) =>
|
||||
export const delOneDatasetDataById = (id: string) =>
|
||||
DELETE<string>(`/core/dataset/data/delete`, { id });
|
||||
|
||||
// Get quote data
|
||||
export const getQuoteData = (id: string) =>
|
||||
GET<GetQuoteDataResponse>(`/core/dataset/data/getQuoteData`, { id });
|
||||
|
||||
/* ================ training ==================== */
|
||||
export const postRebuildEmbedding = (data: rebuildEmbeddingBody) =>
|
||||
POST(`/core/dataset/training/rebuildEmbedding`, data);
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { POST } from '@/web/common/api/request';
|
||||
import { CreateTrainingUsageProps } from '@fastgpt/global/support/wallet/usage/api.d';
|
||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||
import {
|
||||
CreateTrainingUsageProps,
|
||||
GetUsageDashboardProps,
|
||||
GetUsageDashboardResponseItem,
|
||||
GetUsageProps
|
||||
} from '@fastgpt/global/support/wallet/usage/api.d';
|
||||
import type { UsageItemType } from '@fastgpt/global/support/wallet/usage/type';
|
||||
import { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
|
||||
export const getUserUsages = (
|
||||
data: PaginationProps<{
|
||||
dateStart: Date;
|
||||
dateEnd: Date;
|
||||
source?: UsageSourceEnum;
|
||||
teamMemberId: string;
|
||||
}>
|
||||
) => POST<PaginationResponse<UsageItemType>>(`/proApi/support/wallet/usage/getUsage`, data);
|
||||
export const getUserUsages = (data: PaginationProps<GetUsageProps>) =>
|
||||
POST<PaginationResponse<UsageItemType>>(`/proApi/support/wallet/usage/getUsage`, data);
|
||||
|
||||
export const getDashboardData = (data: GetUsageDashboardProps) =>
|
||||
POST<GetUsageDashboardResponseItem[]>(`/proApi/support/wallet/usage/getDashboardData`, data);
|
||||
|
||||
export const postCreateTrainingUsage = (data: CreateTrainingUsageProps) =>
|
||||
POST<string>(`/support/wallet/usage/createTrainingUsage`, data);
|
||||
|
||||
Reference in New Issue
Block a user