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
4420281d
Unverified
Commit
4420281d
authored
Aug 18, 2023
by
zxhlyh
Committed by
GitHub
Aug 18, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Feat/segment add tag (#907)
parent
d9afebe2
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
132 additions
and
10 deletions
+132
-10
index.tsx
web/app/components/base/tag-input/index.tsx
+94
-0
index.tsx
.../components/datasets/documents/detail/completed/index.tsx
+19
-6
new-segment-modal.tsx
...omponents/datasets/documents/detail/new-segment-modal.tsx
+10
-2
global.d.ts
web/global.d.ts
+2
-1
dataset-documents.en.ts
web/i18n/lang/dataset-documents.en.ts
+2
-0
dataset-documents.zh.ts
web/i18n/lang/dataset-documents.zh.ts
+2
-0
datasets.ts
web/models/datasets.ts
+1
-0
package.json
web/package.json
+2
-1
No files found.
web/app/components/base/tag-input/index.tsx
0 → 100644
View file @
4420281d
import
{
useState
}
from
'react'
import
type
{
ChangeEvent
,
FC
,
KeyboardEvent
}
from
'react'
import
{}
from
'use-context-selector'
import
{
useTranslation
}
from
'react-i18next'
import
AutosizeInput
from
'react-18-input-autosize'
import
{
X
}
from
'@/app/components/base/icons/src/vender/line/general'
import
{
useToastContext
}
from
'@/app/components/base/toast'
type
TagInputProps
=
{
items
:
string
[]
onChange
:
(
items
:
string
[])
=>
void
disableRemove
?:
boolean
disableAdd
?:
boolean
}
const
TagInput
:
FC
<
TagInputProps
>
=
({
items
,
onChange
,
disableAdd
,
disableRemove
,
})
=>
{
const
{
t
}
=
useTranslation
()
const
{
notify
}
=
useToastContext
()
const
[
value
,
setValue
]
=
useState
(
''
)
const
[
focused
,
setFocused
]
=
useState
(
false
)
const
handleRemove
=
(
index
:
number
)
=>
{
const
copyItems
=
[...
items
]
copyItems
.
splice
(
index
,
1
)
onChange
(
copyItems
)
}
const
handleKeyDown
=
(
e
:
KeyboardEvent
)
=>
{
if
(
e
.
key
===
'Enter'
)
{
const
valueTrimed
=
value
.
trim
()
if
(
!
valueTrimed
||
(
items
.
find
(
item
=>
item
===
valueTrimed
)))
return
if
(
valueTrimed
.
length
>
20
)
{
notify
({
type
:
'error'
,
message
:
t
(
'datasetDocuments.segment.keywordError'
)
})
return
}
onChange
([...
items
,
valueTrimed
])
setValue
(
''
)
}
}
const
handleBlur
=
()
=>
{
setValue
(
''
)
setFocused
(
false
)
}
return
(
<
div
className=
'flex flex-wrap'
>
{
items
.
map
((
item
,
index
)
=>
(
<
div
key=
{
item
}
className=
'flex items-center mr-1 mt-1 px-2 py-1 text-sm text-gray-700 rounded-lg border border-gray-200'
>
{
item
}
{
!
disableRemove
&&
(
<
X
className=
'ml-0.5 w-3 h-3 text-gray-500 cursor-pointer'
onClick=
{
()
=>
handleRemove
(
index
)
}
/>
)
}
</
div
>
))
}
{
!
disableAdd
&&
(
<
AutosizeInput
inputClassName=
'outline-none appearance-none placeholder:text-gray-300 caret-primary-600 hover:placeholder:text-gray-400'
className=
{
`
mt-1 py-1 rounded-lg border border-transparent text-sm max-w-[300px] overflow-hidden
${focused && 'px-2 border !border-dashed !border-gray-200'}
`
}
onFocus=
{
()
=>
setFocused
(
true
)
}
onBlur=
{
handleBlur
}
value=
{
value
}
onChange=
{
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
setValue
(
e
.
target
.
value
)
}
onKeyDown=
{
handleKeyDown
}
placeholder=
{
t
(
'datasetDocuments.segment.addKeyWord'
)
}
/>
)
}
</
div
>
)
}
export
default
TagInput
web/app/components/datasets/documents/detail/completed/index.tsx
View file @
4420281d
...
...
@@ -26,6 +26,7 @@ import { Edit03, XClose } from '@/app/components/base/icons/src/vender/line/gene
import
AutoHeightTextarea
from
'@/app/components/base/auto-height-textarea/common'
import
Button
from
'@/app/components/base/button'
import
NewSegmentModal
from
'@/app/components/datasets/documents/detail/new-segment-modal'
import
TagInput
from
'@/app/components/base/tag-input'
export
const
SegmentIndexTag
:
FC
<
{
positionId
:
string
|
number
;
className
?:
string
}
>
=
({
positionId
,
className
})
=>
{
const
localPositionId
=
useMemo
(()
=>
{
...
...
@@ -45,7 +46,7 @@ export const SegmentIndexTag: FC<{ positionId: string | number; className?: stri
type
ISegmentDetailProps
=
{
segInfo
?:
Partial
<
SegmentDetailModel
>
&
{
id
:
string
}
onChangeSwitch
?:
(
segId
:
string
,
enabled
:
boolean
)
=>
Promise
<
void
>
onUpdate
:
(
segmentId
:
string
,
q
:
string
,
a
:
string
)
=>
void
onUpdate
:
(
segmentId
:
string
,
q
:
string
,
a
:
string
,
k
:
string
[]
)
=>
void
onCancel
:
()
=>
void
}
/**
...
...
@@ -61,14 +62,16 @@ export const SegmentDetail: FC<ISegmentDetailProps> = memo(({
const
[
isEditing
,
setIsEditing
]
=
useState
(
false
)
const
[
question
,
setQuestion
]
=
useState
(
segInfo
?.
content
||
''
)
const
[
answer
,
setAnswer
]
=
useState
(
segInfo
?.
answer
||
''
)
const
[
keywords
,
setKeywords
]
=
useState
<
string
[]
>
(
segInfo
?.
keywords
||
[])
const
handleCancel
=
()
=>
{
setIsEditing
(
false
)
setQuestion
(
segInfo
?.
content
||
''
)
setAnswer
(
segInfo
?.
answer
||
''
)
setKeywords
(
segInfo
?.
keywords
||
[])
}
const
handleSave
=
()
=>
{
onUpdate
(
segInfo
?.
id
||
''
,
question
,
answer
)
onUpdate
(
segInfo
?.
id
||
''
,
question
,
answer
,
keywords
)
}
const
renderContent
=
()
=>
{
...
...
@@ -148,9 +151,15 @@ export const SegmentDetail: FC<ISegmentDetailProps> = memo(({
<
div
className=
{
s
.
keywordWrapper
}
>
{
!
segInfo
?.
keywords
?.
length
?
'-'
:
segInfo
?.
keywords
?.
map
((
word
:
any
)
=>
{
return
<
div
className=
{
s
.
keyword
}
>
{
word
}
</
div
>
})
}
:
(
<
TagInput
items=
{
keywords
}
onChange=
{
newKeywords
=>
setKeywords
(
newKeywords
)
}
disableAdd=
{
!
isEditing
}
disableRemove=
{
!
isEditing
||
(
keywords
.
length
===
1
)
}
/>
)
}
</
div
>
<
div
className=
{
cn
(
s
.
footer
,
s
.
numberInfo
)
}
>
<
div
className=
'flex items-center'
>
...
...
@@ -272,7 +281,7 @@ const Completed: FC<ICompletedProps> = ({ showNewSegmentModal, onNewSegmentModal
}
}
const
handleUpdateSegment
=
async
(
segmentId
:
string
,
question
:
string
,
answer
:
string
)
=>
{
const
handleUpdateSegment
=
async
(
segmentId
:
string
,
question
:
string
,
answer
:
string
,
keywords
:
string
[]
)
=>
{
const
params
:
SegmentUpdator
=
{
content
:
''
}
if
(
docForm
===
'qa_model'
)
{
if
(
!
question
.
trim
())
...
...
@@ -290,6 +299,9 @@ const Completed: FC<ICompletedProps> = ({ showNewSegmentModal, onNewSegmentModal
params
.
content
=
question
}
if
(
keywords
.
length
)
params
.
keywords
=
keywords
const
res
=
await
updateSegment
({
datasetId
,
documentId
,
segmentId
,
body
:
params
})
notify
({
type
:
'success'
,
message
:
t
(
'common.actionMsg.modifiedSuccessfully'
)
})
onCloseModal
()
...
...
@@ -298,6 +310,7 @@ const Completed: FC<ICompletedProps> = ({ showNewSegmentModal, onNewSegmentModal
if
(
seg
.
id
===
segmentId
)
{
seg
.
answer
=
res
.
data
.
answer
seg
.
content
=
res
.
data
.
content
seg
.
keywords
=
res
.
data
.
keywords
seg
.
word_count
=
res
.
data
.
word_count
seg
.
hit_count
=
res
.
data
.
hit_count
seg
.
index_node_hash
=
res
.
data
.
index_node_hash
...
...
web/app/components/datasets/documents/detail/new-segment-modal.tsx
View file @
4420281d
...
...
@@ -10,6 +10,7 @@ import { Hash02, XClose } from '@/app/components/base/icons/src/vender/line/gene
import
{
ToastContext
}
from
'@/app/components/base/toast'
import
type
{
SegmentUpdator
}
from
'@/models/datasets'
import
{
addSegment
}
from
'@/service/datasets'
import
TagInput
from
'@/app/components/base/tag-input'
type
NewSegmentModalProps
=
{
isShow
:
boolean
...
...
@@ -29,11 +30,13 @@ const NewSegmentModal: FC<NewSegmentModalProps> = memo(({
const
[
question
,
setQuestion
]
=
useState
(
''
)
const
[
answer
,
setAnswer
]
=
useState
(
''
)
const
{
datasetId
,
documentId
}
=
useParams
()
const
[
keywords
,
setKeywords
]
=
useState
<
string
[]
>
([])
const
handleCancel
=
()
=>
{
setQuestion
(
''
)
setAnswer
(
''
)
onCancel
()
setKeywords
([])
}
const
handleSave
=
async
()
=>
{
...
...
@@ -54,6 +57,9 @@ const NewSegmentModal: FC<NewSegmentModalProps> = memo(({
params
.
content
=
question
}
if
(
keywords
?.
length
)
params
.
keywords
=
keywords
await
addSegment
({
datasetId
,
documentId
,
body
:
params
})
notify
({
type
:
'success'
,
message
:
t
(
'common.actionMsg.modifiedSuccessfully'
)
})
handleCancel
()
...
...
@@ -117,8 +123,10 @@ const NewSegmentModal: FC<NewSegmentModalProps> = memo(({
</
span
>
</
div
>
<
div
className=
'mb-4 py-1.5 h-[420px] overflow-auto'
>
{
renderContent
()
}
</
div
>
<
div
className=
'mb-2 text-xs font-medium text-gray-500'
>
{
t
(
'datasetDocuments.segment.keywords'
)
}
</
div
>
<
div
className=
'mb-8'
></
div
>
<
div
className=
'text-xs font-medium text-gray-500'
>
{
t
(
'datasetDocuments.segment.keywords'
)
}
</
div
>
<
div
className=
'mb-8'
>
<
TagInput
items=
{
keywords
}
onChange=
{
newKeywords
=>
setKeywords
(
newKeywords
)
}
/>
</
div
>
<
div
className=
'flex justify-end'
>
<
Button
className=
'mr-2 !h-9 !px-4 !py-2 text-sm font-medium text-gray-700 !rounded-lg'
...
...
web/global.d.ts
View file @
4420281d
declare
module
'lamejs'
;
declare
module
'react-18-input-autosize'
;
\ No newline at end of file
web/i18n/lang/dataset-documents.en.ts
View file @
4420281d
...
...
@@ -308,6 +308,8 @@ const translation = {
segment
:
{
paragraphs
:
'Paragraphs'
,
keywords
:
'Key Words'
,
addKeyWord
:
'Add key word'
,
keywordError
:
'The maximum length of keyword is 20'
,
characters
:
'characters'
,
hitCount
:
'hit count'
,
vectorHash
:
'Vector hash: '
,
...
...
web/i18n/lang/dataset-documents.zh.ts
View file @
4420281d
...
...
@@ -307,6 +307,8 @@ const translation = {
segment
:
{
paragraphs
:
'段落'
,
keywords
:
'关键词'
,
addKeyWord
:
'添加关键词'
,
keywordError
:
'关键词最大长度为 20'
,
characters
:
'字符'
,
hitCount
:
'命中次数'
,
vectorHash
:
'向量哈希:'
,
...
...
web/models/datasets.ts
View file @
4420281d
...
...
@@ -388,4 +388,5 @@ export type RelatedAppResponse = {
export
type
SegmentUpdator
=
{
content
:
string
answer
?:
string
keywords
?:
string
[]
}
web/package.json
View file @
4420281d
...
...
@@ -47,6 +47,7 @@
"next"
:
"13.3.1"
,
"qs"
:
"^6.11.1"
,
"react"
:
"^18.2.0"
,
"react-18-input-autosize"
:
"^3.0.0"
,
"react-dom"
:
"^18.2.0"
,
"react-error-boundary"
:
"^4.0.2"
,
"react-headless-pagination"
:
"^1.1.4"
,
...
...
@@ -80,8 +81,8 @@
"@types/crypto-js"
:
"^4.1.1"
,
"@types/js-cookie"
:
"^3.0.3"
,
"@types/lodash-es"
:
"^4.17.7"
,
"@types/node"
:
"18.15.0"
,
"@types/negotiator"
:
"^0.6.1"
,
"@types/node"
:
"18.15.0"
,
"@types/qs"
:
"^6.9.7"
,
"@types/react"
:
"18.0.28"
,
"@types/react-dom"
:
"18.0.11"
,
...
...
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