Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/global/openapi/admin/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { DashboardPath } from './dashboard';
import { AdminAppPath } from './app';
import { AdminRoutesPath } from '../routes';
import { AdminCommonPath } from '../common';
import { StatusPath } from './status';
import type { OpenAPIPath } from '../../type';

export const AdminCorePath: OpenAPIPath = {
...DashboardPath,
...AdminAppPath,
...AdminRoutesPath,
...AdminCommonPath
...AdminCommonPath,
...StatusPath
};
94 changes: 94 additions & 0 deletions packages/global/openapi/admin/core/status/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import z from 'zod';
import { ObjectIdSchema } from '../../../../common/type/mongo';
import { PaginationResponseSchema, PaginationSchema } from '../../../api';

export const TrainingRecordStateEnumSchema = z.enum([
'queued',
'processing',
'retrying',
'final_error',
'blocked',
'exhausted_without_error'
]);
export type TrainingRecordState = z.infer<typeof TrainingRecordStateEnumSchema>;

export const TrainingRecordStateFilterEnumSchema = z.enum(['queued', 'processing', 'error']);
export type TrainingRecordStateFilter = z.infer<typeof TrainingRecordStateFilterEnumSchema>;

export const TrainingRecordActionEnumSchema = z.enum(['retry', 'delete']);
export type TrainingRecordAction = z.infer<typeof TrainingRecordActionEnumSchema>;

export const TrainingTaskSummarySchema = z.object({
mode: z.literal('chunk').meta({ description: '固定为 Chunk 向量训练' }),
queued: z.number().meta({ description: '排队任务数' }),
processing: z.number().meta({ description: '处理中任务数' }),
retrying: z.number().meta({ description: '自动重试任务数' }),
finalError: z.number().meta({ description: '最终失败任务数' }),
blocked: z.number().meta({ description: '永久阻塞任务数' }),
exhaustedWithoutError: z.number().meta({ description: '无错误但重试耗尽任务数' }),
total: z.number().meta({ description: '当前训练任务总数' }),
completed: z.number().meta({ description: '已完成 Chunk 数量' }),
severity: z.enum(['normal', 'warning', 'severe']).meta({ description: '运维告警等级' })
});
export type TrainingTaskSummaryType = z.infer<typeof TrainingTaskSummarySchema>;

export const GetTrainingTaskListResponseSchema = TrainingTaskSummarySchema;
export type GetTrainingTaskListResponseType = z.infer<typeof GetTrainingTaskListResponseSchema>;

export const GetTrainingRecordListBodySchema = PaginationSchema.extend({
search: z.string().trim().min(1).optional().meta({ description: '训练 ID、知识库或团队名称' }),
state: TrainingRecordStateFilterEnumSchema.optional().meta({ description: '训练状态筛选' })
});
export type GetTrainingRecordListBody = z.infer<typeof GetTrainingRecordListBodySchema>;

export const TrainingRecordSchema = z.object({
id: ObjectIdSchema.meta({ description: '训练任务 ID' }),
datasetId: ObjectIdSchema.meta({ description: '知识库 ID' }),
collectionId: ObjectIdSchema.meta({ description: '集合 ID' }),
datasetName: z.string().meta({ description: '知识库名称' }),
collectionName: z.string().optional().meta({ description: '集合名称' }),
teamName: z.string().optional().meta({ description: '团队名称' }),
model: z.string().optional().meta({ description: 'Embedding 模型' }),
chunkIndex: z.number().optional().meta({ description: '分块序号' }),
dataId: ObjectIdSchema.optional().meta({ description: '重建关联的数据 ID' }),
q: z.string().optional().meta({ description: '分块主文本' }),
a: z.string().optional().meta({ description: '分块补充文本' }),
retryCount: z.number().meta({ description: '剩余重试次数' }),
state: TrainingRecordStateEnumSchema.meta({ description: '训练状态' }),
actions: z
.array(TrainingRecordActionEnumSchema)
.meta({ description: '当前状态允许的管理员操作' }),
error: z.string().optional().meta({ description: '最近错误信息' }),
lockTime: z.string().optional().meta({ description: '任务租约时间' })
});
export type TrainingRecordType = z.infer<typeof TrainingRecordSchema>;

export const GetTrainingRecordListResponseSchema = PaginationResponseSchema(TrainingRecordSchema);
export type GetTrainingRecordListResponseType = z.infer<typeof GetTrainingRecordListResponseSchema>;

export const TrainingActionBodySchema = z.object({
id: ObjectIdSchema.meta({ description: '训练任务 ID' }),
action: z.enum(['retry', 'delete']).meta({ description: '管理员操作' })
});
export type TrainingActionBody = z.infer<typeof TrainingActionBodySchema>;

export const TrainingActionResponseSchema = z.object({
affectedCount: z.number().meta({ description: '实际影响的任务数量' })
});
export type TrainingActionResponseType = z.infer<typeof TrainingActionResponseSchema>;

export const StatusOverviewAlertSchema = z.object({
level: z.literal('warning').meta({ description: '告警等级' }),
title: z.string().meta({ description: '告警标题' }),
description: z.string().meta({ description: '告警描述' }),
source: z.string().meta({ description: '告警来源' }),
scope: z.string().meta({ description: '告警范围' }),
count: z.number().meta({ description: '异常数量' })
});
export type StatusOverviewAlertType = z.infer<typeof StatusOverviewAlertSchema>;

export const GetStatusOverviewResponseSchema = z.object({
unresolvedCount: z.number().meta({ description: '未恢复告警数' }),
alerts: z.array(StatusOverviewAlertSchema).meta({ description: '告警消息列表' })
});
export type GetStatusOverviewResponseType = z.infer<typeof GetStatusOverviewResponseSchema>;
67 changes: 67 additions & 0 deletions packages/global/openapi/admin/core/status/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { OpenAPIPath } from '../../../type';
import {
GetStatusOverviewResponseSchema,
GetTrainingRecordListBodySchema,
GetTrainingRecordListResponseSchema,
GetTrainingTaskListResponseSchema,
TrainingActionBodySchema,
TrainingActionResponseSchema
} from './api';
import { DevApiTagsMap } from '../../../tag';

export const StatusPath: OpenAPIPath = {
'/admin/status/overview': {
get: {
summary: '获取 Chunk 训练总览告警',
tags: [DevApiTagsMap.adminStatus],
responses: {
200: {
description: '成功获取训练总览告警',
content: { 'application/json': { schema: GetStatusOverviewResponseSchema } }
}
}
}
},
'/admin/status/dataset/tasks': {
get: {
summary: '获取 Chunk 训练状态汇总',
tags: [DevApiTagsMap.adminStatus],
responses: {
200: {
description: '成功获取训练状态汇总',
content: { 'application/json': { schema: GetTrainingTaskListResponseSchema } }
}
}
}
},
'/admin/status/dataset/training': {
post: {
summary: '获取 Chunk 训练任务列表',
tags: [DevApiTagsMap.adminStatus],
requestBody: {
content: { 'application/json': { schema: GetTrainingRecordListBodySchema } }
},
responses: {
200: {
description: '成功获取训练任务列表',
content: { 'application/json': { schema: GetTrainingRecordListResponseSchema } }
}
}
}
},
'/admin/status/dataset/training/action': {
post: {
summary: '重试或删除 Chunk 训练任务',
tags: [DevApiTagsMap.adminStatus],
requestBody: {
content: { 'application/json': { schema: TrainingActionBodySchema } }
},
responses: {
200: {
description: '成功执行训练任务操作',
content: { 'application/json': { schema: TrainingActionResponseSchema } }
}
}
}
}
};
7 changes: 6 additions & 1 deletion packages/global/openapi/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ export const adminOpenAPIPaths: NonNullable<OpenAPIPath> = {
export const adminOpenAPITagGroups = [
{
name: '管理员-系统概览',
tags: [DevApiTagsMap.adminDashboard, DevApiTagsMap.adminLogs, DevApiTagsMap.adminLicense]
tags: [
DevApiTagsMap.adminDashboard,
DevApiTagsMap.adminStatus,
DevApiTagsMap.adminLogs,
DevApiTagsMap.adminLicense
]
},
{
name: '管理员-资源管理',
Expand Down
1 change: 1 addition & 0 deletions packages/global/openapi/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const DevApiTagsMap = {

/* 管理员-系统管理 */
adminDashboard: '仪表盘',
adminStatus: '运维数据',
adminInform: '通知管理',
adminApps: '应用管理',
adminWalletCoupon: '兑换码管理',
Expand Down
13 changes: 13 additions & 0 deletions packages/service/core/dataset/training/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
TrainingModeEnum
} from '@fastgpt/global/core/dataset/constants';
import type { DatasetTrainingSchemaType } from '@fastgpt/global/core/dataset/type';
import { subMinutes } from 'date-fns';

type TrainingStatusCount = {
activeCount: number;
Expand All @@ -11,6 +12,18 @@ type TrainingStatusCount = {

export const BLOCKED_LOCK_TIME = new Date('2050-01-01');

export const trainingModeLockTimeoutMinutes: Record<TrainingModeEnum, number> = {
[TrainingModeEnum.parse]: 10,
[TrainingModeEnum.imageParse]: 10,
[TrainingModeEnum.qa]: 10,
[TrainingModeEnum.image]: 10,
[TrainingModeEnum.auto]: 10,
[TrainingModeEnum.chunk]: 3
};

export const getTrainingLockExpireTime = (mode: TrainingModeEnum, now = new Date()) =>
subMinutes(now, trainingModeLockTimeoutMinutes[mode]);

export const trainingModeRankMap: Record<TrainingModeEnum, number> = {
[TrainingModeEnum.parse]: 0,
[TrainingModeEnum.imageParse]: 1,
Expand Down
Loading
Loading