panel.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import type { FC } from 'react'
  2. import {
  3. memo,
  4. useCallback,
  5. useMemo,
  6. } from 'react'
  7. import { intersectionBy } from 'lodash-es'
  8. import { useTranslation } from 'react-i18next'
  9. import VarReferencePicker from '../_base/components/variable/var-reference-picker'
  10. import useConfig from './use-config'
  11. import RetrievalConfig from './components/retrieval-config'
  12. import AddKnowledge from './components/add-dataset'
  13. import DatasetList from './components/dataset-list'
  14. import MetadataFilter from './components/metadata/metadata-filter'
  15. import type { KnowledgeRetrievalNodeType } from './types'
  16. import Field from '@/app/components/workflow/nodes/_base/components/field'
  17. import Split from '@/app/components/workflow/nodes/_base/components/split'
  18. import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
  19. import { InputVarType, type NodePanelProps } from '@/app/components/workflow/types'
  20. import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
  21. import ResultPanel from '@/app/components/workflow/run/result-panel'
  22. const i18nPrefix = 'workflow.nodes.knowledgeRetrieval'
  23. const Panel: FC<NodePanelProps<KnowledgeRetrievalNodeType>> = ({
  24. id,
  25. data,
  26. }) => {
  27. const { t } = useTranslation()
  28. const {
  29. readOnly,
  30. inputs,
  31. handleQueryVarChange,
  32. filterVar,
  33. handleModelChanged,
  34. handleCompletionParamsChange,
  35. handleRetrievalModeChange,
  36. handleMultipleRetrievalConfigChange,
  37. selectedDatasets,
  38. selectedDatasetsLoaded,
  39. handleOnDatasetsChange,
  40. isShowSingleRun,
  41. hideSingleRun,
  42. runningStatus,
  43. handleRun,
  44. handleStop,
  45. query,
  46. setQuery,
  47. runResult,
  48. rerankModelOpen,
  49. setRerankModelOpen,
  50. handleAddCondition,
  51. handleMetadataFilterModeChange,
  52. handleRemoveCondition,
  53. handleToggleConditionLogicalOperator,
  54. handleUpdateCondition,
  55. handleMetadataModelChange,
  56. handleMetadataCompletionParamsChange,
  57. availableStringVars,
  58. availableStringNodesWithParent,
  59. availableNumberVars,
  60. availableNumberNodesWithParent,
  61. } = useConfig(id, data)
  62. const handleOpenFromPropsChange = useCallback((openFromProps: boolean) => {
  63. setRerankModelOpen(openFromProps)
  64. }, [setRerankModelOpen])
  65. const metadataList = useMemo(() => {
  66. return intersectionBy(...selectedDatasets.filter((dataset) => {
  67. return !!dataset.doc_metadata
  68. }).map((dataset) => {
  69. return dataset.doc_metadata!
  70. }), 'name')
  71. }, [selectedDatasets])
  72. return (
  73. <div className='pt-2'>
  74. <div className='space-y-4 px-4 pb-2'>
  75. {/* {JSON.stringify(inputs, null, 2)} */}
  76. <Field
  77. title={t(`${i18nPrefix}.queryVariable`)}
  78. >
  79. <VarReferencePicker
  80. nodeId={id}
  81. readonly={readOnly}
  82. isShowNodeName
  83. value={inputs.query_variable_selector}
  84. onChange={handleQueryVarChange}
  85. filterVar={filterVar}
  86. />
  87. </Field>
  88. <Field
  89. title={t(`${i18nPrefix}.knowledge`)}
  90. operations={
  91. <div className='flex items-center space-x-1'>
  92. <RetrievalConfig
  93. payload={{
  94. retrieval_mode: inputs.retrieval_mode,
  95. multiple_retrieval_config: inputs.multiple_retrieval_config,
  96. single_retrieval_config: inputs.single_retrieval_config,
  97. }}
  98. onRetrievalModeChange={handleRetrievalModeChange}
  99. onMultipleRetrievalConfigChange={handleMultipleRetrievalConfigChange}
  100. singleRetrievalModelConfig={inputs.single_retrieval_config?.model}
  101. onSingleRetrievalModelChange={handleModelChanged as any}
  102. onSingleRetrievalModelParamsChange={handleCompletionParamsChange}
  103. readonly={readOnly || !selectedDatasets.length}
  104. openFromProps={rerankModelOpen}
  105. onOpenFromPropsChange={handleOpenFromPropsChange}
  106. selectedDatasets={selectedDatasets}
  107. />
  108. {!readOnly && (<div className='h-3 w-px bg-gray-200'></div>)}
  109. {!readOnly && (
  110. <AddKnowledge
  111. selectedIds={inputs.dataset_ids}
  112. onChange={handleOnDatasetsChange}
  113. />
  114. )}
  115. </div>
  116. }
  117. >
  118. <DatasetList
  119. list={selectedDatasets}
  120. onChange={handleOnDatasetsChange}
  121. readonly={readOnly}
  122. />
  123. </Field>
  124. </div>
  125. <div className='mb-2 py-2'>
  126. <MetadataFilter
  127. metadataList={metadataList}
  128. selectedDatasetsLoaded={selectedDatasetsLoaded}
  129. metadataFilterMode={inputs.metadata_filtering_mode}
  130. metadataFilteringConditions={inputs.metadata_filtering_conditions}
  131. handleAddCondition={handleAddCondition}
  132. handleMetadataFilterModeChange={handleMetadataFilterModeChange}
  133. handleRemoveCondition={handleRemoveCondition}
  134. handleToggleConditionLogicalOperator={handleToggleConditionLogicalOperator}
  135. handleUpdateCondition={handleUpdateCondition}
  136. metadataModelConfig={inputs.metadata_model_config}
  137. handleMetadataModelChange={handleMetadataModelChange}
  138. handleMetadataCompletionParamsChange={handleMetadataCompletionParamsChange}
  139. availableStringVars={availableStringVars}
  140. availableStringNodesWithParent={availableStringNodesWithParent}
  141. availableNumberVars={availableNumberVars}
  142. availableNumberNodesWithParent={availableNumberNodesWithParent}
  143. />
  144. </div>
  145. <Split />
  146. <div>
  147. <OutputVars>
  148. <>
  149. <VarItem
  150. name='result'
  151. type='Array[Object]'
  152. description={t(`${i18nPrefix}.outputVars.output`)}
  153. subItems={[
  154. {
  155. name: 'content',
  156. type: 'string',
  157. description: t(`${i18nPrefix}.outputVars.content`),
  158. },
  159. // url, title, link like bing search reference result: link, link page title, link page icon
  160. {
  161. name: 'title',
  162. type: 'string',
  163. description: t(`${i18nPrefix}.outputVars.title`),
  164. },
  165. {
  166. name: 'url',
  167. type: 'string',
  168. description: t(`${i18nPrefix}.outputVars.url`),
  169. },
  170. {
  171. name: 'icon',
  172. type: 'string',
  173. description: t(`${i18nPrefix}.outputVars.icon`),
  174. },
  175. {
  176. name: 'metadata',
  177. type: 'object',
  178. description: t(`${i18nPrefix}.outputVars.metadata`),
  179. },
  180. ]}
  181. />
  182. </>
  183. </OutputVars>
  184. {isShowSingleRun && (
  185. <BeforeRunForm
  186. nodeName={inputs.title}
  187. onHide={hideSingleRun}
  188. forms={[
  189. {
  190. inputs: [{
  191. label: t(`${i18nPrefix}.queryVariable`)!,
  192. variable: 'query',
  193. type: InputVarType.paragraph,
  194. required: true,
  195. }],
  196. values: { query },
  197. onChange: keyValue => setQuery((keyValue as any).query),
  198. },
  199. ]}
  200. runningStatus={runningStatus}
  201. onRun={handleRun}
  202. onStop={handleStop}
  203. result={<ResultPanel {...runResult} showSteps={false} />}
  204. />
  205. )}
  206. </div>
  207. </div>
  208. )
  209. }
  210. export default memo(Panel)