mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
fix: price page init data;perf: usage code;fix: reasoning tokens;fix: workflow basic node cannot upgrade (#3816)
* fix: img read * fix: price page init data * perf: ai model avatar * perf: refresh in change team * perf: null checker * perf: usage code * fix: reasoning tokens * fix: workflow basic node cannot upgrade * perf: model refresh * perf: icon refresh
This commit is contained in:
@@ -11,7 +11,13 @@ weight: 802
|
|||||||
## 完整更新内容
|
## 完整更新内容
|
||||||
|
|
||||||
1. 新增 - AI 对话节点解析 <think></think> 标签内容,便于各类模型进行思考链输出。
|
1. 新增 - AI 对话节点解析 <think></think> 标签内容,便于各类模型进行思考链输出。
|
||||||
2. 修复 - 思考链流输出时,有时与正文顺序偏差。
|
2. 优化 - 模型未配置时提示,减少冲突提示。
|
||||||
3. 修复 - API 调用工作流,如果传递的图片不支持 Head 检测时,图片会被过滤。已增加该类错误检测,避免被错误过滤。
|
3. 优化 - 使用记录代码。
|
||||||
4. 修复 - 模板市场部分模板错误。
|
4. 修复 - 思考内容未进入到输出 Tokens.
|
||||||
5. 修复 - 免登录窗口无法正常判断语言识别是否开启。
|
5. 修复 - 思考链流输出时,有时与正文顺序偏差。
|
||||||
|
6. 修复 - API 调用工作流,如果传递的图片不支持 Head 检测时,图片会被过滤。已增加该类错误检测,避免被错误过滤。
|
||||||
|
7. 修复 - 模板市场部分模板错误。
|
||||||
|
8. 修复 - 免登录窗口无法正常判断语言识别是否开启。
|
||||||
|
9. 修复 - 对话日志导出,未兼容 sub path。
|
||||||
|
10. 修复 - list 接口在联查 member 时,存在空指针可能性。
|
||||||
|
11. 修复 - 工作流基础节点无法升级。
|
||||||
|
@@ -20,4 +20,4 @@ export const ReadFileBaseUrl = `${process.env.FILE_DOMAIN || process.env.FE_DOMA
|
|||||||
|
|
||||||
export const documentFileType = '.txt, .docx, .csv, .xlsx, .pdf, .md, .html, .pptx';
|
export const documentFileType = '.txt, .docx, .csv, .xlsx, .pdf, .md, .html, .pptx';
|
||||||
export const imageFileType =
|
export const imageFileType =
|
||||||
'.jpg, .jpeg, .png, .gif, .bmp, .webp, .svg, .tiff, .tif, .ico, .heic, .heif, .avif';
|
'.jpg, .jpeg, .png, .gif, .bmp, .webp, .svg, .tiff, .tif, .ico, .heic, .heif, .avif, .raw, .cr2, .nef, .arw, .dng, .psd, .ai, .eps, .emf, .wmf, .jfif, .exif, .pgm, .ppm, .pbm, .jp2, .j2k, .jpf, .jpx, .jpm, .mj2, .xbm, .pcx';
|
||||||
|
1
packages/global/core/ai/type.d.ts
vendored
1
packages/global/core/ai/type.d.ts
vendored
@@ -46,6 +46,7 @@ export type ChatCompletionMessageParam = (
|
|||||||
| CustomChatCompletionToolMessageParam
|
| CustomChatCompletionToolMessageParam
|
||||||
| CustomChatCompletionAssistantMessageParam
|
| CustomChatCompletionAssistantMessageParam
|
||||||
) & {
|
) & {
|
||||||
|
reasoning_text?: string;
|
||||||
dataId?: string;
|
dataId?: string;
|
||||||
hideInUI?: boolean;
|
hideInUI?: boolean;
|
||||||
};
|
};
|
||||||
|
@@ -46,7 +46,16 @@ export const chats2GPTMessages = ({
|
|||||||
|
|
||||||
messages.forEach((item) => {
|
messages.forEach((item) => {
|
||||||
const dataId = reserveId ? item.dataId : undefined;
|
const dataId = reserveId ? item.dataId : undefined;
|
||||||
if (item.obj === ChatRoleEnum.Human) {
|
if (item.obj === ChatRoleEnum.System) {
|
||||||
|
const content = item.value?.[0]?.text?.content;
|
||||||
|
if (content) {
|
||||||
|
results.push({
|
||||||
|
dataId,
|
||||||
|
role: ChatCompletionRequestMessageRoleEnum.System,
|
||||||
|
content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (item.obj === ChatRoleEnum.Human) {
|
||||||
const value = item.value
|
const value = item.value
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (item.type === ChatItemValueTypeEnum.text) {
|
if (item.type === ChatItemValueTypeEnum.text) {
|
||||||
@@ -80,15 +89,6 @@ export const chats2GPTMessages = ({
|
|||||||
role: ChatCompletionRequestMessageRoleEnum.User,
|
role: ChatCompletionRequestMessageRoleEnum.User,
|
||||||
content: simpleUserContentPart(value)
|
content: simpleUserContentPart(value)
|
||||||
});
|
});
|
||||||
} else if (item.obj === ChatRoleEnum.System) {
|
|
||||||
const content = item.value?.[0]?.text?.content;
|
|
||||||
if (content) {
|
|
||||||
results.push({
|
|
||||||
dataId,
|
|
||||||
role: ChatCompletionRequestMessageRoleEnum.System,
|
|
||||||
content
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const aiResults: ChatCompletionMessageParam[] = [];
|
const aiResults: ChatCompletionMessageParam[] = [];
|
||||||
|
|
||||||
|
@@ -26,15 +26,18 @@ export async function uploadMongoImg({
|
|||||||
const [base64Mime, base64Data] = base64Img.split(',');
|
const [base64Mime, base64Data] = base64Img.split(',');
|
||||||
// Check if mime type is valid
|
// Check if mime type is valid
|
||||||
if (!base64MimeRegex.test(base64Mime)) {
|
if (!base64MimeRegex.test(base64Mime)) {
|
||||||
return Promise.reject('Invalid image mime type');
|
return Promise.reject('Invalid image base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
const mime = `image/${base64Mime.match(base64MimeRegex)?.[1] ?? 'image/jpeg'}`;
|
const mime = `image/${base64Mime.match(base64MimeRegex)?.[1] ?? 'image/jpeg'}`;
|
||||||
const binary = Buffer.from(base64Data, 'base64');
|
const binary = Buffer.from(base64Data, 'base64');
|
||||||
const extension = mime.split('/')[1];
|
let extension = mime.split('/')[1];
|
||||||
|
if (extension.startsWith('x-')) {
|
||||||
|
extension = extension.substring(2); // Remove 'x-' prefix
|
||||||
|
}
|
||||||
|
|
||||||
if (!imageFileType.includes(`.${extension}`)) {
|
if (!extension || !imageFileType.includes(`.${extension}`)) {
|
||||||
return Promise.reject('Invalid image file type');
|
return Promise.reject(`Invalid image file type: ${mime}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { _id } = await MongoImage.create({
|
const { _id } = await MongoImage.create({
|
||||||
|
@@ -25,7 +25,7 @@ export const countGptMessagesTokens = async (
|
|||||||
number
|
number
|
||||||
>({
|
>({
|
||||||
name: WorkerNameEnum.countGptMessagesTokens,
|
name: WorkerNameEnum.countGptMessagesTokens,
|
||||||
maxReservedThreads: global.systemEnv?.tokenWorkers || 50
|
maxReservedThreads: global.systemEnv?.tokenWorkers || 30
|
||||||
});
|
});
|
||||||
|
|
||||||
const total = await workerController.run({ messages, tools, functionCall });
|
const total = await workerController.run({ messages, tools, functionCall });
|
||||||
|
@@ -270,7 +270,8 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
|||||||
const AIMessages: ChatCompletionMessageParam[] = [
|
const AIMessages: ChatCompletionMessageParam[] = [
|
||||||
{
|
{
|
||||||
role: ChatCompletionRequestMessageRoleEnum.Assistant,
|
role: ChatCompletionRequestMessageRoleEnum.Assistant,
|
||||||
content: answerText
|
content: answerText,
|
||||||
|
reasoning_text: reasoningText // reasoning_text is only recorded for response, but not for request
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -232,9 +232,14 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
|||||||
chatNodeUsages = chatNodeUsages.concat(nodeDispatchUsages);
|
chatNodeUsages = chatNodeUsages.concat(nodeDispatchUsages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toolResponses !== undefined) {
|
if (toolResponses !== undefined && toolResponses !== null) {
|
||||||
if (Array.isArray(toolResponses) && toolResponses.length === 0) return;
|
if (Array.isArray(toolResponses) && toolResponses.length === 0) return;
|
||||||
if (typeof toolResponses === 'object' && Object.keys(toolResponses).length === 0) return;
|
if (
|
||||||
|
!Array.isArray(toolResponses) &&
|
||||||
|
typeof toolResponses === 'object' &&
|
||||||
|
Object.keys(toolResponses).length === 0
|
||||||
|
)
|
||||||
|
return;
|
||||||
toolRunResponse = toolResponses;
|
toolRunResponse = toolResponses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,114 @@
|
|||||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||||
import { MongoUsage } from './schema';
|
import { MongoUsage } from './schema';
|
||||||
import { ClientSession } from '../../../common/mongo';
|
import { ClientSession, Types } from '../../../common/mongo';
|
||||||
|
import { addLog } from '../../../common/system/log';
|
||||||
|
import { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type';
|
||||||
|
import { ConcatUsageProps, CreateUsageProps } from '@fastgpt/global/support/wallet/usage/api';
|
||||||
|
import { i18nT } from '../../../../web/i18n/utils';
|
||||||
|
import { pushConcatBillTask, pushReduceTeamAiPointsTask } from './utils';
|
||||||
|
|
||||||
|
import { POST } from '../../../common/api/plusRequest';
|
||||||
|
import { FastGPTProUrl } from '../../../common/system/constants';
|
||||||
|
|
||||||
|
export async function createUsage(data: CreateUsageProps) {
|
||||||
|
try {
|
||||||
|
// In FastGPT server
|
||||||
|
if (FastGPTProUrl) {
|
||||||
|
await POST('/support/wallet/usage/createUsage', data);
|
||||||
|
} else if (global.reduceAiPointsQueue) {
|
||||||
|
// In FastGPT pro server
|
||||||
|
await MongoUsage.create(data);
|
||||||
|
pushReduceTeamAiPointsTask({ teamId: data.teamId, totalPoints: data.totalPoints });
|
||||||
|
|
||||||
|
if (data.totalPoints === 0) {
|
||||||
|
addLog.info('0 totalPoints', data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
addLog.error('createUsage error', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export async function concatUsage(data: ConcatUsageProps) {
|
||||||
|
try {
|
||||||
|
// In FastGPT server
|
||||||
|
if (FastGPTProUrl) {
|
||||||
|
await POST('/support/wallet/usage/concatUsage', data);
|
||||||
|
} else if (global.reduceAiPointsQueue) {
|
||||||
|
const {
|
||||||
|
teamId,
|
||||||
|
billId,
|
||||||
|
totalPoints = 0,
|
||||||
|
listIndex,
|
||||||
|
inputTokens = 0,
|
||||||
|
outputTokens = 0
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
// billId is required and valid
|
||||||
|
if (!billId || !Types.ObjectId.isValid(billId)) return;
|
||||||
|
|
||||||
|
// In FastGPT pro server
|
||||||
|
pushConcatBillTask([
|
||||||
|
{
|
||||||
|
billId,
|
||||||
|
listIndex,
|
||||||
|
inputTokens,
|
||||||
|
outputTokens,
|
||||||
|
totalPoints
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
pushReduceTeamAiPointsTask({ teamId, totalPoints });
|
||||||
|
|
||||||
|
if (data.totalPoints === 0) {
|
||||||
|
addLog.info('0 totalPoints', data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
addLog.error('concatUsage error', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createChatUsage = ({
|
||||||
|
appName,
|
||||||
|
appId,
|
||||||
|
pluginId,
|
||||||
|
teamId,
|
||||||
|
tmbId,
|
||||||
|
source,
|
||||||
|
flowUsages
|
||||||
|
}: {
|
||||||
|
appName: string;
|
||||||
|
appId?: string;
|
||||||
|
pluginId?: string;
|
||||||
|
teamId: string;
|
||||||
|
tmbId: string;
|
||||||
|
source: UsageSourceEnum;
|
||||||
|
flowUsages: ChatNodeUsageType[];
|
||||||
|
}) => {
|
||||||
|
const totalPoints = flowUsages.reduce((sum, item) => sum + (item.totalPoints || 0), 0);
|
||||||
|
|
||||||
|
createUsage({
|
||||||
|
teamId,
|
||||||
|
tmbId,
|
||||||
|
appName,
|
||||||
|
appId,
|
||||||
|
pluginId,
|
||||||
|
totalPoints,
|
||||||
|
source,
|
||||||
|
list: flowUsages.map((item) => ({
|
||||||
|
moduleName: item.moduleName,
|
||||||
|
amount: item.totalPoints || 0,
|
||||||
|
model: item.model,
|
||||||
|
inputTokens: item.inputTokens,
|
||||||
|
outputTokens: item.outputTokens
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
addLog.debug(`Create chat usage`, {
|
||||||
|
source,
|
||||||
|
teamId,
|
||||||
|
totalPoints
|
||||||
|
});
|
||||||
|
return { totalPoints };
|
||||||
|
};
|
||||||
|
|
||||||
export const createTrainingUsage = async ({
|
export const createTrainingUsage = async ({
|
||||||
teamId,
|
teamId,
|
||||||
@@ -29,21 +137,21 @@ export const createTrainingUsage = async ({
|
|||||||
totalPoints: 0,
|
totalPoints: 0,
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
moduleName: 'support.wallet.moduleName.index',
|
moduleName: i18nT('common:support.wallet.moduleName.index'),
|
||||||
model: vectorModel,
|
model: vectorModel,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
inputTokens: 0,
|
inputTokens: 0,
|
||||||
outputTokens: 0
|
outputTokens: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleName: 'support.wallet.moduleName.qa',
|
moduleName: i18nT('common:support.wallet.moduleName.qa'),
|
||||||
model: agentModel,
|
model: agentModel,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
inputTokens: 0,
|
inputTokens: 0,
|
||||||
outputTokens: 0
|
outputTokens: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleName: 'core.dataset.training.Auto mode',
|
moduleName: i18nT('common:core.dataset.training.Auto mode'),
|
||||||
model: agentModel,
|
model: agentModel,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
inputTokens: 0,
|
inputTokens: 0,
|
||||||
|
12
packages/service/support/wallet/usage/type.d.ts
vendored
Normal file
12
packages/service/support/wallet/usage/type.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export type ConcatBillQueueItemType = {
|
||||||
|
billId: string;
|
||||||
|
listIndex?: number;
|
||||||
|
totalPoints: number;
|
||||||
|
inputTokens: number;
|
||||||
|
outputTokens: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var reduceAiPointsQueue: { teamId: string; totalPoints: number }[];
|
||||||
|
var concatBillQueue: ConcatBillQueueItemType[];
|
||||||
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
import { findAIModel } from '../../../core/ai/model';
|
import { findAIModel } from '../../../core/ai/model';
|
||||||
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
||||||
|
import { ConcatBillQueueItemType } from './type';
|
||||||
|
|
||||||
export const formatModelChars2Points = ({
|
export const formatModelChars2Points = ({
|
||||||
model,
|
model,
|
||||||
@@ -34,3 +35,20 @@ export const formatModelChars2Points = ({
|
|||||||
totalPoints
|
totalPoints
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const pushReduceTeamAiPointsTask = ({
|
||||||
|
teamId,
|
||||||
|
totalPoints
|
||||||
|
}: {
|
||||||
|
teamId: string;
|
||||||
|
totalPoints: number;
|
||||||
|
}) => {
|
||||||
|
global.reduceAiPointsQueue.push({
|
||||||
|
teamId: String(teamId),
|
||||||
|
totalPoints
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pushConcatBillTask = (data: ConcatBillQueueItemType[]) => {
|
||||||
|
global.concatBillQueue.push(...data);
|
||||||
|
};
|
||||||
|
@@ -72,7 +72,7 @@ parentPort?.on(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const total =
|
const total =
|
||||||
messages.reduce((sum, item) => {
|
messages.reduce((sum, item, index) => {
|
||||||
// Evaluates the text of toolcall and functioncall
|
// Evaluates the text of toolcall and functioncall
|
||||||
const functionCallPrompt = (() => {
|
const functionCallPrompt = (() => {
|
||||||
let prompt = '';
|
let prompt = '';
|
||||||
@@ -100,7 +100,13 @@ parentPort?.on(
|
|||||||
.join('');
|
.join('');
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return sum + countPromptTokens(`${contentPrompt}${functionCallPrompt}`, item.role);
|
// Only the last message computed reasoning_text
|
||||||
|
const reasoningText = index === messages.length - 1 ? item.reasoning_text || '' : '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
sum +
|
||||||
|
countPromptTokens(`${reasoningText}${contentPrompt}${functionCallPrompt}`, item.role)
|
||||||
|
);
|
||||||
}, 0) +
|
}, 0) +
|
||||||
countToolsTokens(tools) +
|
countToolsTokens(tools) +
|
||||||
countToolsTokens(functionCall);
|
countToolsTokens(functionCall);
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import type { IconProps } from '@chakra-ui/react';
|
import type { IconProps } from '@chakra-ui/react';
|
||||||
import { Box, Icon } from '@chakra-ui/react';
|
import { Box, Icon } from '@chakra-ui/react';
|
||||||
import { iconPaths } from './constants';
|
import { iconPaths } from './constants';
|
||||||
import type { IconNameType } from './type.d';
|
import type { IconNameType } from './type.d';
|
||||||
|
import { useRefresh } from '../../../hooks/useRefresh';
|
||||||
|
|
||||||
const iconCache: Record<string, any> = {};
|
const iconCache: Record<string, any> = {};
|
||||||
|
|
||||||
const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType } & IconProps) => {
|
const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType } & IconProps) => {
|
||||||
const [IconComponent, setIconComponent] = useState<any>(null);
|
const { refresh } = useRefresh();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (iconCache[name]) {
|
if (iconCache[name]) {
|
||||||
setIconComponent(iconCache[name]);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,11 +20,13 @@ const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType
|
|||||||
const component = { as: icon.default };
|
const component = { as: icon.default };
|
||||||
// Store in cache
|
// Store in cache
|
||||||
iconCache[name] = component;
|
iconCache[name] = component;
|
||||||
setIconComponent(component);
|
refresh();
|
||||||
})
|
})
|
||||||
.catch((error) => console.log(error));
|
.catch((error) => console.log(error));
|
||||||
}, [name]);
|
}, [name]);
|
||||||
|
|
||||||
|
const IconComponent = iconCache[name];
|
||||||
|
|
||||||
return !!IconComponent ? (
|
return !!IconComponent ? (
|
||||||
<Icon
|
<Icon
|
||||||
{...IconComponent}
|
{...IconComponent}
|
||||||
@@ -40,4 +42,4 @@ const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MyIcon;
|
export default React.memo(MyIcon);
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"systemEnv": {
|
"systemEnv": {
|
||||||
"vectorMaxProcess": 15, // 向量处理线程数量
|
"vectorMaxProcess": 15, // 向量处理线程数量
|
||||||
"qaMaxProcess": 15, // 问答拆分线程数量
|
"qaMaxProcess": 15, // 问答拆分线程数量
|
||||||
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
"tokenWorkers": 30, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||||
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"systemEnv": {
|
"systemEnv": {
|
||||||
"vectorMaxProcess": 15, // 向量处理线程数量
|
"vectorMaxProcess": 15, // 向量处理线程数量
|
||||||
"qaMaxProcess": 15, // 问答拆分线程数量
|
"qaMaxProcess": 15, // 问答拆分线程数量
|
||||||
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
"tokenWorkers": 30, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||||
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||||
},
|
},
|
||||||
"llmModels": [
|
"llmModels": [
|
||||||
|
@@ -9,7 +9,7 @@ module.exports = {
|
|||||||
locales: ['en', 'zh-CN', 'zh-Hant'],
|
locales: ['en', 'zh-CN', 'zh-Hant'],
|
||||||
localeDetection: false
|
localeDetection: false
|
||||||
},
|
},
|
||||||
localePath:
|
defaultNS: 'common',
|
||||||
typeof window === 'undefined' ? require('path').resolve('../../packages/web/i18n') : '/i18n',
|
localePath: require('path').resolve('../../packages/web/i18n'),
|
||||||
reloadOnPrerender: process.env.NODE_ENV === 'development'
|
reloadOnPrerender: process.env.NODE_ENV === 'development'
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useLoading } from '@fastgpt/web/hooks/useLoading';
|
import { useLoading } from '@fastgpt/web/hooks/useLoading';
|
||||||
@@ -11,7 +11,7 @@ import { useI18nLng } from '@fastgpt/web/hooks/useI18n';
|
|||||||
|
|
||||||
import Auth from './auth';
|
import Auth from './auth';
|
||||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||||
import { useMount } from 'ahooks';
|
import { useDebounceEffect, useMount } from 'ahooks';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
|
|
||||||
@@ -88,7 +88,8 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check model invalid
|
// Check model invalid
|
||||||
useEffect(() => {
|
useDebounceEffect(
|
||||||
|
() => {
|
||||||
if (userInfo?.username === 'root') {
|
if (userInfo?.username === 'root') {
|
||||||
if (llmModelList.length === 0) {
|
if (llmModelList.length === 0) {
|
||||||
toast({
|
toast({
|
||||||
@@ -104,7 +105,12 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
|||||||
router.push('/account/model');
|
router.push('/account/model');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [embeddingModelList.length, llmModelList.length, userInfo?.username]);
|
},
|
||||||
|
[embeddingModelList.length, llmModelList.length, userInfo?.username],
|
||||||
|
{
|
||||||
|
wait: 2000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@@ -35,7 +35,9 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => {
|
|||||||
return props.size ? size[props.size] : size['md'];
|
return props.size ? size[props.size] : size['md'];
|
||||||
}, [props.size]);
|
}, [props.size]);
|
||||||
|
|
||||||
const avatarList = list.map((item) => {
|
const avatarList = useMemo(
|
||||||
|
() =>
|
||||||
|
list.map((item) => {
|
||||||
const modelData = getModelFromList(
|
const modelData = getModelFromList(
|
||||||
[
|
[
|
||||||
...llmModelList,
|
...llmModelList,
|
||||||
@@ -62,7 +64,17 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
});
|
}),
|
||||||
|
[
|
||||||
|
list,
|
||||||
|
llmModelList,
|
||||||
|
embeddingModelList,
|
||||||
|
ttsModelList,
|
||||||
|
sttModelList,
|
||||||
|
reRankModelList,
|
||||||
|
avatarSize
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -99,6 +111,16 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } =
|
const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } =
|
||||||
useSystemStore();
|
useSystemStore();
|
||||||
|
const modelList = useMemo(() => {
|
||||||
|
return [
|
||||||
|
...llmModelList,
|
||||||
|
...embeddingModelList,
|
||||||
|
...ttsModelList,
|
||||||
|
...sttModelList,
|
||||||
|
...reRankModelList
|
||||||
|
];
|
||||||
|
}, [llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList]);
|
||||||
|
|
||||||
const [value, setValue] = useState<string[]>([]);
|
const [value, setValue] = useState<string[]>([]);
|
||||||
|
|
||||||
const avatarSize = useMemo(() => {
|
const avatarSize = useMemo(() => {
|
||||||
@@ -134,7 +156,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
for (const item of list) {
|
for (const item of list) {
|
||||||
const modelData = getModelFromList([...llmModelList, ...embeddingModelList], item.value);
|
const modelData = getModelFromList(modelList, item.value);
|
||||||
const provider =
|
const provider =
|
||||||
renderList.find((item) => item.value === (modelData?.provider || 'Other')) ??
|
renderList.find((item) => item.value === (modelData?.provider || 'Other')) ??
|
||||||
renderList[renderList.length - 1];
|
renderList[renderList.length - 1];
|
||||||
@@ -146,7 +168,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
return renderList.filter((item) => item.children.length > 0);
|
return renderList.filter((item) => item.children.length > 0);
|
||||||
}, [avatarSize, list, llmModelList, t, embeddingModelList]);
|
}, [avatarSize, list, modelList]);
|
||||||
|
|
||||||
const onSelect = useCallback(
|
const onSelect = useCallback(
|
||||||
(e: string[]) => {
|
(e: string[]) => {
|
||||||
@@ -156,16 +178,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const SelectedModel = useMemo(() => {
|
const SelectedModel = useMemo(() => {
|
||||||
const modelData = getModelFromList(
|
const modelData = getModelFromList(modelList, props.value);
|
||||||
[
|
|
||||||
...llmModelList,
|
|
||||||
...embeddingModelList,
|
|
||||||
...ttsModelList,
|
|
||||||
...sttModelList,
|
|
||||||
...reRankModelList
|
|
||||||
],
|
|
||||||
props.value
|
|
||||||
);
|
|
||||||
|
|
||||||
setValue([modelData.provider, props.value]);
|
setValue([modelData.provider, props.value]);
|
||||||
|
|
||||||
@@ -181,15 +194,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
|
|||||||
<Box>{modelData?.name}</Box>
|
<Box>{modelData?.name}</Box>
|
||||||
</HStack>
|
</HStack>
|
||||||
);
|
);
|
||||||
}, [
|
}, [modelList, props.value, avatarSize]);
|
||||||
llmModelList,
|
|
||||||
embeddingModelList,
|
|
||||||
ttsModelList,
|
|
||||||
sttModelList,
|
|
||||||
reRankModelList,
|
|
||||||
props.value,
|
|
||||||
avatarSize
|
|
||||||
]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
@@ -13,11 +13,11 @@ import { useRouter } from 'next/router';
|
|||||||
|
|
||||||
const TeamSelector = ({
|
const TeamSelector = ({
|
||||||
showManage,
|
showManage,
|
||||||
afterSwitchTeam,
|
onChange,
|
||||||
...props
|
...props
|
||||||
}: ButtonProps & {
|
}: Omit<ButtonProps, 'onChange'> & {
|
||||||
showManage?: boolean;
|
showManage?: boolean;
|
||||||
afterSwitchTeam?: () => void;
|
onChange?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -38,7 +38,7 @@ const TeamSelector = ({
|
|||||||
{
|
{
|
||||||
onFinally: () => {
|
onFinally: () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
afterSwitchTeam?.();
|
onChange?.();
|
||||||
},
|
},
|
||||||
errorToast: t('common:user.team.Switch Team Failed')
|
errorToast: t('common:user.team.Switch Team Failed')
|
||||||
}
|
}
|
||||||
|
@@ -142,7 +142,9 @@ const NodeCard = (props: Props) => {
|
|||||||
|
|
||||||
const { runAsync: onClickSyncVersion } = useRequest2(
|
const { runAsync: onClickSyncVersion } = useRequest2(
|
||||||
async () => {
|
async () => {
|
||||||
if (!node?.pluginId) return;
|
if (!node) return;
|
||||||
|
|
||||||
|
if (node.pluginId) {
|
||||||
const template = await getPreviewPluginNode({ appId: node.pluginId });
|
const template = await getPreviewPluginNode({ appId: node.pluginId });
|
||||||
|
|
||||||
if (!!template) {
|
if (!!template) {
|
||||||
@@ -151,10 +153,25 @@ const NodeCard = (props: Props) => {
|
|||||||
node: template
|
node: template
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onCloseConfirmSync();
|
} else {
|
||||||
|
const template = moduleTemplatesFlat.find(
|
||||||
|
(item) => item.flowNodeType === node.flowNodeType
|
||||||
|
);
|
||||||
|
if (!template) {
|
||||||
|
return toast({
|
||||||
|
title: t('app:app.modules.not_found_tips'),
|
||||||
|
status: 'warning'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onResetNode({
|
||||||
|
id: nodeId,
|
||||||
|
node: template
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
refreshDeps: [node, nodeId, onResetNode]
|
refreshDeps: [node, nodeId, onResetNode],
|
||||||
|
onFinally() {}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -311,7 +328,6 @@ const NodeCard = (props: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<MenuRender nodeId={nodeId} menuForbid={menuForbid} nodeList={nodeList} />
|
<MenuRender nodeId={nodeId} menuForbid={menuForbid} nodeList={nodeList} />
|
||||||
<ConfirmSyncModal />
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
@@ -335,7 +351,6 @@ const NodeCard = (props: Props) => {
|
|||||||
intro,
|
intro,
|
||||||
menuForbid,
|
menuForbid,
|
||||||
nodeList,
|
nodeList,
|
||||||
ConfirmSyncModal,
|
|
||||||
onChangeNode,
|
onChangeNode,
|
||||||
onOpenCustomTitleModal,
|
onOpenCustomTitleModal,
|
||||||
toast
|
toast
|
||||||
|
@@ -7,7 +7,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
|||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import React, { DragEvent, useCallback, useMemo, useState } from 'react';
|
import React, { DragEvent, useCallback, useMemo, useState } from 'react';
|
||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
import { useRequest } from '@fastgpt/web/hooks/useRequest';
|
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||||
import { getFileIcon } from '@fastgpt/global/common/file/icon';
|
import { getFileIcon } from '@fastgpt/global/common/file/icon';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { uploadFile2DB } from '@/web/common/file/controller';
|
import { uploadFile2DB } from '@/web/common/file/controller';
|
||||||
@@ -66,30 +66,9 @@ const FileSelector = ({
|
|||||||
'i'
|
'i'
|
||||||
);
|
);
|
||||||
|
|
||||||
const { mutate: onSelectFile, isLoading } = useRequest({
|
const { runAsync: onSelectFile, loading: isLoading } = useRequest2(
|
||||||
mutationFn: async (files: SelectFileItemType[]) => {
|
async (files: SelectFileItemType[]) => {
|
||||||
{
|
{
|
||||||
onStartSelect();
|
|
||||||
setSelectFiles((state) => {
|
|
||||||
const formatFiles = files.map<ImportSourceItemType>((selectFile) => {
|
|
||||||
const { fileId, file } = selectFile;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: fileId,
|
|
||||||
createStatus: 'waiting',
|
|
||||||
file,
|
|
||||||
sourceName: file.name,
|
|
||||||
sourceSize: formatFileSize(file.size),
|
|
||||||
icon: getFileIcon(file.name),
|
|
||||||
isUploading: true,
|
|
||||||
uploadedFileRate: 0
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const results = formatFiles.concat(state).slice(0, maxCount);
|
|
||||||
return results;
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
// upload file
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
files.map(async ({ fileId, file }) => {
|
files.map(async ({ fileId, file }) => {
|
||||||
const { fileId: uploadFileId } = await uploadFile2DB({
|
const { fileId: uploadFileId } = await uploadFile2DB({
|
||||||
@@ -127,13 +106,35 @@ const FileSelector = ({
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onBefore([files]) {
|
||||||
|
onStartSelect();
|
||||||
|
setSelectFiles((state) => {
|
||||||
|
const formatFiles = files.map<ImportSourceItemType>((selectFile) => {
|
||||||
|
const { fileId, file } = selectFile;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: fileId,
|
||||||
|
createStatus: 'waiting',
|
||||||
|
file,
|
||||||
|
sourceName: file.name,
|
||||||
|
sourceSize: formatFileSize(file.size),
|
||||||
|
icon: getFileIcon(file.name),
|
||||||
|
isUploading: true,
|
||||||
|
uploadedFileRate: 0
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const results = formatFiles.concat(state).slice(0, maxCount);
|
||||||
|
return results;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onFinally() {
|
||||||
onFinishSelect();
|
onFinishSelect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
const selectFileCallback = useCallback(
|
const selectFileCallback = useCallback(
|
||||||
(files: SelectFileItemType[]) => {
|
(files: SelectFileItemType[]) => {
|
||||||
|
@@ -284,7 +284,7 @@ const MyInfo = ({ onOpenContact }: { onOpenContact: () => void }) => {
|
|||||||
<Flex mt={6} alignItems={'center'}>
|
<Flex mt={6} alignItems={'center'}>
|
||||||
<Box {...labelStyles}>{t('account_info:user_team_team_name')}: </Box>
|
<Box {...labelStyles}>{t('account_info:user_team_team_name')}: </Box>
|
||||||
<Flex flex={'1 0 0'} w={0} align={'center'}>
|
<Flex flex={'1 0 0'} w={0} align={'center'}>
|
||||||
<TeamSelector height={'28px'} w={'100%'} showManage afterSwitchTeam={initUserInfo} />
|
<TeamSelector height={'28px'} w={'100%'} showManage onChange={initUserInfo} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
@@ -88,7 +88,7 @@ const Team = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex align={'center'} ml={6}>
|
<Flex align={'center'} ml={6}>
|
||||||
<TeamSelector height={'28px'} afterSwitchTeam={refetchMembers} />
|
<TeamSelector height={'28px'} onChange={refetchMembers} />
|
||||||
</Flex>
|
</Flex>
|
||||||
{userInfo?.team?.role === TeamMemberRoleEnum.owner && (
|
{userInfo?.team?.role === TeamMemberRoleEnum.owner && (
|
||||||
<Flex align={'center'} justify={'center'} ml={2} p={'0.44rem'}>
|
<Flex align={'center'} justify={'center'} ml={2} p={'0.44rem'}>
|
||||||
|
@@ -44,12 +44,22 @@ async function handler(
|
|||||||
defaultModels: global.systemDefaultModel
|
defaultModels: global.systemDefaultModel
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const referer = req.headers.referer;
|
||||||
|
if (referer?.includes('/price')) {
|
||||||
|
return {
|
||||||
|
feConfigs: global.feConfigs,
|
||||||
|
subPlans: global.subPlans,
|
||||||
|
activeModelList
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const unAuthBufferId = global.systemInitBufferId ? `unAuth_${global.systemInitBufferId}` : '';
|
const unAuthBufferId = global.systemInitBufferId ? `unAuth_${global.systemInitBufferId}` : '';
|
||||||
if (bufferId && unAuthBufferId === bufferId) {
|
if (bufferId && unAuthBufferId === bufferId) {
|
||||||
return {
|
return {
|
||||||
bufferId: unAuthBufferId
|
bufferId: unAuthBufferId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bufferId: unAuthBufferId,
|
bufferId: unAuthBufferId,
|
||||||
feConfigs: global.feConfigs
|
feConfigs: global.feConfigs
|
||||||
|
@@ -5,7 +5,7 @@ import {
|
|||||||
SseResponseEventEnum
|
SseResponseEventEnum
|
||||||
} from '@fastgpt/global/core/workflow/runtime/constants';
|
} from '@fastgpt/global/core/workflow/runtime/constants';
|
||||||
import { responseWrite } from '@fastgpt/service/common/response';
|
import { responseWrite } from '@fastgpt/service/common/response';
|
||||||
import { pushChatUsage } from '@/service/support/wallet/usage/push';
|
import { createChatUsage } from '@fastgpt/service/support/wallet/usage/controller';
|
||||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||||
import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type';
|
import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type';
|
||||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||||
@@ -244,7 +244,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pushChatUsage({
|
createChatUsage({
|
||||||
appName,
|
appName,
|
||||||
appId,
|
appId,
|
||||||
teamId,
|
teamId,
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { pushChatUsage } from '@/service/support/wallet/usage/push';
|
import { createChatUsage } from '@fastgpt/service/support/wallet/usage/controller';
|
||||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||||
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
|
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
|
||||||
@@ -66,8 +66,8 @@ async function handler(
|
|||||||
maxRunTimes: WORKFLOW_MAX_RUN_TIMES
|
maxRunTimes: WORKFLOW_MAX_RUN_TIMES
|
||||||
});
|
});
|
||||||
|
|
||||||
pushChatUsage({
|
createChatUsage({
|
||||||
appName: '工作流Debug',
|
appName: `${app.name}-Debug`,
|
||||||
appId,
|
appId,
|
||||||
teamId,
|
teamId,
|
||||||
tmbId,
|
tmbId,
|
||||||
|
@@ -20,7 +20,7 @@ import { GPTMessages2Chats, chatValue2RuntimePrompt } from '@fastgpt/global/core
|
|||||||
import { getChatItems } from '@fastgpt/service/core/chat/controller';
|
import { getChatItems } from '@fastgpt/service/core/chat/controller';
|
||||||
import { saveChat, updateInteractiveChat } from '@fastgpt/service/core/chat/saveChat';
|
import { saveChat, updateInteractiveChat } from '@fastgpt/service/core/chat/saveChat';
|
||||||
import { responseWrite } from '@fastgpt/service/common/response';
|
import { responseWrite } from '@fastgpt/service/common/response';
|
||||||
import { pushChatUsage } from '@/service/support/wallet/usage/push';
|
import { createChatUsage } from '@fastgpt/service/support/wallet/usage/controller';
|
||||||
import { authOutLinkChatStart } from '@/service/support/permission/auth/outLink';
|
import { authOutLinkChatStart } from '@/service/support/permission/auth/outLink';
|
||||||
import { pushResult2Remote, addOutLinkUsage } from '@fastgpt/service/support/outLink/tools';
|
import { pushResult2Remote, addOutLinkUsage } from '@fastgpt/service/support/outLink/tools';
|
||||||
import requestIp from 'request-ip';
|
import requestIp from 'request-ip';
|
||||||
@@ -423,7 +423,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add record
|
// add record
|
||||||
const { totalPoints } = pushChatUsage({
|
const { totalPoints } = createChatUsage({
|
||||||
appName: app.name,
|
appName: app.name,
|
||||||
appId: app._id,
|
appId: app._id,
|
||||||
teamId,
|
teamId,
|
||||||
|
@@ -67,9 +67,7 @@ const Login = ({ ChineseRedirectUrl }: { ChineseRedirectUrl: string }) => {
|
|||||||
// 检查是否是当前的 route
|
// 检查是否是当前的 route
|
||||||
const navigateTo =
|
const navigateTo =
|
||||||
decodeLastRoute && !decodeLastRoute.includes('/login') ? decodeLastRoute : '/app/list';
|
decodeLastRoute && !decodeLastRoute.includes('/login') ? decodeLastRoute : '/app/list';
|
||||||
setTimeout(() => {
|
|
||||||
router.push(navigateTo);
|
router.push(navigateTo);
|
||||||
}, 300);
|
|
||||||
},
|
},
|
||||||
[setUserInfo, lastRoute, router]
|
[setUserInfo, lastRoute, router]
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { getUserChatInfoAndAuthTeamPoints } from '@fastgpt/service/support/permission/auth/team';
|
import { getUserChatInfoAndAuthTeamPoints } from '@fastgpt/service/support/permission/auth/team';
|
||||||
import { pushChatUsage } from '@/service/support/wallet/usage/push';
|
import { createChatUsage } from '@fastgpt/service/support/wallet/usage/controller';
|
||||||
import { getNextTimeByCronStringAndTimezone } from '@fastgpt/global/common/string/time';
|
import { getNextTimeByCronStringAndTimezone } from '@fastgpt/global/common/string/time';
|
||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
import { delay, retryFn } from '@fastgpt/global/common/system/utils';
|
import { delay, retryFn } from '@fastgpt/global/common/system/utils';
|
||||||
@@ -113,7 +113,7 @@ export const getScheduleTriggerApp = async () => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
pushChatUsage({
|
createChatUsage({
|
||||||
appName: app.name,
|
appName: app.name,
|
||||||
appId: app._id,
|
appId: app._id,
|
||||||
teamId: String(app.teamId),
|
teamId: String(app.teamId),
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
import { ConcatUsageProps, CreateUsageProps } from '@fastgpt/global/support/wallet/usage/api';
|
|
||||||
import { addLog } from '@fastgpt/service/common/system/log';
|
|
||||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
|
||||||
import { FastGPTProUrl } from '@fastgpt/service/common/system/constants';
|
|
||||||
|
|
||||||
export async function createUsage(data: CreateUsageProps) {
|
|
||||||
if (!FastGPTProUrl) return;
|
|
||||||
if (data.totalPoints === 0) {
|
|
||||||
addLog.info('0 totalPoints', data);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await POST('/support/wallet/usage/createUsage', data);
|
|
||||||
} catch (error) {
|
|
||||||
addLog.error('createUsage error', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function concatUsage(data: ConcatUsageProps) {
|
|
||||||
if (!FastGPTProUrl) return;
|
|
||||||
if (data.totalPoints === 0) {
|
|
||||||
addLog.info('0 totalPoints', data);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await POST('/support/wallet/usage/concatUsage', data);
|
|
||||||
} catch (error) {
|
|
||||||
addLog.error('concatUsage error', error);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,55 +1,10 @@
|
|||||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||||
import { addLog } from '@fastgpt/service/common/system/log';
|
import { createUsage, concatUsage } from '@fastgpt/service/support/wallet/usage/controller';
|
||||||
import { createUsage, concatUsage } from './controller';
|
|
||||||
import { formatModelChars2Points } from '@fastgpt/service/support/wallet/usage/utils';
|
import { formatModelChars2Points } from '@fastgpt/service/support/wallet/usage/utils';
|
||||||
import { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type';
|
|
||||||
import { i18nT } from '@fastgpt/web/i18n/utils';
|
import { i18nT } from '@fastgpt/web/i18n/utils';
|
||||||
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
||||||
import { getDefaultTTSModel } from '@fastgpt/service/core/ai/model';
|
import { getDefaultTTSModel } from '@fastgpt/service/core/ai/model';
|
||||||
|
|
||||||
export const pushChatUsage = ({
|
|
||||||
appName,
|
|
||||||
appId,
|
|
||||||
pluginId,
|
|
||||||
teamId,
|
|
||||||
tmbId,
|
|
||||||
source,
|
|
||||||
flowUsages
|
|
||||||
}: {
|
|
||||||
appName: string;
|
|
||||||
appId?: string;
|
|
||||||
pluginId?: string;
|
|
||||||
teamId: string;
|
|
||||||
tmbId: string;
|
|
||||||
source: UsageSourceEnum;
|
|
||||||
flowUsages: ChatNodeUsageType[];
|
|
||||||
}) => {
|
|
||||||
const totalPoints = flowUsages.reduce((sum, item) => sum + (item.totalPoints || 0), 0);
|
|
||||||
|
|
||||||
createUsage({
|
|
||||||
teamId,
|
|
||||||
tmbId,
|
|
||||||
appName,
|
|
||||||
appId,
|
|
||||||
pluginId,
|
|
||||||
totalPoints,
|
|
||||||
source,
|
|
||||||
list: flowUsages.map((item) => ({
|
|
||||||
moduleName: item.moduleName,
|
|
||||||
amount: item.totalPoints || 0,
|
|
||||||
model: item.model,
|
|
||||||
inputTokens: item.inputTokens,
|
|
||||||
outputTokens: item.outputTokens
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
addLog.info(`finish completions`, {
|
|
||||||
source,
|
|
||||||
teamId,
|
|
||||||
totalPoints
|
|
||||||
});
|
|
||||||
return { totalPoints };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const pushQAUsage = async ({
|
export const pushQAUsage = async ({
|
||||||
teamId,
|
teamId,
|
||||||
tmbId,
|
tmbId,
|
||||||
|
@@ -31,7 +31,7 @@ export const uploadFile2DB = ({
|
|||||||
if (!e.total) return;
|
if (!e.total) return;
|
||||||
|
|
||||||
const percent = Math.round((e.loaded / e.total) * 100);
|
const percent = Math.round((e.loaded / e.total) * 100);
|
||||||
percentListen && percentListen(percent);
|
percentListen?.(percent);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user