Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
c40ee7e6
Unverified
Commit
c40ee7e6
authored
Sep 25, 2023
by
Joel
Committed by
GitHub
Sep 25, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: batch run support retry errors and decrease rate limit times (#1215)
parent
841e967d
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
428 additions
and
127 deletions
+428
-127
index.tsx
web/app/components/app/text-generate/item/index.tsx
+106
-103
refresh-ccw-01.svg
...s/base/icons/assets/vender/line/arrows/refresh-ccw-01.svg
+3
-0
clipboard.svg
...ponents/base/icons/assets/vender/line/files/clipboard.svg
+3
-0
bookmark.svg
...onents/base/icons/assets/vender/line/general/bookmark.svg
+3
-0
stars-02.svg
...onents/base/icons/assets/vender/line/weather/stars-02.svg
+3
-0
RefreshCcw01.json
...nents/base/icons/src/vender/line/arrows/RefreshCcw01.json
+29
-0
RefreshCcw01.tsx
...onents/base/icons/src/vender/line/arrows/RefreshCcw01.tsx
+16
-0
index.ts
...app/components/base/icons/src/vender/line/arrows/index.ts
+1
-0
Clipboard.json
...omponents/base/icons/src/vender/line/files/Clipboard.json
+29
-0
Clipboard.tsx
...components/base/icons/src/vender/line/files/Clipboard.tsx
+16
-0
index.ts
web/app/components/base/icons/src/vender/line/files/index.ts
+1
-0
Bookmark.json
...mponents/base/icons/src/vender/line/general/Bookmark.json
+29
-0
Bookmark.tsx
...omponents/base/icons/src/vender/line/general/Bookmark.tsx
+16
-0
index.ts
...pp/components/base/icons/src/vender/line/general/index.ts
+1
-0
Stars02.json
...omponents/base/icons/src/vender/line/weather/Stars02.json
+29
-0
Stars02.tsx
...components/base/icons/src/vender/line/weather/Stars02.tsx
+16
-0
index.ts
...pp/components/base/icons/src/vender/line/weather/index.ts
+1
-0
index.tsx
web/app/components/share/text-generation/index.tsx
+70
-18
index.tsx
web/app/components/share/text-generation/result/index.tsx
+39
-3
index.tsx
web/app/components/share/text-generation/run-batch/index.tsx
+7
-3
share-app.en.ts
web/i18n/lang/share-app.en.ts
+5
-0
share-app.zh.ts
web/i18n/lang/share-app.zh.ts
+5
-0
No files found.
web/app/components/app/text-generate/item/index.tsx
View file @
c40ee7e6
This diff is collapsed.
Click to expand it.
web/app/components/base/icons/assets/vender/line/arrows/refresh-ccw-01.svg
0 → 100644
View file @
c40ee7e6
<svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M2 10C2 10 4.00498 7.26822 5.63384 5.63824C7.26269 4.00827 9.5136 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.89691 21 4.43511 18.2543 3.35177 14.5M2 10V4M2 10H8"
stroke=
"black"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</svg>
web/app/components/base/icons/assets/vender/line/files/clipboard.svg
0 → 100644
View file @
c40ee7e6
<svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M16 4C16.93 4 17.395 4 17.7765 4.10222C18.8117 4.37962 19.6204 5.18827 19.8978 6.22354C20 6.60504 20 7.07003 20 8V17.2C20 18.8802 20 19.7202 19.673 20.362C19.3854 20.9265 18.9265 21.3854 18.362 21.673C17.7202 22 16.8802 22 15.2 22H8.8C7.11984 22 6.27976 22 5.63803 21.673C5.07354 21.3854 4.6146 20.9265 4.32698 20.362C4 19.7202 4 18.8802 4 17.2V8C4 7.07003 4 6.60504 4.10222 6.22354C4.37962 5.18827 5.18827 4.37962 6.22354 4.10222C6.60504 4 7.07003 4 8 4M9.6 6H14.4C14.9601 6 15.2401 6 15.454 5.89101C15.6422 5.79513 15.7951 5.64215 15.891 5.45399C16 5.24008 16 4.96005 16 4.4V3.6C16 3.03995 16 2.75992 15.891 2.54601C15.7951 2.35785 15.6422 2.20487 15.454 2.10899C15.2401 2 14.9601 2 14.4 2H9.6C9.03995 2 8.75992 2 8.54601 2.10899C8.35785 2.20487 8.20487 2.35785 8.10899 2.54601C8 2.75992 8 3.03995 8 3.6V4.4C8 4.96005 8 5.24008 8.10899 5.45399C8.20487 5.64215 8.35785 5.79513 8.54601 5.89101C8.75992 6 9.03995 6 9.6 6Z"
stroke=
"black"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</svg>
web/app/components/base/icons/assets/vender/line/general/bookmark.svg
0 → 100644
View file @
c40ee7e6
<svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M5 7.8C5 6.11984 5 5.27976 5.32698 4.63803C5.6146 4.07354 6.07354 3.6146 6.63803 3.32698C7.27976 3 8.11984 3 9.8 3H14.2C15.8802 3 16.7202 3 17.362 3.32698C17.9265 3.6146 18.3854 4.07354 18.673 4.63803C19 5.27976 19 6.11984 19 7.8V21L12 17L5 21V7.8Z"
stroke=
"black"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</svg>
web/app/components/base/icons/assets/vender/line/weather/stars-02.svg
0 → 100644
View file @
c40ee7e6
<svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M4.5 22V17M4.5 7V2M2 4.5H7M2 19.5H7M13 3L11.2658 7.50886C10.9838 8.24209 10.8428 8.60871 10.6235 8.91709C10.4292 9.1904 10.1904 9.42919 9.91709 9.62353C9.60871 9.8428 9.24209 9.98381 8.50886 10.2658L4 12L8.50886 13.7342C9.24209 14.0162 9.60871 14.1572 9.91709 14.3765C10.1904 14.5708 10.4292 14.8096 10.6235 15.0829C10.8428 15.3913 10.9838 15.7579 11.2658 16.4911L13 21L14.7342 16.4911C15.0162 15.7579 15.1572 15.3913 15.3765 15.0829C15.5708 14.8096 15.8096 14.5708 16.0829 14.3765C16.3913 14.1572 16.7579 14.0162 17.4911 13.7342L22 12L17.4911 10.2658C16.7579 9.98381 16.3913 9.8428 16.0829 9.62353C15.8096 9.42919 15.5708 9.1904 15.3765 8.91709C15.1572 8.60871 15.0162 8.24209 14.7342 7.50886L13 3Z"
stroke=
"black"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</svg>
web/app/components/base/icons/src/vender/line/arrows/RefreshCcw01.json
0 → 100644
View file @
c40ee7e6
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"24"
,
"height"
:
"24"
,
"viewBox"
:
"0 0 24 24"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"d"
:
"M2 10C2 10 4.00498 7.26822 5.63384 5.63824C7.26269 4.00827 9.5136 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.89691 21 4.43511 18.2543 3.35177 14.5M2 10V4M2 10H8"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"2"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
}
]
},
"name"
:
"RefreshCcw01"
}
\ No newline at end of file
web/app/components/base/icons/src/vender/line/arrows/RefreshCcw01.tsx
0 → 100644
View file @
c40ee7e6
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./RefreshCcw01.json'
import
IconBase
from
'@/app/components/base/icons/IconBase'
import
type
{
IconBaseProps
,
IconData
}
from
'@/app/components/base/icons/IconBase'
const
Icon
=
React
.
forwardRef
<
React
.
MutableRefObject
<
SVGElement
>
,
Omit
<
IconBaseProps
,
'data'
>>
((
props
,
ref
,
)
=>
<
IconBase
{
...
props
}
ref=
{
ref
}
data=
{
data
as
IconData
}
/>)
Icon
.
displayName
=
'RefreshCcw01'
export
default
Icon
web/app/components/base/icons/src/vender/line/arrows/index.ts
View file @
c40ee7e6
...
...
@@ -3,4 +3,5 @@ export { default as ArrowUpRight } from './ArrowUpRight'
export
{
default
as
ChevronDownDouble
}
from
'./ChevronDownDouble'
export
{
default
as
ChevronDown
}
from
'./ChevronDown'
export
{
default
as
ChevronRight
}
from
'./ChevronRight'
export
{
default
as
RefreshCcw01
}
from
'./RefreshCcw01'
export
{
default
as
RefreshCw05
}
from
'./RefreshCw05'
web/app/components/base/icons/src/vender/line/files/Clipboard.json
0 → 100644
View file @
c40ee7e6
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"24"
,
"height"
:
"24"
,
"viewBox"
:
"0 0 24 24"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"d"
:
"M16 4C16.93 4 17.395 4 17.7765 4.10222C18.8117 4.37962 19.6204 5.18827 19.8978 6.22354C20 6.60504 20 7.07003 20 8V17.2C20 18.8802 20 19.7202 19.673 20.362C19.3854 20.9265 18.9265 21.3854 18.362 21.673C17.7202 22 16.8802 22 15.2 22H8.8C7.11984 22 6.27976 22 5.63803 21.673C5.07354 21.3854 4.6146 20.9265 4.32698 20.362C4 19.7202 4 18.8802 4 17.2V8C4 7.07003 4 6.60504 4.10222 6.22354C4.37962 5.18827 5.18827 4.37962 6.22354 4.10222C6.60504 4 7.07003 4 8 4M9.6 6H14.4C14.9601 6 15.2401 6 15.454 5.89101C15.6422 5.79513 15.7951 5.64215 15.891 5.45399C16 5.24008 16 4.96005 16 4.4V3.6C16 3.03995 16 2.75992 15.891 2.54601C15.7951 2.35785 15.6422 2.20487 15.454 2.10899C15.2401 2 14.9601 2 14.4 2H9.6C9.03995 2 8.75992 2 8.54601 2.10899C8.35785 2.20487 8.20487 2.35785 8.10899 2.54601C8 2.75992 8 3.03995 8 3.6V4.4C8 4.96005 8 5.24008 8.10899 5.45399C8.20487 5.64215 8.35785 5.79513 8.54601 5.89101C8.75992 6 9.03995 6 9.6 6Z"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"2"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
}
]
},
"name"
:
"Clipboard"
}
\ No newline at end of file
web/app/components/base/icons/src/vender/line/files/Clipboard.tsx
0 → 100644
View file @
c40ee7e6
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./Clipboard.json'
import
IconBase
from
'@/app/components/base/icons/IconBase'
import
type
{
IconBaseProps
,
IconData
}
from
'@/app/components/base/icons/IconBase'
const
Icon
=
React
.
forwardRef
<
React
.
MutableRefObject
<
SVGElement
>
,
Omit
<
IconBaseProps
,
'data'
>>
((
props
,
ref
,
)
=>
<
IconBase
{
...
props
}
ref=
{
ref
}
data=
{
data
as
IconData
}
/>)
Icon
.
displayName
=
'Clipboard'
export
default
Icon
web/app/components/base/icons/src/vender/line/files/index.ts
View file @
c40ee7e6
export
{
default
as
Clipboard
}
from
'./Clipboard'
export
{
default
as
FilePlus02
}
from
'./FilePlus02'
web/app/components/base/icons/src/vender/line/general/Bookmark.json
0 → 100644
View file @
c40ee7e6
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"24"
,
"height"
:
"24"
,
"viewBox"
:
"0 0 24 24"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"d"
:
"M5 7.8C5 6.11984 5 5.27976 5.32698 4.63803C5.6146 4.07354 6.07354 3.6146 6.63803 3.32698C7.27976 3 8.11984 3 9.8 3H14.2C15.8802 3 16.7202 3 17.362 3.32698C17.9265 3.6146 18.3854 4.07354 18.673 4.63803C19 5.27976 19 6.11984 19 7.8V21L12 17L5 21V7.8Z"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"2"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
}
]
},
"name"
:
"Bookmark"
}
\ No newline at end of file
web/app/components/base/icons/src/vender/line/general/Bookmark.tsx
0 → 100644
View file @
c40ee7e6
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./Bookmark.json'
import
IconBase
from
'@/app/components/base/icons/IconBase'
import
type
{
IconBaseProps
,
IconData
}
from
'@/app/components/base/icons/IconBase'
const
Icon
=
React
.
forwardRef
<
React
.
MutableRefObject
<
SVGElement
>
,
Omit
<
IconBaseProps
,
'data'
>>
((
props
,
ref
,
)
=>
<
IconBase
{
...
props
}
ref=
{
ref
}
data=
{
data
as
IconData
}
/>)
Icon
.
displayName
=
'Bookmark'
export
default
Icon
web/app/components/base/icons/src/vender/line/general/index.ts
View file @
c40ee7e6
export
{
default
as
AtSign
}
from
'./AtSign'
export
{
default
as
Bookmark
}
from
'./Bookmark'
export
{
default
as
Check
}
from
'./Check'
export
{
default
as
DotsHorizontal
}
from
'./DotsHorizontal'
export
{
default
as
Edit03
}
from
'./Edit03'
...
...
web/app/components/base/icons/src/vender/line/weather/Stars02.json
0 → 100644
View file @
c40ee7e6
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"24"
,
"height"
:
"24"
,
"viewBox"
:
"0 0 24 24"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"d"
:
"M4.5 22V17M4.5 7V2M2 4.5H7M2 19.5H7M13 3L11.2658 7.50886C10.9838 8.24209 10.8428 8.60871 10.6235 8.91709C10.4292 9.1904 10.1904 9.42919 9.91709 9.62353C9.60871 9.8428 9.24209 9.98381 8.50886 10.2658L4 12L8.50886 13.7342C9.24209 14.0162 9.60871 14.1572 9.91709 14.3765C10.1904 14.5708 10.4292 14.8096 10.6235 15.0829C10.8428 15.3913 10.9838 15.7579 11.2658 16.4911L13 21L14.7342 16.4911C15.0162 15.7579 15.1572 15.3913 15.3765 15.0829C15.5708 14.8096 15.8096 14.5708 16.0829 14.3765C16.3913 14.1572 16.7579 14.0162 17.4911 13.7342L22 12L17.4911 10.2658C16.7579 9.98381 16.3913 9.8428 16.0829 9.62353C15.8096 9.42919 15.5708 9.1904 15.3765 8.91709C15.1572 8.60871 15.0162 8.24209 14.7342 7.50886L13 3Z"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"2"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
}
]
},
"name"
:
"Stars02"
}
\ No newline at end of file
web/app/components/base/icons/src/vender/line/weather/Stars02.tsx
0 → 100644
View file @
c40ee7e6
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./Stars02.json'
import
IconBase
from
'@/app/components/base/icons/IconBase'
import
type
{
IconBaseProps
,
IconData
}
from
'@/app/components/base/icons/IconBase'
const
Icon
=
React
.
forwardRef
<
React
.
MutableRefObject
<
SVGElement
>
,
Omit
<
IconBaseProps
,
'data'
>>
((
props
,
ref
,
)
=>
<
IconBase
{
...
props
}
ref=
{
ref
}
data=
{
data
as
IconData
}
/>)
Icon
.
displayName
=
'Stars02'
export
default
Icon
web/app/components/base/icons/src/vender/line/weather/index.ts
0 → 100644
View file @
c40ee7e6
export
{
default
as
Stars02
}
from
'./Stars02'
web/app/components/share/text-generation/index.tsx
View file @
c40ee7e6
...
...
@@ -3,11 +3,12 @@ import type { FC } from 'react'
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
{
useBoolean
,
useClickAway
,
useGetState
}
from
'ahooks'
import
{
useBoolean
,
useClickAway
}
from
'ahooks'
import
{
XMarkIcon
}
from
'@heroicons/react/24/outline'
import
TabHeader
from
'../../base/tab-header'
import
Button
from
'../../base/button'
import
{
checkOrSetAccessToken
}
from
'../utils'
import
{
AlertCircle
}
from
'../../base/icons/src/vender/solid/alertsAndFeedback'
import
s
from
'./style.module.css'
import
RunBatch
from
'./run-batch'
import
ResDownload
from
'./run-batch/res-download'
...
...
@@ -25,12 +26,12 @@ import SavedItems from '@/app/components/app/text-generate/saved-items'
import
type
{
InstalledApp
}
from
'@/models/explore'
import
{
DEFAULT_VALUE_MAX_LEN
,
appDefaultIconBackground
}
from
'@/config'
import
Toast
from
'@/app/components/base/toast'
const
PARALLEL_LIMIT
=
5
const
GROUP_SIZE
=
5
// to avoid RPM(Request per minute) limit. The group task finished then the next group.
enum
TaskStatus
{
pending
=
'pending'
,
running
=
'running'
,
completed
=
'completed'
,
failed
=
'failed'
,
}
type
TaskParam
=
{
...
...
@@ -99,15 +100,41 @@ const TextGeneration: FC<IMainProps> = ({
showResSidebar
()
}
const
[
allTaskList
,
setAllTaskList
,
getLatestTaskList
]
=
useGetState
<
Task
[]
>
([])
const
[
controlRetry
,
setControlRetry
]
=
useState
(
0
)
const
handleRetryAllFailedTask
=
()
=>
{
setControlRetry
(
Date
.
now
())
}
const
[
allTaskList
,
doSetAllTaskList
]
=
useState
<
Task
[]
>
([])
const
allTaskListRef
=
useRef
<
Task
[]
>
([])
const
getLatestTaskList
=
()
=>
allTaskListRef
.
current
const
setAllTaskList
=
(
taskList
:
Task
[])
=>
{
doSetAllTaskList
(
taskList
)
allTaskListRef
.
current
=
taskList
}
const
pendingTaskList
=
allTaskList
.
filter
(
task
=>
task
.
status
===
TaskStatus
.
pending
)
const
noPendingTask
=
pendingTaskList
.
length
===
0
const
showTaskList
=
allTaskList
.
filter
(
task
=>
task
.
status
!==
TaskStatus
.
pending
)
const
[
currGroupNum
,
doSetCurrGroupNum
]
=
useState
(
0
)
const
currGroupNumRef
=
useRef
(
0
)
const
setCurrGroupNum
=
(
num
:
number
)
=>
{
doSetCurrGroupNum
(
num
)
currGroupNumRef
.
current
=
num
}
const
getCurrGroupNum
=
()
=>
{
return
currGroupNumRef
.
current
}
const
allSuccessTaskList
=
allTaskList
.
filter
(
task
=>
task
.
status
===
TaskStatus
.
completed
)
const
allFailedTaskList
=
allTaskList
.
filter
(
task
=>
task
.
status
===
TaskStatus
.
failed
)
const
allTaskFinished
=
allTaskList
.
every
(
task
=>
task
.
status
===
TaskStatus
.
completed
)
const
[
batchCompletionRes
,
setBatchCompletionRes
,
getBatchCompletionRes
]
=
useGetState
<
Record
<
string
,
string
>>
({})
const
allTaskRuned
=
allTaskList
.
every
(
task
=>
[
TaskStatus
.
completed
,
TaskStatus
.
failed
].
includes
(
task
.
status
))
const
[
batchCompletionRes
,
doSetBatchCompletionRes
]
=
useState
<
Record
<
string
,
string
>>
({})
const
batchCompletionResRef
=
useRef
<
Record
<
string
,
string
>>
({})
const
setBatchCompletionRes
=
(
res
:
Record
<
string
,
string
>
)
=>
{
doSetBatchCompletionRes
(
res
)
batchCompletionResRef
.
current
=
res
}
const
getBatchCompletionRes
=
()
=>
batchCompletionResRef
.
current
const
exportRes
=
allTaskList
.
map
((
task
)
=>
{
if
(
allTaskList
.
length
>
0
&&
!
allTaskFinished
)
return
{}
const
batchCompletionResLatest
=
getBatchCompletionRes
()
const
res
:
Record
<
string
,
string
>
=
{}
const
{
inputs
}
=
task
.
params
...
...
@@ -123,7 +150,6 @@ const TextGeneration: FC<IMainProps> = ({
return
false
}
const
headerData
=
data
[
0
]
const
varLen
=
promptConfig
?.
prompt_variables
.
length
||
0
let
isMapVarName
=
true
promptConfig
?.
prompt_variables
.
forEach
((
item
,
index
)
=>
{
if
(
!
isMapVarName
)
...
...
@@ -234,7 +260,7 @@ const TextGeneration: FC<IMainProps> = ({
}
return
{
id
:
i
+
1
,
status
:
i
<
PARALLEL_LIMIT
?
TaskStatus
.
running
:
TaskStatus
.
pending
,
status
:
i
<
GROUP_SIZE
?
TaskStatus
.
running
:
TaskStatus
.
pending
,
params
:
{
inputs
,
},
...
...
@@ -248,20 +274,28 @@ const TextGeneration: FC<IMainProps> = ({
// eslint-disable-next-line @typescript-eslint/no-use-before-define
showResSidebar
()
}
const
handleCompleted
=
(
completionRes
:
string
,
taskId
?:
number
)
=>
{
const
handleCompleted
=
(
completionRes
:
string
,
taskId
?:
number
,
isSuccess
?:
boolean
)
=>
{
const
allTasklistLatest
=
getLatestTaskList
()
const
batchCompletionResLatest
=
getBatchCompletionRes
()
const
pendingTaskList
=
allTasklistLatest
.
filter
(
task
=>
task
.
status
===
TaskStatus
.
pending
)
const
nextPendingTaskId
=
pendingTaskList
[
0
]?.
id
// console.log(`start: ${allTasklistLatest.map(item => item.status).join(',')}`)
const
hadRunedTaskNum
=
1
+
allTasklistLatest
.
filter
(
task
=>
[
TaskStatus
.
completed
,
TaskStatus
.
failed
].
includes
(
task
.
status
)).
length
const
needToAddNextGroupTask
=
(
getCurrGroupNum
()
!==
hadRunedTaskNum
)
&&
pendingTaskList
.
length
>
0
&&
(
hadRunedTaskNum
%
GROUP_SIZE
===
0
||
(
allTasklistLatest
.
length
-
hadRunedTaskNum
<
GROUP_SIZE
))
// avoid add many task at the same time
if
(
needToAddNextGroupTask
)
setCurrGroupNum
(
hadRunedTaskNum
)
// console.group()
// console.log(`[#${taskId}]: ${isSuccess ? 'success' : 'fail'}.currGroupNum: ${getCurrGroupNum()}.hadRunedTaskNum: ${hadRunedTaskNum}, needToAddNextGroupTask: ${needToAddNextGroupTask}`)
// console.log([...allTasklistLatest.filter(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status)).map(item => item.id), taskId].sort((a: any, b: any) => a - b).join(','))
// console.groupEnd()
const
nextPendingTaskIds
=
needToAddNextGroupTask
?
pendingTaskList
.
slice
(
0
,
GROUP_SIZE
).
map
(
item
=>
item
.
id
)
:
[]
const
newAllTaskList
=
allTasklistLatest
.
map
((
item
)
=>
{
if
(
item
.
id
===
taskId
)
{
return
{
...
item
,
status
:
TaskStatus
.
complet
ed
,
status
:
isSuccess
?
TaskStatus
.
completed
:
TaskStatus
.
fail
ed
,
}
}
if
(
item
.
id
===
nextPendingTaskId
)
{
if
(
needToAddNextGroupTask
&&
nextPendingTaskIds
.
includes
(
item
.
id
)
)
{
return
{
...
item
,
status
:
TaskStatus
.
running
,
...
...
@@ -269,7 +303,6 @@ const TextGeneration: FC<IMainProps> = ({
}
return
item
})
// console.log(`end: ${newAllTaskList.map(item => item.status).join(',')}`)
setAllTaskList
(
newAllTaskList
)
if
(
taskId
)
{
setBatchCompletionRes
({
...
...
@@ -333,10 +366,12 @@ const TextGeneration: FC<IMainProps> = ({
isMobile=
{
isMobile
}
isInstalledApp=
{
!!
isInstalledApp
}
installedAppInfo=
{
installedAppInfo
}
isError=
{
task
?.
status
===
TaskStatus
.
failed
}
promptConfig=
{
promptConfig
}
moreLikeThisEnabled=
{
!!
moreLikeThisConfig
?.
enabled
}
inputs=
{
isCallBatchAPI
?
(
task
as
Task
).
params
.
inputs
:
inputs
}
controlSend=
{
controlSend
}
controlRetry=
{
task
?.
status
===
TaskStatus
.
failed
?
controlRetry
:
0
}
controlStopResponding=
{
controlStopResponding
}
onShowRes=
{
showResSidebar
}
handleSaveMessage=
{
handleSaveMessage
}
...
...
@@ -365,7 +400,19 @@ const TextGeneration: FC<IMainProps> = ({
<
div
className=
'text-lg text-gray-800 font-semibold'
>
{
t
(
'share.generation.title'
)
}
</
div
>
</
div
>
<
div
className=
'flex items-center space-x-2'
>
{
allTaskList
.
length
>
0
&&
allTaskFinished
&&
(
{
allFailedTaskList
.
length
>
0
&&
(
<
div
className=
'flex items-center'
>
<
AlertCircle
className=
'w-4 h-4 text-[#D92D20]'
/>
<
div
className=
'ml-1 text-[#D92D20]'
>
{
t
(
'share.generation.batchFailed.info'
,
{
num
:
allFailedTaskList
.
length
})
}
</
div
>
<
Button
type=
'primary'
className=
'ml-2 !h-8 !px-3'
onClick=
{
handleRetryAllFailedTask
}
>
{
t
(
'share.generation.batchFailed.retry'
)
}
</
Button
>
<
div
className=
'mx-3 w-[1px] h-3.5 bg-gray-200'
></
div
>
</
div
>
)
}
{
allSuccessTaskList
.
length
>
0
&&
(
<
ResDownload
isMobile=
{
isMobile
}
values=
{
exportRes
}
...
...
@@ -394,8 +441,12 @@ const TextGeneration: FC<IMainProps> = ({
</
div
>
)
if
(
!
appId
||
!
siteInfo
||
!
promptConfig
)
return
<
Loading
type=
'app'
/>
if
(
!
appId
||
!
siteInfo
||
!
promptConfig
)
{
return
(
<
div
className=
'flex items-center h-screen'
>
<
Loading
type=
'app'
/>
</
div
>)
}
return
(
<>
...
...
@@ -466,6 +517,7 @@ const TextGeneration: FC<IMainProps> = ({
<
RunBatch
vars=
{
promptConfig
.
prompt_variables
}
onSend=
{
handleRunBatch
}
isAllFinished=
{
allTaskRuned
}
/>
</
div
>
...
...
web/app/components/share/text-generation/result/index.tsx
View file @
c40ee7e6
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
useBoolean
,
useGetState
}
from
'ahooks'
import
React
,
{
useEffect
,
use
Ref
,
use
State
}
from
'react'
import
{
useBoolean
}
from
'ahooks'
import
{
t
}
from
'i18next'
import
cn
from
'classnames'
import
TextGenerationRes
from
'@/app/components/app/text-generate/item'
...
...
@@ -18,10 +18,12 @@ export type IResultProps = {
isMobile
:
boolean
isInstalledApp
:
boolean
installedAppInfo
?:
InstalledApp
isError
:
boolean
promptConfig
:
PromptConfig
|
null
moreLikeThisEnabled
:
boolean
inputs
:
Record
<
string
,
any
>
controlSend
?:
number
controlRetry
?:
number
controlStopResponding
?:
number
onShowRes
:
()
=>
void
handleSaveMessage
:
(
messageId
:
string
)
=>
void
...
...
@@ -35,10 +37,12 @@ const Result: FC<IResultProps> = ({
isMobile
,
isInstalledApp
,
installedAppInfo
,
isError
,
promptConfig
,
moreLikeThisEnabled
,
inputs
,
controlSend
,
controlRetry
,
controlStopResponding
,
onShowRes
,
handleSaveMessage
,
...
...
@@ -51,7 +55,13 @@ const Result: FC<IResultProps> = ({
setResponsingFalse
()
},
[
controlStopResponding
])
const
[
completionRes
,
setCompletionRes
,
getCompletionRes
]
=
useGetState
(
''
)
const
[
completionRes
,
doSetCompletionRes
]
=
useState
(
''
)
const
completionResRef
=
useRef
(
''
)
const
setCompletionRes
=
(
res
:
string
)
=>
{
completionResRef
.
current
=
res
doSetCompletionRes
(
res
)
}
const
getCompletionRes
=
()
=>
completionResRef
.
current
const
{
notify
}
=
Toast
const
isNoData
=
!
completionRes
...
...
@@ -124,6 +134,17 @@ const Result: FC<IResultProps> = ({
onShowRes
()
setResponsingTrue
()
const
startTime
=
Date
.
now
()
let
isTimeout
=
false
const
runId
=
setInterval
(()
=>
{
if
(
Date
.
now
()
-
startTime
>
1000
*
60
)
{
// 1min timeout
clearInterval
(
runId
)
setResponsingFalse
()
onCompleted
(
getCompletionRes
(),
taskId
,
false
)
isTimeout
=
true
console
.
log
(
`[#
${
taskId
}
]: timeout`
)
}
},
1000
)
sendCompletionMessage
(
data
,
{
onData
:
(
data
:
string
,
_isFirstMessage
:
boolean
,
{
messageId
})
=>
{
tempMessageId
=
messageId
...
...
@@ -131,13 +152,21 @@ const Result: FC<IResultProps> = ({
setCompletionRes
(
res
.
join
(
''
))
},
onCompleted
:
()
=>
{
if
(
isTimeout
)
return
setResponsingFalse
()
setMessageId
(
tempMessageId
)
onCompleted
(
getCompletionRes
(),
taskId
,
true
)
clearInterval
(
runId
)
},
onError
()
{
if
(
isTimeout
)
return
setResponsingFalse
()
onCompleted
(
getCompletionRes
(),
taskId
,
false
)
clearInterval
(
runId
)
},
},
isInstalledApp
,
installedAppInfo
?.
id
)
}
...
...
@@ -150,9 +179,16 @@ const Result: FC<IResultProps> = ({
}
},
[
controlSend
])
useEffect
(()
=>
{
if
(
controlRetry
)
handleSend
()
},
[
controlRetry
])
const
renderTextGenerationRes
=
()
=>
(
<
TextGenerationRes
className=
'mt-3'
isError=
{
isError
}
onRetry=
{
handleSend
}
content=
{
completionRes
}
messageId=
{
messageId
}
isInWebApp
...
...
web/app/components/share/text-generation/run-batch/index.tsx
View file @
c40ee7e6
...
...
@@ -5,18 +5,21 @@ import {
PlayIcon
,
}
from
'@heroicons/react/24/solid'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
CSVReader
from
'./csv-reader'
import
CSVDownload
from
'./csv-download'
import
Button
from
'@/app/components/base/button'
import
{
Loading02
}
from
'@/app/components/base/icons/src/vender/line/general'
export
type
IRunBatchProps
=
{
vars
:
{
name
:
string
}[]
onSend
:
(
data
:
string
[][])
=>
void
isAllFinished
:
boolean
}
const
RunBatch
:
FC
<
IRunBatchProps
>
=
({
vars
,
onSend
,
isAllFinished
,
})
=>
{
const
{
t
}
=
useTranslation
()
...
...
@@ -31,6 +34,7 @@ const RunBatch: FC<IRunBatchProps> = ({
const
handleSend
=
()
=>
{
onSend
(
csvData
)
}
const
Icon
=
isAllFinished
?
PlayIcon
:
Loading02
return
(
<
div
className=
'pt-4'
>
<
CSVReader
onParsed=
{
handleParsed
}
/>
...
...
@@ -41,9 +45,9 @@ const RunBatch: FC<IRunBatchProps> = ({
type=
"primary"
className=
'mt-4 !h-8 !pl-3 !pr-4'
onClick=
{
handleSend
}
disabled=
{
!
isParsed
}
disabled=
{
!
isParsed
||
!
isAllFinished
}
>
<
PlayIcon
className=
"shrink-0 w-4 h-4 mr-1"
aria
-
hidden=
"true"
/>
<
Icon
className=
{
cn
(
!
isAllFinished
&&
'animate-spin'
,
'shrink-0 w-4 h-4 mr-1'
)
}
aria
-
hidden=
"true"
/>
<
span
className=
'uppercase text-[13px]'
>
{
t
(
'share.generation.run'
)
}
</
span
>
</
Button
>
</
div
>
...
...
web/i18n/lang/share-app.en.ts
View file @
c40ee7e6
...
...
@@ -54,6 +54,11 @@ const translation = {
csvStructureTitle
:
'The CSV file must conform to the following structure:'
,
downloadTemplate
:
'Download the template here'
,
field
:
'Field'
,
batchFailed
:
{
info
:
'{{num}} failed executions'
,
retry
:
'Retry'
,
outputPlaceholder
:
'No output content'
,
},
errorMsg
:
{
empty
:
'Please input content in the uploaded file.'
,
fileStructNotMatch
:
'The uploaded CSV file not match the struct.'
,
...
...
web/i18n/lang/share-app.zh.ts
View file @
c40ee7e6
...
...
@@ -51,6 +51,11 @@ const translation = {
csvStructureTitle
:
'CSV 文件必须符合以下结构:'
,
downloadTemplate
:
'下载模板'
,
field
:
''
,
batchFailed
:
{
info
:
'{{num}} 次运行失败'
,
retry
:
'重试'
,
outputPlaceholder
:
'无输出内容'
,
},
errorMsg
:
{
empty
:
'上传文件的内容不能为空'
,
fileStructNotMatch
:
'上传文件的内容与结构不匹配'
,
...
...
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