Create.tsx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import { useEffect, useMemo, useState } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { CodeLanguageEnum, CodeViewData } from '@/components/code/Types';
  4. import DialogTemplate from '@/components/customDialog/DialogTemplate';
  5. import CustomSwitch from '@/components/customSwitch/CustomSwitch';
  6. import {
  7. INDEX_CONFIG,
  8. INDEX_OPTIONS_MAP,
  9. METRIC_TYPES_VALUES,
  10. INDEX_TYPES_ENUM,
  11. DataTypeEnum,
  12. DataTypeStringEnum,
  13. VectorTypes,
  14. } from '@/consts';
  15. import { useFormValidation } from '@/hooks';
  16. import { getCreateIndexJSCode } from '@/utils/code/Js';
  17. import { getCreateIndexPYCode } from '@/utils/code/Py';
  18. import { getCreateIndexJavaCode } from '@/utils/code/Java';
  19. import { formatForm, getMetricOptions } from '@/utils';
  20. import CreateForm from './CreateForm';
  21. import { IndexType, IndexExtraParam } from './Types';
  22. const CreateIndex = (props: {
  23. collectionName: string;
  24. fieldType: DataTypeStringEnum;
  25. dataType: DataTypeEnum;
  26. handleCreate: (params: IndexExtraParam, index_name: string) => void;
  27. handleCancel: () => void;
  28. // used for code mode
  29. fieldName: string;
  30. // used for sizing info
  31. dimension: number;
  32. }) => {
  33. const {
  34. collectionName,
  35. fieldType,
  36. handleCreate,
  37. handleCancel,
  38. fieldName,
  39. dataType,
  40. } = props;
  41. const { t: indexTrans } = useTranslation('index');
  42. const { t: dialogTrans } = useTranslation('dialog');
  43. const { t: btnTrans } = useTranslation('btn');
  44. const { t: commonTrans } = useTranslation();
  45. // https://milvus.io/docs/index.md#In-memory-Index
  46. const defaultIndexType = useMemo(() => {
  47. switch (fieldType) {
  48. case DataTypeStringEnum.BinaryVector:
  49. return INDEX_TYPES_ENUM.BIN_IVF_FLAT;
  50. case DataTypeStringEnum.FloatVector:
  51. case DataTypeStringEnum.Float16Vector:
  52. case DataTypeStringEnum.BFloat16Vector:
  53. return INDEX_TYPES_ENUM.AUTOINDEX;
  54. case DataTypeStringEnum.SparseFloatVector:
  55. return INDEX_TYPES_ENUM.SPARSE_WAND;
  56. case DataTypeStringEnum.VarChar:
  57. return INDEX_TYPES_ENUM.MARISA_TRIE;
  58. case DataTypeStringEnum.Int8:
  59. case DataTypeStringEnum.Int16:
  60. case DataTypeStringEnum.Int32:
  61. case DataTypeStringEnum.Int64:
  62. return INDEX_TYPES_ENUM.INVERTED;
  63. default:
  64. return INDEX_TYPES_ENUM.INVERTED;
  65. }
  66. }, [fieldType]);
  67. const defaultMetricType = useMemo(() => {
  68. switch (fieldType) {
  69. case DataTypeStringEnum.BinaryVector:
  70. return METRIC_TYPES_VALUES.HAMMING;
  71. case DataTypeStringEnum.FloatVector:
  72. case DataTypeStringEnum.Float16Vector:
  73. case DataTypeStringEnum.BFloat16Vector:
  74. return METRIC_TYPES_VALUES.COSINE;
  75. case DataTypeStringEnum.SparseFloatVector:
  76. return METRIC_TYPES_VALUES.IP;
  77. default:
  78. return '';
  79. }
  80. }, [fieldType]);
  81. const [indexSetting, setIndexSetting] = useState<{
  82. index_type: IndexType;
  83. [x: string]: string;
  84. }>({
  85. index_name: '',
  86. index_type: defaultIndexType,
  87. metric_type: defaultMetricType,
  88. M: '',
  89. m: '4',
  90. efConstruction: '',
  91. nlist: '',
  92. nbits: '',
  93. n_trees: '',
  94. outDegree: '',
  95. candidatePoolSize: '',
  96. searchLength: '',
  97. knng: '',
  98. });
  99. // control whether show code mode
  100. const [showCode, setShowCode] = useState<boolean>(false);
  101. const indexCreateParams = useMemo(() => {
  102. if (!INDEX_CONFIG[indexSetting.index_type]) {
  103. return [];
  104. }
  105. return INDEX_CONFIG[indexSetting.index_type].create;
  106. }, [indexSetting.index_type]);
  107. const metricOptions = useMemo(() => {
  108. return VectorTypes.includes(dataType)
  109. ? getMetricOptions(indexSetting.index_type, dataType)
  110. : [];
  111. }, [indexSetting.index_type, fieldType]);
  112. const extraParams = useMemo(() => {
  113. const params: { [x: string]: string } = {};
  114. indexCreateParams.forEach(v => {
  115. params[v] = indexSetting[v];
  116. });
  117. const { index_type, metric_type } = indexSetting;
  118. const extraParams: IndexExtraParam = {
  119. index_type,
  120. metric_type,
  121. params: JSON.stringify(params),
  122. };
  123. return extraParams;
  124. }, [indexCreateParams, indexSetting]);
  125. const indexOptions = useMemo(() => {
  126. switch (fieldType) {
  127. case DataTypeStringEnum.BinaryVector:
  128. return INDEX_OPTIONS_MAP[DataTypeEnum.BinaryVector];
  129. case DataTypeStringEnum.FloatVector:
  130. case DataTypeStringEnum.Float16Vector:
  131. case DataTypeStringEnum.BFloat16Vector:
  132. return INDEX_OPTIONS_MAP[DataTypeEnum.FloatVector];
  133. case DataTypeStringEnum.SparseFloatVector:
  134. return INDEX_OPTIONS_MAP[DataTypeEnum.SparseFloatVector];
  135. case DataTypeStringEnum.VarChar:
  136. return INDEX_OPTIONS_MAP[DataTypeEnum.VarChar];
  137. default:
  138. return [
  139. { label: 'INVERTED', value: INDEX_TYPES_ENUM.INVERTED },
  140. { label: 'STL sort', value: INDEX_TYPES_ENUM.SORT },
  141. ];
  142. }
  143. }, [fieldType]);
  144. const checkedForm = useMemo(() => {
  145. if (!VectorTypes.includes(dataType)) {
  146. return [];
  147. }
  148. const paramsForm: any = { metric_type: indexSetting.metric_type };
  149. indexCreateParams.forEach(v => {
  150. paramsForm[v] = indexSetting[v];
  151. });
  152. const form = formatForm(paramsForm);
  153. return form;
  154. }, [indexSetting, indexCreateParams, fieldType]);
  155. /**
  156. * create index code mode
  157. */
  158. const codeBlockData: CodeViewData[] = useMemo(() => {
  159. const isScalarField = !VectorTypes.includes(dataType);
  160. const getCodeParams = {
  161. collectionName,
  162. fieldName,
  163. extraParams,
  164. isScalarField,
  165. indexName: indexSetting.index_name,
  166. metricType: indexSetting.metric_type,
  167. indexType: indexSetting.index_type,
  168. };
  169. return [
  170. {
  171. label: commonTrans('py'),
  172. language: CodeLanguageEnum.python,
  173. code: getCreateIndexPYCode(getCodeParams),
  174. },
  175. {
  176. label: commonTrans('java'),
  177. language: CodeLanguageEnum.java,
  178. code: getCreateIndexJavaCode(getCodeParams),
  179. },
  180. {
  181. label: commonTrans('js'),
  182. language: CodeLanguageEnum.javascript,
  183. code: getCreateIndexJSCode(getCodeParams),
  184. },
  185. ];
  186. }, [
  187. commonTrans,
  188. extraParams,
  189. collectionName,
  190. fieldName,
  191. indexSetting.index_name,
  192. fieldType,
  193. ]);
  194. const {
  195. validation,
  196. checkIsValid,
  197. disabled,
  198. setDisabled,
  199. resetValidation,
  200. checkFormValid,
  201. } = useFormValidation(checkedForm);
  202. // reset index params
  203. useEffect(() => {
  204. // no need
  205. // setDisabled(true);
  206. setIndexSetting(v => ({
  207. ...v,
  208. index_name: v.index_name,
  209. metric_type: defaultMetricType,
  210. M: '',
  211. m: '4',
  212. efConstruction: '',
  213. nlist: '',
  214. nbits: '8', // 8 by default
  215. n_trees: '',
  216. out_degree: '',
  217. candidate_pool_size: '',
  218. search_length: '',
  219. knng: '',
  220. drop_ratio_build: '0.5',
  221. }));
  222. }, [setDisabled, defaultMetricType]);
  223. const updateStepTwoForm = (type: string, value: string) => {
  224. setIndexSetting(v => ({ ...v, [type]: value }));
  225. };
  226. const onIndexTypeChange = (type: string) => {
  227. // reset index params
  228. let paramsForm: { [key in string]: string } = {};
  229. // m is selector not input
  230. (INDEX_CONFIG[type].create || [])
  231. .filter(t => t !== 'm')
  232. .forEach(item => {
  233. paramsForm[item] = '';
  234. });
  235. // if no other params, the form should be valid.
  236. const form = formatForm(paramsForm);
  237. resetValidation(form);
  238. // trigger validation check after the render
  239. setTimeout(() => {
  240. checkFormValid('.index-form .MuiInputBase-input');
  241. }, 0);
  242. };
  243. const handleCreateIndex = () => {
  244. handleCreate(extraParams, indexSetting.index_name);
  245. };
  246. const handleShowCode = (event: React.ChangeEvent<{ checked: boolean }>) => {
  247. const isChecked = event.target.checked;
  248. setShowCode(isChecked);
  249. };
  250. return (
  251. <DialogTemplate
  252. title={dialogTrans('createTitle', {
  253. type: indexTrans('index'),
  254. name: collectionName,
  255. })}
  256. handleClose={handleCancel}
  257. confirmLabel={btnTrans('create')}
  258. handleConfirm={handleCreateIndex}
  259. confirmDisabled={disabled}
  260. leftActions={<CustomSwitch onChange={handleShowCode} />}
  261. showCode={showCode}
  262. codeBlocksData={codeBlockData}
  263. >
  264. <>
  265. <CreateForm
  266. updateForm={updateStepTwoForm}
  267. metricOptions={metricOptions}
  268. indexOptions={indexOptions}
  269. formValue={indexSetting}
  270. checkIsValid={checkIsValid}
  271. validation={validation}
  272. indexParams={indexCreateParams}
  273. indexTypeChange={onIndexTypeChange}
  274. wrapperClass="index-form"
  275. />
  276. </>
  277. </DialogTemplate>
  278. );
  279. };
  280. export default CreateIndex;