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
0a0960c1
Commit
0a0960c1
authored
Jul 25, 2023
by
jyong
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/feat/milvus-support' into feat/milvus-support
parents
148aa84f
c12eb8d6
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
307 additions
and
23 deletions
+307
-23
common.tsx
web/app/components/base/auto-height-textarea/common.tsx
+52
-0
message-chat-square.svg
...s/base/icons/assets/public/common/message-chat-square.svg
+4
-0
MessageChatSquare.json
...nents/base/icons/src/public/common/MessageChatSquare.json
+37
-0
MessageChatSquare.tsx
...onents/base/icons/src/public/common/MessageChatSquare.tsx
+14
-0
index.ts
web/app/components/base/icons/src/public/common/index.ts
+1
-0
index.ts
...pp/components/base/icons/src/vender/line/general/index.ts
+1
-1
index.module.css
web/app/components/datasets/create/step-two/index.module.css
+1
-1
index.tsx
web/app/components/datasets/create/step-two/index.tsx
+43
-0
SegmentCard.tsx
...nents/datasets/documents/detail/completed/SegmentCard.tsx
+2
-2
index.tsx
.../components/datasets/documents/detail/completed/index.tsx
+101
-12
style.module.css
...ents/datasets/documents/detail/completed/style.module.css
+3
-0
index.tsx
.../components/datasets/documents/detail/embedding/index.tsx
+3
-1
index.tsx
web/app/components/datasets/documents/detail/index.tsx
+3
-3
hit-detail.tsx
web/app/components/datasets/hit-testing/hit-detail.tsx
+2
-2
dataset-creation.en.ts
web/i18n/lang/dataset-creation.en.ts
+2
-0
dataset-creation.zh.ts
web/i18n/lang/dataset-creation.zh.ts
+2
-0
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
+8
-0
datasets.ts
web/service/datasets.ts
+24
-1
No files found.
web/app/components/base/auto-height-textarea/common.tsx
0 → 100644
View file @
0a0960c1
import
{
forwardRef
,
useEffect
,
useRef
}
from
'react'
import
cn
from
'classnames'
type
AutoHeightTextareaProps
=
&
React
.
DetailedHTMLProps
<
React
.
TextareaHTMLAttributes
<
HTMLTextAreaElement
>
,
HTMLTextAreaElement
>
&
{
outerClassName
?:
string
}
const
AutoHeightTextarea
=
forwardRef
<
HTMLTextAreaElement
,
AutoHeightTextareaProps
>
(
(
{
outerClassName
,
value
,
className
,
placeholder
,
autoFocus
,
disabled
,
...
rest
},
outRef
,
)
=>
{
const
innerRef
=
useRef
<
HTMLTextAreaElement
>
(
null
)
const
ref
=
outRef
||
innerRef
useEffect
(()
=>
{
if
(
autoFocus
&&
!
disabled
&&
value
)
{
if
(
typeof
ref
!==
'function'
)
{
ref
.
current
?.
setSelectionRange
(
`
${
value
}
`
.
length
,
`
${
value
}
`
.
length
)
ref
.
current
?.
focus
()
}
}
},
[
autoFocus
,
disabled
,
ref
,
value
])
return
(
<
div
className=
{
outerClassName
}
>
<
div
className=
'relative'
>
<
div
className=
{
cn
(
className
,
'invisible whitespace-pre-wrap break-all'
)
}
>
{
!
value
?
placeholder
:
`${value}`
.
replace
(
/
\n
$/
,
'
\
n '
)
}
</
div
>
<
textarea
ref=
{
ref
}
placeholder=
{
placeholder
}
className=
{
cn
(
className
,
'disabled:bg-transparent absolute inset-0 outline-none border-none appearance-none resize-none'
)
}
value=
{
value
}
disabled=
{
disabled
}
{
...
rest
}
/>
</
div
>
</
div
>
)
},
)
export
default
AutoHeightTextarea
web/app/components/base/icons/assets/public/common/message-chat-square.svg
0 → 100644
View file @
0a0960c1
<svg
width=
"16"
height=
"16"
viewBox=
"0 0 16 16"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
fill-rule=
"evenodd"
clip-rule=
"evenodd"
d=
"M8.77438 6.6665H12.5591C12.9105 6.66649 13.2137 6.66648 13.4634 6.68688C13.727 6.70842 13.9891 6.75596 14.2414 6.88449C14.6177 7.07624 14.9237 7.3822 15.1154 7.75852C15.244 8.01078 15.2915 8.27292 15.313 8.53649C15.3334 8.7862 15.3334 9.08938 15.3334 9.44082V11.2974C15.3334 11.5898 15.3334 11.8421 15.3192 12.0509C15.3042 12.2708 15.2712 12.4908 15.1812 12.7081C14.9782 13.1981 14.5888 13.5875 14.0988 13.7905C13.8815 13.8805 13.6616 13.9135 13.4417 13.9285C13.4068 13.9308 13.3707 13.9328 13.3334 13.9345V14.6665C13.3334 14.9147 13.1955 15.1424 12.9756 15.2573C12.7556 15.3723 12.49 15.3556 12.2862 15.2139L10.8353 14.2051C10.6118 14.0498 10.5666 14.0214 10.5238 14.0021C10.4746 13.9798 10.4228 13.9635 10.3696 13.9537C10.3235 13.9452 10.2702 13.9427 9.99803 13.9427H8.7744C8.42296 13.9427 8.11978 13.9427 7.87006 13.9223C7.6065 13.9008 7.34435 13.8532 7.0921 13.7247C6.71578 13.533 6.40981 13.227 6.21807 12.8507C6.08954 12.5984 6.04199 12.3363 6.02046 12.0727C6.00006 11.823 6.00007 11.5198 6.00008 11.1684V9.44081C6.00007 9.08938 6.00006 8.7862 6.02046 8.53649C6.04199 8.27292 6.08954 8.01078 6.21807 7.75852C6.40981 7.3822 6.71578 7.07624 7.0921 6.88449C7.34435 6.75596 7.6065 6.70842 7.87006 6.68688C8.11978 6.66648 8.42295 6.66649 8.77438 6.6665Z"
fill=
"#444CE7"
/>
<path
d=
"M9.4943 0.666504H4.5059C3.96926 0.666496 3.52635 0.666489 3.16555 0.695967C2.79082 0.726584 2.44635 0.792293 2.12279 0.957154C1.62103 1.21282 1.21308 1.62076 0.957417 2.12253C0.792557 2.44609 0.726847 2.79056 0.69623 3.16529C0.666752 3.52608 0.666759 3.96899 0.666768 4.50564L0.666758 7.6804C0.666669 7.97482 0.666603 8.19298 0.694924 8.38632C0.86568 9.55207 1.78121 10.4676 2.94695 10.6383C2.99461 10.6453 3.02432 10.6632 3.03714 10.6739L3.03714 11.7257C3.03711 11.9075 3.03708 12.0858 3.04976 12.2291C3.06103 12.3565 3.09053 12.6202 3.27795 12.8388C3.48686 13.0825 3.80005 13.2111 4.11993 13.1845C4.40689 13.1607 4.61323 12.9938 4.71072 12.9111C4.73849 12.8875 4.76726 12.8618 4.7968 12.8344C4.73509 12.594 4.70707 12.3709 4.69157 12.1813C4.66659 11.8756 4.66668 11.5224 4.66676 11.1966V9.41261C4.66668 9.08685 4.66659 8.73364 4.69157 8.42793C4.71984 8.08191 4.78981 7.62476 5.03008 7.15322C5.34965 6.52601 5.85959 6.01608 6.4868 5.6965C6.95834 5.45624 7.41549 5.38627 7.7615 5.358C8.06722 5.33302 8.42041 5.3331 8.74617 5.33318H12.5873C12.8311 5.33312 13.0903 5.33306 13.3334 5.3435V4.50562C13.3334 3.96898 13.3334 3.52608 13.304 3.16529C13.2734 2.79056 13.2076 2.44609 13.0428 2.12253C12.7871 1.62076 12.3792 1.21282 11.8774 0.957154C11.5539 0.792293 11.2094 0.726584 10.8347 0.695967C10.4739 0.666489 10.0309 0.666496 9.4943 0.666504Z"
fill=
"#444CE7"
/>
</svg>
web/app/components/base/icons/src/public/common/MessageChatSquare.json
0 → 100644
View file @
0a0960c1
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"16"
,
"height"
:
"16"
,
"viewBox"
:
"0 0 16 16"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"fill-rule"
:
"evenodd"
,
"clip-rule"
:
"evenodd"
,
"d"
:
"M8.77438 6.6665H12.5591C12.9105 6.66649 13.2137 6.66648 13.4634 6.68688C13.727 6.70842 13.9891 6.75596 14.2414 6.88449C14.6177 7.07624 14.9237 7.3822 15.1154 7.75852C15.244 8.01078 15.2915 8.27292 15.313 8.53649C15.3334 8.7862 15.3334 9.08938 15.3334 9.44082V11.2974C15.3334 11.5898 15.3334 11.8421 15.3192 12.0509C15.3042 12.2708 15.2712 12.4908 15.1812 12.7081C14.9782 13.1981 14.5888 13.5875 14.0988 13.7905C13.8815 13.8805 13.6616 13.9135 13.4417 13.9285C13.4068 13.9308 13.3707 13.9328 13.3334 13.9345V14.6665C13.3334 14.9147 13.1955 15.1424 12.9756 15.2573C12.7556 15.3723 12.49 15.3556 12.2862 15.2139L10.8353 14.2051C10.6118 14.0498 10.5666 14.0214 10.5238 14.0021C10.4746 13.9798 10.4228 13.9635 10.3696 13.9537C10.3235 13.9452 10.2702 13.9427 9.99803 13.9427H8.7744C8.42296 13.9427 8.11978 13.9427 7.87006 13.9223C7.6065 13.9008 7.34435 13.8532 7.0921 13.7247C6.71578 13.533 6.40981 13.227 6.21807 12.8507C6.08954 12.5984 6.04199 12.3363 6.02046 12.0727C6.00006 11.823 6.00007 11.5198 6.00008 11.1684V9.44081C6.00007 9.08938 6.00006 8.7862 6.02046 8.53649C6.04199 8.27292 6.08954 8.01078 6.21807 7.75852C6.40981 7.3822 6.71578 7.07624 7.0921 6.88449C7.34435 6.75596 7.6065 6.70842 7.87006 6.68688C8.11978 6.66648 8.42295 6.66649 8.77438 6.6665Z"
,
"fill"
:
"#444CE7"
},
"children"
:
[]
},
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"d"
:
"M9.4943 0.666504H4.5059C3.96926 0.666496 3.52635 0.666489 3.16555 0.695967C2.79082 0.726584 2.44635 0.792293 2.12279 0.957154C1.62103 1.21282 1.21308 1.62076 0.957417 2.12253C0.792557 2.44609 0.726847 2.79056 0.69623 3.16529C0.666752 3.52608 0.666759 3.96899 0.666768 4.50564L0.666758 7.6804C0.666669 7.97482 0.666603 8.19298 0.694924 8.38632C0.86568 9.55207 1.78121 10.4676 2.94695 10.6383C2.99461 10.6453 3.02432 10.6632 3.03714 10.6739L3.03714 11.7257C3.03711 11.9075 3.03708 12.0858 3.04976 12.2291C3.06103 12.3565 3.09053 12.6202 3.27795 12.8388C3.48686 13.0825 3.80005 13.2111 4.11993 13.1845C4.40689 13.1607 4.61323 12.9938 4.71072 12.9111C4.73849 12.8875 4.76726 12.8618 4.7968 12.8344C4.73509 12.594 4.70707 12.3709 4.69157 12.1813C4.66659 11.8756 4.66668 11.5224 4.66676 11.1966V9.41261C4.66668 9.08685 4.66659 8.73364 4.69157 8.42793C4.71984 8.08191 4.78981 7.62476 5.03008 7.15322C5.34965 6.52601 5.85959 6.01608 6.4868 5.6965C6.95834 5.45624 7.41549 5.38627 7.7615 5.358C8.06722 5.33302 8.42041 5.3331 8.74617 5.33318H12.5873C12.8311 5.33312 13.0903 5.33306 13.3334 5.3435V4.50562C13.3334 3.96898 13.3334 3.52608 13.304 3.16529C13.2734 2.79056 13.2076 2.44609 13.0428 2.12253C12.7871 1.62076 12.3792 1.21282 11.8774 0.957154C11.5539 0.792293 11.2094 0.726584 10.8347 0.695967C10.4739 0.666489 10.0309 0.666496 9.4943 0.666504Z"
,
"fill"
:
"#444CE7"
},
"children"
:
[]
}
]
},
"name"
:
"MessageChatSquare"
}
\ No newline at end of file
web/app/components/base/icons/src/public/common/MessageChatSquare.tsx
0 → 100644
View file @
0a0960c1
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./MessageChatSquare.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
}
/>)
export
default
Icon
web/app/components/base/icons/src/public/common/index.ts
View file @
0a0960c1
export
{
default
as
Dify
}
from
'./Dify'
export
{
default
as
Github
}
from
'./Github'
export
{
default
as
MessageChatSquare
}
from
'./MessageChatSquare'
web/app/components/base/icons/src/vender/line/general/index.ts
View file @
0a0960c1
export
{
default
as
Edit03
}
from
'./Edit03'
export
{
default
as
Check
}
from
'./Check'
export
{
default
as
Edit03
}
from
'./Edit03'
export
{
default
as
Loading02
}
from
'./Loading02'
export
{
default
as
LogOut01
}
from
'./LogOut01'
export
{
default
as
Trash03
}
from
'./Trash03'
...
...
web/app/components/datasets/create/step-two/index.module.css
View file @
0a0960c1
...
...
@@ -291,7 +291,7 @@
}
.source
{
@apply
flex
justify-between
items-center
mt-8
px-6
py-4
rounded-xl
bg-gray-50;
@apply
flex
justify-between
items-center
mt-8
px-6
py-4
rounded-xl
bg-gray-50
border
border-gray-100
;
}
.source
.divider
{
...
...
web/app/components/datasets/create/step-two/index.tsx
View file @
0a0960c1
...
...
@@ -24,6 +24,8 @@ import { formatNumber } from '@/utils/format'
import
type
{
DataSourceNotionPage
}
from
'@/models/common'
import
{
DataSourceType
}
from
'@/models/datasets'
import
NotionIcon
from
'@/app/components/base/notion-icon'
import
Switch
from
'@/app/components/base/switch'
import
{
MessageChatSquare
}
from
'@/app/components/base/icons/src/public/common'
import
{
useDatasetDetailContext
}
from
'@/context/dataset-detail'
type
Page
=
DataSourceNotionPage
&
{
workspace_id
:
string
}
...
...
@@ -53,6 +55,10 @@ enum IndexingType {
QUALIFIED
=
'high_quality'
,
ECONOMICAL
=
'economy'
,
}
enum
DocForm
{
TEXT
=
'text_model'
,
QA
=
'qa_model'
,
}
const
StepTwo
=
({
isSetting
,
...
...
@@ -88,6 +94,9 @@ const StepTwo = ({
?
IndexingType
.
QUALIFIED
:
IndexingType
.
ECONOMICAL
,
)
const
[
docForm
,
setDocForm
]
=
useState
<
DocForm
|
string
>
(
datasetId
&&
documentDetail
?
documentDetail
.
doc_form
:
DocForm
.
TEXT
,
)
const
[
showPreview
,
{
setTrue
:
setShowPreview
,
setFalse
:
hidePreview
}]
=
useBoolean
()
const
[
customFileIndexingEstimate
,
setCustomFileIndexingEstimate
]
=
useState
<
IndexingEstimateResponse
|
null
>
(
null
)
const
[
automaticFileIndexingEstimate
,
setAutomaticFileIndexingEstimate
]
=
useState
<
IndexingEstimateResponse
|
null
>
(
null
)
...
...
@@ -205,6 +214,7 @@ const StepTwo = ({
})
as
NotionInfo
[]
}
// TODO
const
getFileIndexingEstimateParams
=
()
=>
{
let
params
if
(
dataSourceType
===
DataSourceType
.
FILE
)
{
...
...
@@ -237,6 +247,7 @@ const StepTwo = ({
if
(
isSetting
)
{
params
=
{
original_document_id
:
documentDetail
?.
id
,
doc_form
:
docForm
,
process_rule
:
getProcessRule
(),
}
as
CreateDocumentReq
}
...
...
@@ -250,6 +261,7 @@ const StepTwo = ({
},
indexing_technique
:
getIndexing_technique
(),
process_rule
:
getProcessRule
(),
doc_form
:
docForm
,
}
as
CreateDocumentReq
if
(
dataSourceType
===
DataSourceType
.
FILE
)
{
params
.
data_source
.
info_list
.
file_info_list
=
{
...
...
@@ -325,6 +337,13 @@ const StepTwo = ({
}
}
const
handleCheck
=
(
state
:
boolean
)
=>
{
if
(
state
)
setDocForm
(
DocForm
.
QA
)
else
setDocForm
(
DocForm
.
TEXT
)
}
useEffect
(()
=>
{
// fetch rules
if
(
!
isSetting
)
{
...
...
@@ -352,6 +371,11 @@ const StepTwo = ({
}
},
[
showPreview
])
useEffect
(()
=>
{
if
(
indexingType
===
IndexingType
.
ECONOMICAL
&&
docForm
===
DocForm
.
QA
)
setDocForm
(
DocForm
.
TEXT
)
},
[
indexingType
,
docForm
])
useEffect
(()
=>
{
// get indexing type by props
if
(
indexingType
)
...
...
@@ -527,6 +551,24 @@ const StepTwo = ({
<
Link
className=
'text-[#155EEF]'
href=
{
`/datasets/${datasetId}/settings`
}
>
{
t
(
'datasetCreation.stepTwo.datasetSettingLink'
)
}
</
Link
>
</
div
>
)
}
{
(
!
hasSetIndexType
||
(
hasSetIndexType
&&
indexingType
===
IndexingType
.
QUALIFIED
))
&&
(
<
div
className=
'flex justify-between items-center mt-3 px-5 py-4 rounded-xl bg-gray-50 border border-gray-100'
>
<
div
className=
'flex justify-center items-center w-8 h-8 rounded-lg bg-indigo-50'
>
<
MessageChatSquare
className=
'w-4 h-4'
/>
</
div
>
<
div
className=
'grow mx-3'
>
<
div
className=
'mb-[2px] text-md font-medium text-gray-900'
>
{
t
(
'datasetCreation.stepTwo.QATitle'
)
}
</
div
>
<
div
className=
'text-[13px] leading-[18px] text-gray-500'
>
{
t
(
'datasetCreation.stepTwo.QATip'
)
}
</
div
>
</
div
>
<
div
className=
'shrink-0'
>
<
Switch
defaultValue=
{
docForm
===
DocForm
.
QA
}
onChange=
{
handleCheck
}
size=
'md'
/>
</
div
>
</
div
>
)
}
<
div
className=
{
s
.
source
}
>
<
div
className=
{
s
.
sourceContent
}
>
{
dataSourceType
===
DataSourceType
.
FILE
&&
(
...
...
@@ -602,6 +644,7 @@ const StepTwo = ({
{
(
showPreview
)
?
(
<
div
ref=
{
previewScrollRef
}
className=
{
cn
(
s
.
previewWrap
,
'relativeh-full overflow-y-scroll border-l border-[#F2F4F7]'
)
}
>
{
/* TODO preview switch */
}
<
div
className=
{
cn
(
s
.
previewHeader
,
previewScrolled
&&
`${s.fixed} pb-3`
,
' flex items-center justify-between px-8'
)
}
>
<
span
>
{
t
(
'datasetCreation.stepTwo.previewTitle'
)
}
</
span
>
<
div
className=
'flex items-center justify-center w-6 h-6 cursor-pointer'
onClick=
{
hidePreview
}
>
...
...
web/app/components/datasets/documents/detail/completed/SegmentCard.tsx
View file @
0a0960c1
...
...
@@ -67,11 +67,11 @@ const SegmentCard: FC<ISegmentCardProps> = ({
<>
<
div
className=
'flex mb-2'
>
<
div
className=
'mr-2 text-[13px] font-semibold text-gray-400'
>
Q
</
div
>
<
div
className=
'text-[13px]'
>
{
answer
}
</
div
>
<
div
className=
'text-[13px]'
>
{
content
}
</
div
>
</
div
>
<
div
className=
'flex'
>
<
div
className=
'mr-2 text-[13px] font-semibold text-gray-400'
>
A
</
div
>
<
div
className=
'text-[13px]'
>
{
content
}
</
div
>
<
div
className=
'text-[13px]'
>
{
answer
}
</
div
>
</
div
>
</>
)
...
...
web/app/components/datasets/documents/detail/completed/index.tsx
View file @
0a0960c1
...
...
@@ -18,11 +18,13 @@ import Input from '@/app/components/base/input'
import
{
ToastContext
}
from
'@/app/components/base/toast'
import
type
{
Item
}
from
'@/app/components/base/select'
import
{
SimpleSelect
}
from
'@/app/components/base/select'
import
{
disableSegment
,
enableSegment
,
fetchSegments
}
from
'@/service/datasets'
import
type
{
SegmentDetailModel
,
SegmentsQuery
,
SegmentsResponse
}
from
'@/models/datasets'
import
{
disableSegment
,
enableSegment
,
fetchSegments
,
updateSegment
}
from
'@/service/datasets'
import
type
{
SegmentDetailModel
,
Segment
Updator
,
Segment
sQuery
,
SegmentsResponse
}
from
'@/models/datasets'
import
{
asyncRunSafe
}
from
'@/utils'
import
type
{
CommonResponse
}
from
'@/models/common'
import
{
Edit03
,
XClose
}
from
'@/app/components/base/icons/src/vender/line/general'
import
AutoHeightTextarea
from
'@/app/components/base/auto-height-textarea/common'
import
Button
from
'@/app/components/base/button'
export
const
SegmentIndexTag
:
FC
<
{
positionId
:
string
|
number
;
className
?:
string
}
>
=
({
positionId
,
className
})
=>
{
const
localPositionId
=
useMemo
(()
=>
{
...
...
@@ -42,6 +44,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
onCancel
:
()
=>
void
}
/**
...
...
@@ -50,31 +53,89 @@ type ISegmentDetailProps = {
export
const
SegmentDetail
:
FC
<
ISegmentDetailProps
>
=
memo
(({
segInfo
,
onChangeSwitch
,
onUpdate
,
onCancel
,
})
=>
{
const
{
t
}
=
useTranslation
()
const
[
isEditing
,
setIsEditing
]
=
useState
(
false
)
const
[
question
,
setQuestion
]
=
useState
(
segInfo
?.
content
||
''
)
const
[
answer
,
setAnswer
]
=
useState
(
segInfo
?.
answer
||
''
)
const
handleCancel
=
()
=>
{
setIsEditing
(
false
)
setQuestion
(
segInfo
?.
content
||
''
)
setAnswer
(
segInfo
?.
answer
||
''
)
}
const
handleSave
=
()
=>
{
onUpdate
(
segInfo
?.
id
||
''
,
question
,
answer
)
}
const
renderContent
=
()
=>
{
if
(
segInfo
?.
answer
)
{
return
(
<>
<
div
className=
'mb-1 text-xs font-medium text-gray-500'
>
QUESTION
</
div
>
<
div
className=
'mb-4 text-md text-gray-800'
>
{
segInfo
.
answer
}
</
div
>
<
AutoHeightTextarea
outerClassName=
'mb-4'
className=
'leading-6 text-md text-gray-800'
value=
{
question
}
placeholder=
{
t
(
'datasetDocuments.segment.questionPlaceholder'
)
||
''
}
onChange=
{
e
=>
setQuestion
(
e
.
target
.
value
)
}
disabled=
{
!
isEditing
}
/>
<
div
className=
'mb-1 text-xs font-medium text-gray-500'
>
ANSWER
</
div
>
<
div
className=
'text-md text-gray-800'
>
{
segInfo
.
content
}
</
div
>
<
AutoHeightTextarea
outerClassName=
'mb-4'
className=
'leading-6 text-md text-gray-800'
value=
{
answer
}
placeholder=
{
t
(
'datasetDocuments.segment.answerPlaceholder'
)
||
''
}
onChange=
{
e
=>
setAnswer
(
e
.
target
.
value
)
}
disabled=
{
!
isEditing
}
autoFocus
/>
</>
)
}
return
segInfo
?.
content
return
(
<
AutoHeightTextarea
className=
'leading-6 text-md text-gray-800'
value=
{
question
}
placeholder=
{
t
(
'datasetDocuments.segment.questionPlaceholder'
)
||
''
}
onChange=
{
e
=>
setQuestion
(
e
.
target
.
value
)
}
disabled=
{
!
isEditing
}
autoFocus
/>
)
}
return
(
<
div
className=
{
'flex flex-col relative'
}
>
<
div
className=
'absolute right-0 top-0 flex items-center'
>
<
div
className=
'flex justify-center items-center w-6 h-6 hover:bg-gray-100 rounded-md cursor-pointer'
>
<
Edit03
className=
'w-4 h-4 text-gray-500'
/>
</
div
>
<
div
className=
'absolute right-0 top-0 flex items-center h-7'
>
{
isEditing
?
(
<>
<
Button
className=
'mr-2 !h-7 !px-3 !py-[5px] text-xs font-medium text-gray-700 !rounded-md'
onClick=
{
handleCancel
}
>
{
t
(
'common.operation.cancel'
)
}
</
Button
>
<
Button
type=
'primary'
className=
'!h-7 !px-3 !py-[5px] text-xs font-medium !rounded-md'
onClick=
{
handleSave
}
>
{
t
(
'common.operation.save'
)
}
</
Button
>
</>
)
:
(
<
div
className=
'group relative flex justify-center items-center w-6 h-6 hover:bg-gray-100 rounded-md cursor-pointer'
>
<
div
className=
{
cn
(
s
.
editTip
,
'hidden items-center absolute -top-10 px-3 h-[34px] bg-white rounded-lg whitespace-nowrap text-xs font-semibold text-gray-700 group-hover:flex'
)
}
>
{
t
(
'common.operation.edit'
)
}
</
div
>
<
Edit03
className=
'w-4 h-4 text-gray-500'
onClick=
{
()
=>
setIsEditing
(
true
)
}
/>
</
div
>
)
}
<
div
className=
'mx-3 w-[1px] h-3 bg-gray-200'
/>
<
div
className=
'flex justify-center items-center w-6 h-6 cursor-pointer'
onClick=
{
onCancel
}
>
<
XClose
className=
'w-4 h-4 text-gray-500'
/>
...
...
@@ -131,7 +192,7 @@ type ICompletedProps = {
const
Completed
:
FC
<
ICompletedProps
>
=
()
=>
{
const
{
t
}
=
useTranslation
()
const
{
notify
}
=
useContext
(
ToastContext
)
const
{
datasetId
=
''
,
documentId
=
''
}
=
useContext
(
DocumentContext
)
const
{
datasetId
=
''
,
documentId
=
''
,
docForm
}
=
useContext
(
DocumentContext
)
// the current segment id and whether to show the modal
const
[
currSegment
,
setCurrSegment
]
=
useState
<
{
segInfo
?:
SegmentDetailModel
;
showModal
:
boolean
}
>
({
showModal
:
false
})
...
...
@@ -200,6 +261,29 @@ const Completed: FC<ICompletedProps> = () => {
}
}
const
handleUpdateSegment
=
async
(
segmentId
:
string
,
question
:
string
,
answer
:
string
)
=>
{
const
params
:
SegmentUpdator
=
{
content
:
question
}
if
(
docForm
===
'qa_model'
)
params
.
answer
=
answer
const
res
=
await
updateSegment
({
datasetId
,
documentId
,
segmentId
,
body
:
params
})
notify
({
type
:
'success'
,
message
:
t
(
'common.actionMsg.modifiedSuccessfully'
)
})
onCloseModal
()
for
(
const
item
of
allSegments
)
{
for
(
const
seg
of
item
)
{
if
(
seg
.
id
===
segmentId
)
{
seg
.
answer
=
res
.
data
.
answer
seg
.
content
=
res
.
data
.
content
seg
.
word_count
=
res
.
data
.
word_count
seg
.
hit_count
=
res
.
data
.
hit_count
seg
.
index_node_hash
=
res
.
data
.
index_node_hash
seg
.
enabled
=
res
.
data
.
enabled
}
}
}
setAllSegments
([...
allSegments
])
}
return
(
<>
<
div
className=
{
s
.
docSearchWrapper
}
>
...
...
@@ -224,8 +308,13 @@ const Completed: FC<ICompletedProps> = () => {
onChangeSwitch=
{
onChangeSwitch
}
onClick=
{
onClickCard
}
/>
<
Modal
isShow=
{
currSegment
.
showModal
}
onClose=
{
()
=>
{}
}
className=
'!max-w-[640px]'
>
<
SegmentDetail
segInfo=
{
currSegment
.
segInfo
??
{
id
:
''
}
}
onChangeSwitch=
{
onChangeSwitch
}
onCancel=
{
onCloseModal
}
/>
<
Modal
isShow=
{
currSegment
.
showModal
}
onClose=
{
()
=>
{}
}
className=
'!max-w-[640px] !overflow-visible'
>
<
SegmentDetail
segInfo=
{
currSegment
.
segInfo
??
{
id
:
''
}
}
onChangeSwitch=
{
onChangeSwitch
}
onUpdate=
{
handleUpdateSegment
}
onCancel=
{
onCloseModal
}
/>
</
Modal
>
</>
)
...
...
web/app/components/datasets/documents/detail/completed/style.module.css
View file @
0a0960c1
...
...
@@ -129,3 +129,6 @@
border-radius
:
5px
;
@apply
h-3.5
w-3.5
bg-[#EAECF0];
}
.editTip
{
box-shadow
:
0px
4px
6px
-2px
rgba
(
16
,
24
,
40
,
0.03
),
0px
12px
16px
-4px
rgba
(
16
,
24
,
40
,
0.08
);
}
web/app/components/datasets/documents/detail/embedding/index.tsx
View file @
0a0960c1
...
...
@@ -30,6 +30,7 @@ type Props = {
datasetId
?:
string
documentId
?:
string
indexingType
?:
string
detailUpdate
:
VoidFunction
}
const
StopIcon
:
FC
<
{
className
?:
string
}
>
=
({
className
})
=>
{
...
...
@@ -108,7 +109,7 @@ const RuleDetail: FC<{ sourceData?: ProcessRuleResponse; docName?: string }> = (
</
div
>
}
const
EmbeddingDetail
:
FC
<
Props
>
=
({
detail
,
stopPosition
=
'top'
,
datasetId
:
dstId
,
documentId
:
docId
,
indexingType
})
=>
{
const
EmbeddingDetail
:
FC
<
Props
>
=
({
detail
,
stopPosition
=
'top'
,
datasetId
:
dstId
,
documentId
:
docId
,
indexingType
,
detailUpdate
})
=>
{
const
onTop
=
stopPosition
===
'top'
const
{
t
}
=
useTranslation
()
const
{
notify
}
=
useContext
(
ToastContext
)
...
...
@@ -145,6 +146,7 @@ const EmbeddingDetail: FC<Props> = ({ detail, stopPosition = 'top', datasetId: d
const
indexingStatusDetail
=
getIndexingStatusDetail
()
if
(
indexingStatusDetail
?.
indexing_status
===
'completed'
)
{
stopQueryStatus
()
detailUpdate
()
return
}
fetchIndexingStatus
()
...
...
web/app/components/datasets/documents/detail/index.tsx
View file @
0a0960c1
...
...
@@ -27,7 +27,7 @@ export const BackCircleBtn: FC<{ onClick: () => void }> = ({ onClick }) => {
)
}
export
const
DocumentContext
=
createContext
<
{
datasetId
?:
string
;
documentId
?:
string
}
>
({
})
export
const
DocumentContext
=
createContext
<
{
datasetId
?:
string
;
documentId
?:
string
;
docForm
:
string
}
>
({
docForm
:
''
})
type
DocumentTitleProps
=
{
extension
?:
string
...
...
@@ -87,7 +87,7 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
}
return
(
<
DocumentContext
.
Provider
value=
{
{
datasetId
,
documentId
}
}
>
<
DocumentContext
.
Provider
value=
{
{
datasetId
,
documentId
,
docForm
:
documentDetail
?.
doc_form
||
''
}
}
>
<
div
className=
'flex flex-col h-full'
>
<
div
className=
'flex h-16 border-b-gray-100 border-b items-center p-4'
>
<
BackCircleBtn
onClick=
{
backToPrev
}
/>
...
...
@@ -114,7 +114,7 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
{
isDetailLoading
?
<
Loading
type=
'app'
/>
:
<
div
className=
{
`box-border h-full w-full overflow-y-scroll ${embedding ? 'py-12 px-16' : 'pb-[30px] pt-3 px-6'}`
}
>
{
embedding
?
<
Embedding
detail=
{
documentDetail
}
/>
:
<
Completed
/>
}
{
embedding
?
<
Embedding
detail=
{
documentDetail
}
detailUpdate=
{
detailMutate
}
/>
:
<
Completed
/>
}
</
div
>
}
{
showMetadata
&&
<
Metadata
...
...
web/app/components/datasets/hit-testing/hit-detail.tsx
View file @
0a0960c1
...
...
@@ -54,9 +54,9 @@ const HitDetail: FC<IHitDetailProps> = ({ segInfo, vectorInfo }) => {
return
(
<>
<
div
className=
'mt-2 mb-1 text-xs font-medium text-gray-500'
>
QUESTION
</
div
>
<
div
className=
'mb-4 text-md text-gray-800'
>
{
segInfo
.
answer
}
</
div
>
<
div
className=
'mb-4 text-md text-gray-800'
>
{
segInfo
.
content
}
</
div
>
<
div
className=
'mb-1 text-xs font-medium text-gray-500'
>
ANSWER
</
div
>
<
div
className=
'text-md text-gray-800'
>
{
segInfo
.
content
}
</
div
>
<
div
className=
'text-md text-gray-800'
>
{
segInfo
.
answer
}
</
div
>
</>
)
}
...
...
web/i18n/lang/dataset-creation.en.ts
View file @
0a0960c1
...
...
@@ -73,6 +73,8 @@ const translation = {
click
:
'Go to settings'
,
economical
:
'Economical'
,
economicalTip
:
'Use offline vector engines, keyword indexes, etc. to reduce accuracy without spending tokens'
,
QATitle
:
'Segmenting in Question & Answer format'
,
QATip
:
'Enable this option will consume more tokens'
,
emstimateCost
:
'Estimation'
,
emstimateSegment
:
'Estimated segments'
,
segmentCount
:
'segments'
,
...
...
web/i18n/lang/dataset-creation.zh.ts
View file @
0a0960c1
...
...
@@ -73,6 +73,8 @@ const translation = {
click
:
'前往设置'
,
economical
:
'经济'
,
economicalTip
:
'使用离线的向量引擎、关键词索引等方式,降低了准确度但无需花费 Token'
,
QATitle
:
'采用 Q&A 分段模式'
,
QATip
:
'开启后将会消耗额外的 token'
,
emstimateCost
:
'执行嵌入预估消耗'
,
emstimateSegment
:
'预估分段数'
,
segmentCount
:
'段'
,
...
...
web/i18n/lang/dataset-documents.en.ts
View file @
0a0960c1
...
...
@@ -310,6 +310,8 @@ const translation = {
characters
:
'characters'
,
hitCount
:
'hit count'
,
vectorHash
:
'Vector hash: '
,
questionPlaceholder
:
'add question here'
,
answerPlaceholder
:
'add answer here'
,
},
}
...
...
web/i18n/lang/dataset-documents.zh.ts
View file @
0a0960c1
...
...
@@ -309,6 +309,8 @@ const translation = {
characters
:
'字符'
,
hitCount
:
'命中次数'
,
vectorHash
:
'向量哈希:'
,
questionPlaceholder
:
'在这里添加问题'
,
answerPlaceholder
:
'在这里添加答案'
,
},
}
...
...
web/models/datasets.ts
View file @
0a0960c1
...
...
@@ -148,6 +148,7 @@ export type InitialDocumentDetail = {
display_status
:
DocumentDisplayStatus
completed_segments
?:
number
total_segments
?:
number
doc_form
:
'text_model'
|
'qa_model'
}
export
type
SimpleDocumentDetail
=
InitialDocumentDetail
&
{
...
...
@@ -171,6 +172,7 @@ export type DocumentListResponse = {
export
type
CreateDocumentReq
=
{
original_document_id
?:
string
indexing_technique
?:
string
doc_form
:
'text_model'
|
'qa_model'
data_source
:
DataSource
process_rule
:
ProcessRule
}
...
...
@@ -293,6 +295,7 @@ export type SegmentDetailModel = {
completed_at
:
number
error
:
string
|
null
stopped_at
:
number
answer
?:
string
}
export
type
SegmentsResponse
=
{
...
...
@@ -370,3 +373,8 @@ export type RelatedAppResponse = {
data
:
Array
<
RelatedApp
>
total
:
number
}
export
type
SegmentUpdator
=
{
content
:
string
answer
?:
string
}
web/service/datasets.ts
View file @
0a0960c1
import
type
{
Fetcher
}
from
'swr'
import
qs
from
'qs'
import
{
del
,
get
,
patch
,
post
,
put
}
from
'./base'
import
type
{
CreateDocumentReq
,
DataSet
,
DataSetListResponse
,
DocumentDetailResponse
,
DocumentListResponse
,
FileIndexingEstimateResponse
,
HitTestingRecordsResponse
,
HitTestingResponse
,
IndexingEstimateResponse
,
IndexingStatusBatchResponse
,
IndexingStatusResponse
,
ProcessRuleResponse
,
RelatedAppResponse
,
SegmentsQuery
,
SegmentsResponse
,
createDocumentResponse
}
from
'@/models/datasets'
import
type
{
CreateDocumentReq
,
DataSet
,
DataSetListResponse
,
DocumentDetailResponse
,
DocumentListResponse
,
FileIndexingEstimateResponse
,
HitTestingRecordsResponse
,
HitTestingResponse
,
IndexingEstimateResponse
,
IndexingStatusBatchResponse
,
IndexingStatusResponse
,
ProcessRuleResponse
,
RelatedAppResponse
,
SegmentDetailModel
,
SegmentUpdator
,
SegmentsQuery
,
SegmentsResponse
,
createDocumentResponse
,
}
from
'@/models/datasets'
import
type
{
CommonResponse
,
DataSourceNotionWorkspace
}
from
'@/models/common'
// apis for documents in a dataset
...
...
@@ -137,6 +156,10 @@ export const disableSegment: Fetcher<CommonResponse, { datasetId: string; segmen
return
patch
(
`/datasets/
${
datasetId
}
/segments/
${
segmentId
}
/disable`
)
as
Promise
<
CommonResponse
>
}
export
const
updateSegment
:
Fetcher
<
{
data
:
SegmentDetailModel
;
doc_form
:
string
},
{
datasetId
:
string
;
documentId
:
string
;
segmentId
:
string
;
body
:
SegmentUpdator
}
>
=
({
datasetId
,
documentId
,
segmentId
,
body
})
=>
{
return
patch
(
`/datasets/
${
datasetId
}
/documents/
${
documentId
}
/segments/
${
segmentId
}
`
,
{
body
})
as
Promise
<
{
data
:
SegmentDetailModel
;
doc_form
:
string
}
>
}
// hit testing
export
const
hitTesting
:
Fetcher
<
HitTestingResponse
,
{
datasetId
:
string
;
queryText
:
string
}
>
=
({
datasetId
,
queryText
})
=>
{
return
post
(
`/datasets/
${
datasetId
}
/hit-testing`
,
{
body
:
{
query
:
queryText
}
})
as
Promise
<
HitTestingResponse
>
...
...
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