Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
2eeea151
authored
Jun 23, 2026
by
light5980
Committed by
GitHub
Jun 23, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
debug: training count error (#7169)
parent
b46748e1
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
375 additions
and
82 deletions
+375
-82
projects/app/src/pageComponents/dataset/detail/CollectionCard/TrainingStates.tsx
+43
-69
projects/app/src/pageComponents/dataset/detail/CollectionCard/trainingStatesUtils.ts
+56
-0
projects/app/src/pages/api/core/dataset/collection/trainingDetail.ts
+25
-12
projects/app/test/api/core/dataset/collection/trainingStatus.test.ts
+85
-1
projects/app/test/pageComponents/dataset/detail/CollectionCard/trainingStatesUtils.test.ts
+166
-0
No files found.
projects/app/src/pageComponents/dataset/detail/CollectionCard/TrainingStates.tsx
View file @
2eeea151
...
@@ -14,14 +14,12 @@ import type { GetCollectionTrainingDetailResponseType } from '@fastgpt/global/op
...
@@ -14,14 +14,12 @@ import type { GetCollectionTrainingDetailResponseType } from '@fastgpt/global/op
import
type
{
Permission
}
from
'@fastgpt/global/support/permission/controller'
;
import
type
{
Permission
}
from
'@fastgpt/global/support/permission/controller'
;
import
React
from
'react'
;
import
React
from
'react'
;
import
TrainingErrorList
from
'./TrainingErrorList'
;
import
TrainingErrorList
from
'./TrainingErrorList'
;
import
{
enum
TrainingStatus
{
getTrainingStepStatus
,
NotStart
=
'NotStart'
,
isTrainingDetailReady
,
Queued
=
'Queued'
,
// wait count>0
isTrainingStepHighlighted
,
Running
=
'Running'
,
// wait count=0; training count>0.
TrainingStatus
Ready
=
'Ready'
,
}
from
'./trainingStatesUtils'
;
Error
=
'Error'
}
const
ProgressView
=
({
const
ProgressView
=
({
trainingDetail
trainingDetail
...
@@ -36,28 +34,23 @@ const ProgressView = ({
...
@@ -36,28 +34,23 @@ const ProgressView = ({
const
isImageIndex
=
trainingDetail
.
advancedTraining
.
imageIndex
;
const
isImageIndex
=
trainingDetail
.
advancedTraining
.
imageIndex
;
const
isAutoIndexes
=
trainingDetail
.
advancedTraining
.
autoIndexes
;
const
isAutoIndexes
=
trainingDetail
.
advancedTraining
.
autoIndexes
;
/*
状态计算
1. 暂时没有内容解析的状态
2. 完全没有训练数据时候,已就绪
3. 有训练数据,中间过程全部是进行中
*/
const
statesArray
=
useMemo
(()
=>
{
const
statesArray
=
useMemo
(()
=>
{
const
isReady
=
const
isReady
=
isTrainingDetailReady
(
trainingDetail
);
Object
.
values
(
trainingDetail
.
queuedCounts
).
every
((
count
)
=>
count
===
0
)
&&
const
modeOrder
=
[
Object
.
values
(
trainingDetail
.
trainingCounts
).
every
((
count
)
=>
count
===
0
)
&&
TrainingModeEnum
.
parse
,
Object
.
values
(
trainingDetail
.
errorCounts
).
every
((
count
)
=>
count
===
0
);
...(
isImageParse
?
[
TrainingModeEnum
.
imageParse
]
:
[]),
...(
isQA
?
[
TrainingModeEnum
.
qa
]
:
[]),
const
isContentParsing
=
trainingDetail
.
trainingCounts
.
parse
>
0
;
...(
isImageIndex
?
[
TrainingModeEnum
.
image
]
:
[]),
...(
isAutoIndexes
?
[
TrainingModeEnum
.
auto
]
:
[]),
TrainingModeEnum
.
chunk
];
const
getTrainingStatus
=
({
errorCount
}:
{
errorCount
:
number
})
=>
{
const
getTrainingStatus
=
(
mode
:
TrainingModeEnum
)
=>
if
(
isContentParsing
)
return
TrainingStatus
.
NotStart
;
getTrainingStepStatus
({
if
(
isReady
)
return
TrainingStatus
.
Ready
;
trainingDetail
,
if
(
errorCount
>
0
)
{
mode
,
return
TrainingStatus
.
Error
;
modeOrder
}
});
return
TrainingStatus
.
Running
;
};
// 只显示排队和处理中的数量
// 只显示排队和处理中的数量
const
getStatusText
=
(
mode
:
TrainingModeEnum
)
=>
{
const
getStatusText
=
(
mode
:
TrainingModeEnum
)
=>
{
...
@@ -85,9 +78,7 @@ const ProgressView = ({
...
@@ -85,9 +78,7 @@ const ProgressView = ({
{
{
label
:
t
(
TrainingProcess
.
parsing
.
label
),
label
:
t
(
TrainingProcess
.
parsing
.
label
),
statusText
:
getStatusText
(
TrainingModeEnum
.
parse
),
statusText
:
getStatusText
(
TrainingModeEnum
.
parse
),
status
:
getTrainingStatus
({
status
:
getTrainingStatus
(
TrainingModeEnum
.
parse
),
errorCount
:
trainingDetail
.
errorCounts
.
parse
}),
errorCount
:
trainingDetail
.
errorCounts
.
parse
errorCount
:
trainingDetail
.
errorCounts
.
parse
},
},
...(
isImageParse
...(
isImageParse
...
@@ -96,9 +87,7 @@ const ProgressView = ({
...
@@ -96,9 +87,7 @@ const ProgressView = ({
errorCount
:
trainingDetail
.
errorCounts
.
imageParse
,
errorCount
:
trainingDetail
.
errorCounts
.
imageParse
,
label
:
t
(
TrainingProcess
.
parseImage
.
label
),
label
:
t
(
TrainingProcess
.
parseImage
.
label
),
statusText
:
getStatusText
(
TrainingModeEnum
.
imageParse
),
statusText
:
getStatusText
(
TrainingModeEnum
.
imageParse
),
status
:
getTrainingStatus
({
status
:
getTrainingStatus
(
TrainingModeEnum
.
imageParse
)
errorCount
:
trainingDetail
.
errorCounts
.
imageParse
})
}
}
]
]
:
[]),
:
[]),
...
@@ -107,9 +96,7 @@ const ProgressView = ({
...
@@ -107,9 +96,7 @@ const ProgressView = ({
{
{
label
:
t
(
TrainingProcess
.
getQA
.
label
),
label
:
t
(
TrainingProcess
.
getQA
.
label
),
statusText
:
getStatusText
(
TrainingModeEnum
.
qa
),
statusText
:
getStatusText
(
TrainingModeEnum
.
qa
),
status
:
getTrainingStatus
({
status
:
getTrainingStatus
(
TrainingModeEnum
.
qa
),
errorCount
:
trainingDetail
.
errorCounts
.
qa
}),
errorCount
:
trainingDetail
.
errorCounts
.
qa
errorCount
:
trainingDetail
.
errorCounts
.
qa
}
}
]
]
...
@@ -120,9 +107,7 @@ const ProgressView = ({
...
@@ -120,9 +107,7 @@ const ProgressView = ({
errorCount
:
trainingDetail
.
errorCounts
.
image
,
errorCount
:
trainingDetail
.
errorCounts
.
image
,
label
:
t
(
TrainingProcess
.
imageIndex
.
label
),
label
:
t
(
TrainingProcess
.
imageIndex
.
label
),
statusText
:
getStatusText
(
TrainingModeEnum
.
image
),
statusText
:
getStatusText
(
TrainingModeEnum
.
image
),
status
:
getTrainingStatus
({
status
:
getTrainingStatus
(
TrainingModeEnum
.
image
)
errorCount
:
trainingDetail
.
errorCounts
.
image
})
}
}
]
]
:
[]),
:
[]),
...
@@ -132,9 +117,7 @@ const ProgressView = ({
...
@@ -132,9 +117,7 @@ const ProgressView = ({
errorCount
:
trainingDetail
.
errorCounts
.
auto
,
errorCount
:
trainingDetail
.
errorCounts
.
auto
,
label
:
t
(
TrainingProcess
.
autoIndex
.
label
),
label
:
t
(
TrainingProcess
.
autoIndex
.
label
),
statusText
:
getStatusText
(
TrainingModeEnum
.
auto
),
statusText
:
getStatusText
(
TrainingModeEnum
.
auto
),
status
:
getTrainingStatus
({
status
:
getTrainingStatus
(
TrainingModeEnum
.
auto
)
errorCount
:
trainingDetail
.
errorCounts
.
auto
})
}
}
]
]
:
[]),
:
[]),
...
@@ -142,9 +125,7 @@ const ProgressView = ({
...
@@ -142,9 +125,7 @@ const ProgressView = ({
errorCount
:
trainingDetail
.
errorCounts
.
chunk
,
errorCount
:
trainingDetail
.
errorCounts
.
chunk
,
label
:
t
(
TrainingProcess
.
vectorizing
.
label
),
label
:
t
(
TrainingProcess
.
vectorizing
.
label
),
statusText
:
getStatusText
(
TrainingModeEnum
.
chunk
),
statusText
:
getStatusText
(
TrainingModeEnum
.
chunk
),
status
:
getTrainingStatus
({
status
:
getTrainingStatus
(
TrainingModeEnum
.
chunk
)
errorCount
:
trainingDetail
.
errorCounts
.
chunk
})
},
},
{
{
errorCount
:
0
,
errorCount
:
0
,
...
@@ -159,21 +140,16 @@ const ProgressView = ({
...
@@ -159,21 +140,16 @@ const ProgressView = ({
];
];
return
states
;
return
states
;
},
[
},
[
trainingDetail
,
isImageIndex
,
isAutoIndexes
,
t
,
isImageParse
,
isQA
]);
trainingDetail
.
queuedCounts
,
trainingDetail
.
trainingCounts
,
trainingDetail
.
errorCounts
,
isImageIndex
,
isAutoIndexes
,
trainingDetail
.
trainedCount
,
t
,
isImageParse
,
isQA
]);
return
(
return
(
<
Flex
flexDirection=
{
'column'
}
gap=
{
6
}
>
<
Flex
flexDirection=
{
'column'
}
gap=
{
6
}
>
{
statesArray
.
map
((
item
,
index
)
=>
(
{
statesArray
.
map
((
item
,
index
)
=>
{
const
isHighlighted
=
isTrainingStepHighlighted
(
item
.
status
);
const
isActive
=
item
.
status
===
TrainingStatus
.
Queued
||
item
.
status
===
TrainingStatus
.
Running
;
return
(
<
Flex
alignItems=
{
'center'
}
pl=
{
4
}
key=
{
index
}
>
<
Flex
alignItems=
{
'center'
}
pl=
{
4
}
key=
{
index
}
>
{
/* Status round */
}
{
/* Status round */
}
<
Box
<
Box
...
@@ -185,16 +161,13 @@ const ProgressView = ({
...
@@ -185,16 +161,13 @@ const ProgressView = ({
display=
{
'flex'
}
display=
{
'flex'
}
alignItems=
{
'center'
}
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
justifyContent=
{
'center'
}
{
...
((
item
.
status
===
TrainingStatus
.
Running
||
{
...
(
isHighlighted
&&
{
item
.
status
===
TrainingStatus
.
Error
)
&&
{
bg
:
'
primary
.
600',
borderColor
:
'
primary
.
600',
boxShadow
:
'0
0
0
4
px
var
(--
Royal
-
Blue
-100,
#
E1EAFF
)'
})}
{
...
(
item
.
status
===
TrainingStatus
.
Ready
&&
{
bg
:
'
primary
.
600',
bg
:
'
primary
.
600',
borderColor
:
'
primary
.
600'
borderColor
:
'
primary
.
600'
})}
})}
{
...
(
isActive
&&
{
boxShadow
:
'0
0
0
4
px
var
(--
Royal
-
Blue
-100,
#
E1EAFF
)'
})}
// Line
// Line
{
...
(
index
!==
statesArray
.
length
-
1
&&
{
{
...
(
index
!==
statesArray
.
length
-
1
&&
{
_after
:
{
_after
:
{
...
@@ -217,10 +190,10 @@ const ProgressView = ({
...
@@ -217,10 +190,10 @@ const ProgressView = ({
alignItems=
{
'center'
}
alignItems=
{
'center'
}
w=
{
'full'
}
w=
{
'full'
}
bg=
{
bg=
{
item
.
status
===
TrainingStatus
.
Running
item
.
status
===
TrainingStatus
.
Error
?
'primary.50'
:
item
.
status
===
TrainingStatus
.
Error
?
'red.50'
?
'red.50'
:
isHighlighted
?
'primary.50'
:
'myGray.50'
:
'myGray.50'
}
}
py=
{
2.5
}
py=
{
2.5
}
...
@@ -259,7 +232,8 @@ const ProgressView = ({
...
@@ -259,7 +232,8 @@ const ProgressView = ({
)
}
)
}
</
Flex
>
</
Flex
>
</
Flex
>
</
Flex
>
))
}
);
})
}
</
Flex
>
</
Flex
>
);
);
};
};
...
...
projects/app/src/pageComponents/dataset/detail/CollectionCard/trainingStatesUtils.ts
0 → 100644
View file @
2eeea151
import
type
{
TrainingModeEnum
}
from
'@fastgpt/global/core/dataset/constants'
;
import
type
{
GetCollectionTrainingDetailResponseType
}
from
'@fastgpt/global/openapi/core/dataset/collection/api'
;
export
enum
TrainingStatus
{
NotStart
=
'NotStart'
,
Queued
=
'Queued'
,
Running
=
'Running'
,
Ready
=
'Ready'
,
Error
=
'Error'
}
/**
* 训练进度弹窗只有未开始阶段置灰;已完成、排队中、处理中和异常阶段都需要保持视觉激活。
*/
export
const
isTrainingStepHighlighted
=
(
status
:
TrainingStatus
)
=>
status
!==
TrainingStatus
.
NotStart
;
/**
* 判断当前集合是否已经没有任何剩余训练或最终异常。
*/
export
const
isTrainingDetailReady
=
(
trainingDetail
:
GetCollectionTrainingDetailResponseType
)
=>
Object
.
values
(
trainingDetail
.
queuedCounts
).
every
((
count
)
=>
count
===
0
)
&&
Object
.
values
(
trainingDetail
.
trainingCounts
).
every
((
count
)
=>
count
===
0
)
&&
Object
.
values
(
trainingDetail
.
errorCounts
).
every
((
count
)
=>
count
===
0
);
/**
* 根据当前集合各训练阶段的计数计算单个阶段的展示状态。
* 已进入后续阶段时,前序阶段展示为完成;仍被前序阶段阻塞时,后续阶段保持未开始。
*/
export
const
getTrainingStepStatus
=
({
trainingDetail
,
mode
,
modeOrder
}:
{
trainingDetail
:
GetCollectionTrainingDetailResponseType
;
mode
:
TrainingModeEnum
;
modeOrder
:
TrainingModeEnum
[];
})
=>
{
if
(
isTrainingDetailReady
(
trainingDetail
))
return
TrainingStatus
.
Ready
;
if
(
trainingDetail
.
errorCounts
[
mode
]
>
0
)
return
TrainingStatus
.
Error
;
if
(
trainingDetail
.
trainingCounts
[
mode
]
>
0
)
return
TrainingStatus
.
Running
;
if
(
trainingDetail
.
queuedCounts
[
mode
]
>
0
)
return
TrainingStatus
.
Queued
;
const
modeIndex
=
modeOrder
.
indexOf
(
mode
);
if
(
modeIndex
===
-
1
)
return
TrainingStatus
.
NotStart
;
const
hasLaterProgress
=
modeOrder
.
slice
(
modeIndex
+
1
).
some
((
nextMode
)
=>
{
return
(
trainingDetail
.
queuedCounts
[
nextMode
]
>
0
||
trainingDetail
.
trainingCounts
[
nextMode
]
>
0
||
trainingDetail
.
errorCounts
[
nextMode
]
>
0
);
});
return
hasLaterProgress
?
TrainingStatus
.
Ready
:
TrainingStatus
.
NotStart
;
};
projects/app/src/pages/api/core/dataset/collection/trainingDetail.ts
View file @
2eeea151
...
@@ -14,9 +14,9 @@ import {
...
@@ -14,9 +14,9 @@ import {
}
from
'@fastgpt/global/openapi/core/dataset/collection/api'
;
}
from
'@fastgpt/global/openapi/core/dataset/collection/api'
;
import
{
import
{
BLOCKED_LOCK_TIME
,
BLOCKED_LOCK_TIME
,
activeTrainingMatch
,
finalErrorTrainingMatch
finalErrorTrainingMatch
}
from
'@fastgpt/service/core/dataset/training/query'
;
}
from
'@fastgpt/service/core/dataset/training/query'
;
import
{
subMinutes
}
from
'date-fns'
;
const
defaultCounts
:
Record
<
TrainingModeEnum
,
number
>
=
{
const
defaultCounts
:
Record
<
TrainingModeEnum
,
number
>
=
{
parse
:
0
,
parse
:
0
,
...
@@ -27,6 +27,15 @@ const defaultCounts: Record<TrainingModeEnum, number> = {
...
@@ -27,6 +27,15 @@ const defaultCounts: Record<TrainingModeEnum, number> = {
imageParse
:
0
imageParse
:
0
};
};
const
MODE_LOCK_TIMEOUT_MINUTES
:
Record
<
TrainingModeEnum
,
number
>
=
{
parse
:
10
,
qa
:
10
,
chunk
:
3
,
image
:
10
,
auto
:
10
,
imageParse
:
10
};
async
function
handler
(
req
:
ApiRequestProps
):
Promise
<
GetCollectionTrainingDetailResponseType
>
{
async
function
handler
(
req
:
ApiRequestProps
):
Promise
<
GetCollectionTrainingDetailResponseType
>
{
const
{
collectionId
}
=
parseApiInput
({
const
{
collectionId
}
=
parseApiInput
({
req
,
req
,
...
@@ -47,19 +56,23 @@ async function handler(req: ApiRequestProps): Promise<GetCollectionTrainingDetai
...
@@ -47,19 +56,23 @@ async function handler(req: ApiRequestProps): Promise<GetCollectionTrainingDetai
collectionId
:
new
Types
.
ObjectId
(
collection
.
_id
)
collectionId
:
new
Types
.
ObjectId
(
collection
.
_id
)
};
};
// Computed global queue
const
now
=
new
Date
();
const
minId
=
(
const
activeTrainingExpr
=
Object
.
entries
(
MODE_LOCK_TIMEOUT_MINUTES
).
map
(
await
MongoDatasetTraining
.
findOne
(
match
,
{
sort
:
{
_id
:
1
},
select
:
'_id'
}).
lean
()
([
mode
,
timeoutMinutes
])
=>
({
)?.
_id
;
mode
,
lockTime
:
{
$gt
:
subMinutes
(
now
,
timeoutMinutes
),
$lt
:
BLOCKED_LOCK_TIME
}
})
);
const
[
ququedCountData
,
trainingCountData
,
errorCountData
,
trainedCount
]
=
(
await
Promise
.
all
([
const
[
ququedCountData
,
trainingCountData
,
errorCountData
,
trainedCount
]
=
(
await
Promise
.
all
([
minId
MongoDatasetTraining
.
aggregate
([
?
MongoDatasetTraining
.
aggregate
([
{
{
$match
:
{
$match
:
{
_id
:
{
$lt
:
new
Types
.
ObjectId
(
minId
)
}
,
...
match
,
retryCount
:
{
$gt
:
0
},
retryCount
:
{
$gt
:
0
},
lockTime
:
{
$lt
:
BLOCKED_LOCK_TIME
}
lockTime
:
{
$lt
:
BLOCKED_LOCK_TIME
},
// 只统计当前集合里未被 worker 领取或锁超时后可重试的任务,避免跨知识库队列污染状态展示。
$nor
:
activeTrainingExpr
}
}
},
},
{
{
...
@@ -68,13 +81,13 @@ async function handler(req: ApiRequestProps): Promise<GetCollectionTrainingDetai
...
@@ -68,13 +81,13 @@ async function handler(req: ApiRequestProps): Promise<GetCollectionTrainingDetai
count
:
{
$sum
:
1
}
count
:
{
$sum
:
1
}
}
}
}
}
])
]),
:
Promise
.
resolve
([]),
MongoDatasetTraining
.
aggregate
([
MongoDatasetTraining
.
aggregate
([
{
{
$match
:
{
$match
:
{
...
match
,
...
match
,
...
activeTrainingMatch
retryCount
:
{
$gt
:
0
},
$or
:
activeTrainingExpr
}
}
},
},
{
{
...
...
projects/app/test/api/core/dataset/collection/trainingStatus.test.ts
View file @
2eeea151
...
@@ -94,7 +94,7 @@ describe('collection training status api', () => {
...
@@ -94,7 +94,7 @@ describe('collection training status api', () => {
});
});
});
});
it
(
'should
use active counts for progress and final errors for error tab
'
,
async
()
=>
{
it
(
'should
split current collection queued/running counts and final errors
'
,
async
()
=>
{
const
root
=
await
getRootUser
();
const
root
=
await
getRootUser
();
const
dataset
=
await
MongoDataset
.
create
({
const
dataset
=
await
MongoDataset
.
create
({
name
:
'test'
,
name
:
'test'
,
...
@@ -120,6 +120,7 @@ describe('collection training status api', () => {
...
@@ -120,6 +120,7 @@ describe('collection training status api', () => {
billId
:
'test'
,
billId
:
'test'
,
mode
:
TrainingModeEnum
.
qa
,
mode
:
TrainingModeEnum
.
qa
,
retryCount
:
3
,
retryCount
:
3
,
lockTime
:
new
Date
(),
errorMsg
:
'temporary failed'
errorMsg
:
'temporary failed'
},
},
{
{
...
@@ -128,6 +129,16 @@ describe('collection training status api', () => {
...
@@ -128,6 +129,16 @@ describe('collection training status api', () => {
datasetId
:
dataset
.
_id
,
datasetId
:
dataset
.
_id
,
collectionId
:
collection
.
_id
,
collectionId
:
collection
.
_id
,
billId
:
'test'
,
billId
:
'test'
,
mode
:
TrainingModeEnum
.
parse
,
retryCount
:
3
,
lockTime
:
new
Date
(
'2000'
)
},
{
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
datasetId
:
dataset
.
_id
,
collectionId
:
collection
.
_id
,
billId
:
'test'
,
mode
:
TrainingModeEnum
.
chunk
,
mode
:
TrainingModeEnum
.
chunk
,
retryCount
:
0
,
retryCount
:
0
,
errorMsg
:
'final failed'
errorMsg
:
'final failed'
...
@@ -142,11 +153,84 @@ describe('collection training status api', () => {
...
@@ -142,11 +153,84 @@ describe('collection training status api', () => {
});
});
expect
(
res
.
code
).
toBe
(
200
);
expect
(
res
.
code
).
toBe
(
200
);
expect
(
res
.
data
.
queuedCounts
.
parse
).
toBe
(
1
);
expect
(
res
.
data
.
trainingCounts
.
parse
).
toBe
(
0
);
expect
(
res
.
data
.
queuedCounts
.
qa
).
toBe
(
0
);
expect
(
res
.
data
.
trainingCounts
.
qa
).
toBe
(
1
);
expect
(
res
.
data
.
trainingCounts
.
qa
).
toBe
(
1
);
expect
(
res
.
data
.
errorCounts
.
qa
).
toBe
(
0
);
expect
(
res
.
data
.
errorCounts
.
qa
).
toBe
(
0
);
expect
(
res
.
data
.
errorCounts
.
chunk
).
toBe
(
1
);
expect
(
res
.
data
.
errorCounts
.
chunk
).
toBe
(
1
);
});
});
it
(
'should not include other dataset training records in collection queued counts'
,
async
()
=>
{
const
root
=
await
getRootUser
();
const
[
dataset
,
otherDataset
]
=
await
MongoDataset
.
create
([
{
name
:
'current'
,
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
vectorModel
:
'test'
,
agentModel
:
'test'
},
{
name
:
'other'
,
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
vectorModel
:
'test'
,
agentModel
:
'test'
}
]);
const
[
collection
,
otherCollection
]
=
await
MongoDatasetCollection
.
create
([
{
name
:
'current'
,
type
:
DatasetCollectionTypeEnum
.
file
,
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
datasetId
:
dataset
.
_id
},
{
name
:
'other'
,
type
:
DatasetCollectionTypeEnum
.
file
,
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
datasetId
:
otherDataset
.
_id
}
]);
await
MongoDatasetTraining
.
create
([
...
Array
.
from
({
length
:
6
}).
map
(()
=>
({
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
datasetId
:
otherDataset
.
_id
,
collectionId
:
otherCollection
.
_id
,
billId
:
'test'
,
mode
:
TrainingModeEnum
.
chunk
,
retryCount
:
3
,
lockTime
:
new
Date
(
'2000'
)
})),
{
teamId
:
root
.
teamId
,
tmbId
:
root
.
tmbId
,
datasetId
:
dataset
.
_id
,
collectionId
:
collection
.
_id
,
billId
:
'test'
,
mode
:
TrainingModeEnum
.
parse
,
retryCount
:
3
,
lockTime
:
new
Date
(
'2000'
)
}
]);
const
res
=
await
Call
(
trainingDetailHandler
,
{
auth
:
root
,
query
:
{
collectionId
:
collection
.
_id
}
});
expect
(
res
.
code
).
toBe
(
200
);
expect
(
res
.
data
.
queuedCounts
.
parse
).
toBe
(
1
);
expect
(
res
.
data
.
queuedCounts
.
chunk
).
toBe
(
0
);
});
it
(
'should keep deprecated scrollList compatible with the collection list item schema'
,
async
()
=>
{
it
(
'should keep deprecated scrollList compatible with the collection list item schema'
,
async
()
=>
{
const
root
=
await
getRootUser
();
const
root
=
await
getRootUser
();
const
dataset
=
await
MongoDataset
.
create
({
const
dataset
=
await
MongoDataset
.
create
({
...
...
projects/app/test/pageComponents/dataset/detail/CollectionCard/trainingStatesUtils.test.ts
0 → 100644
View file @
2eeea151
import
{
describe
,
expect
,
it
}
from
'vitest'
;
import
{
DatasetCollectionDataProcessModeEnum
,
TrainingModeEnum
}
from
'@fastgpt/global/core/dataset/constants'
;
import
type
{
GetCollectionTrainingDetailResponseType
}
from
'@fastgpt/global/openapi/core/dataset/collection/api'
;
import
{
getTrainingStepStatus
,
isTrainingStepHighlighted
,
TrainingStatus
}
from
'@/pageComponents/dataset/detail/CollectionCard/trainingStatesUtils'
;
const
createTrainingDetail
=
(
overrides
:
Partial
<
GetCollectionTrainingDetailResponseType
>
=
{}
):
GetCollectionTrainingDetailResponseType
=>
{
const
counts
=
{
parse
:
0
,
qa
:
0
,
chunk
:
0
,
image
:
0
,
auto
:
0
,
imageParse
:
0
};
return
{
trainingType
:
DatasetCollectionDataProcessModeEnum
.
chunk
,
advancedTraining
:
{
customPdfParse
:
false
,
imageIndex
:
false
,
autoIndexes
:
false
},
queuedCounts
:
{
...
counts
},
trainingCounts
:
{
...
counts
},
errorCounts
:
{
...
counts
},
trainedCount
:
0
,
...
overrides
};
};
describe
(
'trainingStatesUtils'
,
()
=>
{
it
(
'should mark parsing step as running while content parsing is active'
,
()
=>
{
const
trainingDetail
=
createTrainingDetail
({
trainingCounts
:
{
parse
:
1
,
qa
:
0
,
chunk
:
0
,
image
:
0
,
auto
:
0
,
imageParse
:
0
}
});
const
modeOrder
=
[
TrainingModeEnum
.
parse
,
TrainingModeEnum
.
chunk
];
expect
(
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
parse
,
modeOrder
})
).
toBe
(
TrainingStatus
.
Running
);
expect
(
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
chunk
,
modeOrder
})
).
toBe
(
TrainingStatus
.
NotStart
);
});
it
(
'should mark parsing step as queued while waiting to be picked by worker'
,
()
=>
{
const
trainingDetail
=
createTrainingDetail
({
queuedCounts
:
{
parse
:
1
,
qa
:
0
,
chunk
:
0
,
image
:
0
,
auto
:
0
,
imageParse
:
0
}
});
const
modeOrder
=
[
TrainingModeEnum
.
parse
,
TrainingModeEnum
.
chunk
];
expect
(
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
parse
,
modeOrder
})
).
toBe
(
TrainingStatus
.
Queued
);
expect
(
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
chunk
,
modeOrder
})
).
toBe
(
TrainingStatus
.
NotStart
);
});
it
(
'should mark earlier steps ready after later steps start'
,
()
=>
{
const
trainingDetail
=
createTrainingDetail
({
trainingCounts
:
{
parse
:
0
,
qa
:
0
,
chunk
:
1
,
image
:
0
,
auto
:
0
,
imageParse
:
0
},
trainedCount
:
1
});
const
modeOrder
=
[
TrainingModeEnum
.
parse
,
TrainingModeEnum
.
chunk
];
expect
(
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
parse
,
modeOrder
})
).
toBe
(
TrainingStatus
.
Ready
);
expect
(
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
chunk
,
modeOrder
})
).
toBe
(
TrainingStatus
.
Running
);
});
it
(
'should keep multiple in-progress stages highlighted at the same time'
,
()
=>
{
const
trainingDetail
=
createTrainingDetail
({
trainingCounts
:
{
parse
:
1
,
qa
:
0
,
chunk
:
2
,
image
:
0
,
auto
:
0
,
imageParse
:
0
}
});
const
modeOrder
=
[
TrainingModeEnum
.
parse
,
TrainingModeEnum
.
chunk
];
const
parseStatus
=
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
parse
,
modeOrder
});
const
chunkStatus
=
getTrainingStepStatus
({
trainingDetail
,
mode
:
TrainingModeEnum
.
chunk
,
modeOrder
});
expect
(
parseStatus
).
toBe
(
TrainingStatus
.
Running
);
expect
(
chunkStatus
).
toBe
(
TrainingStatus
.
Running
);
expect
(
isTrainingStepHighlighted
(
parseStatus
)).
toBe
(
true
);
expect
(
isTrainingStepHighlighted
(
chunkStatus
)).
toBe
(
true
);
});
it
(
'should highlight completed steps and gray out only not-started steps'
,
()
=>
{
expect
(
isTrainingStepHighlighted
(
TrainingStatus
.
Ready
)).
toBe
(
true
);
expect
(
isTrainingStepHighlighted
(
TrainingStatus
.
Queued
)).
toBe
(
true
);
expect
(
isTrainingStepHighlighted
(
TrainingStatus
.
Running
)).
toBe
(
true
);
expect
(
isTrainingStepHighlighted
(
TrainingStatus
.
Error
)).
toBe
(
true
);
expect
(
isTrainingStepHighlighted
(
TrainingStatus
.
NotStart
)).
toBe
(
false
);
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment