Files
FastGPT/packages/service/support/wallet/usage/controller.ts
Archer 13b7e0a192 V4.11.0 features (#5270)
* feat: workflow catch error (#5220)

* feat: error catch

* feat: workflow catch error

* perf: add catch error to node

* feat: system tool error catch

* catch error

* fix: ts

* update doc

* perf: training queue code (#5232)

* doc

* perf: training queue code

* Feat: 优化错误提示与重试逻辑 (#5192)

* feat: 批量重试异常数据 & 报错信息国际化

  - 新增“全部重试”按钮,支持批量重试所有训练异常数据
  - 报错信息支持国际化,常见错误自动映射为 i18n key
  - 相关文档和 i18n 资源已同步更新

* feat: enhance error message and retry mechanism

* feat: enhance error message and retry mechanism

* feat: add retry_failed i18n key

* feat: enhance error message and retry mechanism

* feat: enhance error message and retry mechanism

* feat: enhance error message and retry mechanism : 5

* feat: enhance error message and retry mechanism : 6

* feat: enhance error message and retry mechanism : 7

* feat: enhance error message and retry mechanism : 8

* perf: catch chat error

* perf: copy hook (#5246)

* perf: copy hook

* doc

* doc

* add app evaluation (#5083)

* add app evaluation

* fix

* usage

* variables

* editing condition

* var ui

* isplus filter

* migrate code

* remove utils

* name

* update type

* build

* fix

* fix

* fix

* delete comment

* fix

* perf: eval code

* eval code

* eval code

* feat: ttfb time in model log

* Refactor chat page (#5253)

* feat: update side bar layout; add login and logout logic at chat page

* refactor: encapsulate login logic and reuse it in `LoginModal` and `Login` page

* chore: improve some logics and comments

* chore: improve some logics

* chore: remove redundant side effect; add translations

---------

Co-authored-by: Archer <545436317@qq.com>

* perf: chat page code

* doc

* perf: provider redirect

* chore: ui improvement (#5266)

* Fix: SSE

* Fix: SSE

* eval pagination (#5264)

* eval scroll pagination

* change eval list to manual pagination

* number

* fix build

* fix

* version doc (#5267)

* version doc

* version doc

* doc

* feat: eval model select

* config eval model

* perf: eval detail modal ui

* doc

* doc

* fix: chat store reload

* doc

---------

Co-authored-by: colnii <1286949794@qq.com>
Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: 酒川户 <76519998+chuanhu9@users.noreply.github.com>
2025-07-22 09:42:50 +08:00

281 lines
6.1 KiB
TypeScript

import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
import { MongoUsage } from './schema';
import { type ClientSession } from '../../../common/mongo';
import { addLog } from '../../../common/system/log';
import { type ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type';
import {
type ConcatUsageProps,
type CreateUsageProps
} from '@fastgpt/global/support/wallet/usage/api';
import { i18nT } from '../../../../web/i18n/utils';
import { formatModelChars2Points } from './utils';
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
export async function createUsage(data: CreateUsageProps) {
try {
await global.createUsageHandler(data);
} catch (error) {
addLog.error('createUsage error', error);
}
}
export async function concatUsage(data: ConcatUsageProps) {
try {
await global.concatUsageHandler(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 type DatasetTrainingMode = 'paragraph' | 'qa' | 'autoIndex' | 'imageIndex' | 'imageParse';
export const datasetTrainingUsageIndexMap: Record<DatasetTrainingMode, number> = {
paragraph: 1,
qa: 2,
autoIndex: 3,
imageIndex: 4,
imageParse: 5
};
export const createTrainingUsage = async ({
teamId,
tmbId,
appName,
billSource,
vectorModel,
agentModel,
vllmModel,
session
}: {
teamId: string;
tmbId: string;
appName: string;
billSource: UsageSourceEnum;
vectorModel?: string;
agentModel?: string;
vllmModel?: string;
session?: ClientSession;
}) => {
const [{ _id }] = await MongoUsage.create(
[
{
teamId,
tmbId,
appName,
source: billSource,
totalPoints: 0,
list: [
...(vectorModel
? [
{
moduleName: i18nT('account_usage:embedding_index'),
model: vectorModel,
amount: 0,
inputTokens: 0,
outputTokens: 0
}
]
: []),
...(agentModel
? [
{
moduleName: i18nT('account_usage:llm_paragraph'),
model: agentModel,
amount: 0,
inputTokens: 0,
outputTokens: 0
},
{
moduleName: i18nT('account_usage:qa'),
model: agentModel,
amount: 0,
inputTokens: 0,
outputTokens: 0
},
{
moduleName: i18nT('account_usage:auto_index'),
model: agentModel,
amount: 0,
inputTokens: 0,
outputTokens: 0
}
]
: []),
...(vllmModel
? [
{
moduleName: i18nT('account_usage:image_index'),
model: vllmModel,
amount: 0,
inputTokens: 0,
outputTokens: 0
},
{
moduleName: i18nT('account_usage:image_parse'),
model: vllmModel,
amount: 0,
inputTokens: 0,
outputTokens: 0
}
]
: [])
]
}
],
{ session, ordered: true }
);
return { billId: String(_id) };
};
export const createPdfParseUsage = async ({
teamId,
tmbId,
pages
}: {
teamId: string;
tmbId: string;
pages: number;
}) => {
const unitPrice = global.systemEnv?.customPdfParse?.price || 0;
const totalPoints = pages * unitPrice;
createUsage({
teamId,
tmbId,
appName: i18nT('account_usage:pdf_enhanced_parse'),
totalPoints,
source: UsageSourceEnum.pdfParse,
list: [
{
moduleName: i18nT('account_usage:pdf_enhanced_parse'),
amount: totalPoints,
pages
}
]
});
};
export const pushLLMTrainingUsage = async ({
teamId,
tmbId,
model,
inputTokens,
outputTokens,
billId,
mode
}: {
teamId: string;
tmbId: string;
model: string;
inputTokens: number;
outputTokens: number;
billId: string;
mode: DatasetTrainingMode;
}) => {
const index = datasetTrainingUsageIndexMap[mode];
// Compute points
const { totalPoints } = formatModelChars2Points({
model,
modelType: ModelTypeEnum.llm,
inputTokens,
outputTokens
});
concatUsage({
billId,
teamId,
tmbId,
totalPoints,
inputTokens,
outputTokens,
listIndex: index
});
return { totalPoints };
};
export const createEvaluationUsage = async ({
teamId,
tmbId,
appName,
model,
session
}: {
teamId: string;
tmbId: string;
appName: string;
model: string;
session?: ClientSession;
}) => {
const [{ _id: usageId }] = await MongoUsage.create(
[
{
teamId,
tmbId,
appName,
source: UsageSourceEnum.evaluation,
totalPoints: 0,
list: [
{
moduleName: i18nT('account_usage:generate_answer'),
amount: 0,
count: 0
},
{
moduleName: i18nT('account_usage:answer_accuracy'),
amount: 0,
inputTokens: 0,
outputTokens: 0,
model
}
]
}
],
{ session, ordered: true }
);
return { usageId };
};