Create.tsx 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. DEFAULT_SEFMENT_FILE_SIZE,
  8. DEFAULT_VECTORS,
  9. INDEX_CONFIG,
  10. INDEX_OPTIONS_MAP,
  11. METRIC_TYPES_VALUES,
  12. } from '../../consts/Milvus';
  13. import { useFormValidation } from '@/hooks/Form';
  14. import { getCreateIndexJSCode } from '@/utils/code/Js';
  15. import { getCreateIndexPYCode } from '@/utils/code/Py';
  16. import { getCreateIndexJavaCode } from '@/utils/code/Java';
  17. import { formatForm, getMetricOptions } from '@/utils/Form';
  18. import { computMilvusRecommonds, formatSize } from '@/utils/SizingTool';
  19. import { DataTypeEnum, DataTypeStringEnum } from '../collections/Types';
  20. import CreateForm from './CreateForm';
  21. import SizingInfo from './SizingInfo';
  22. import { IndexType, IndexExtraParam, INDEX_TYPES_ENUM } from './Types';
  23. const CreateIndex = (props: {
  24. collectionName: string;
  25. fieldType: DataTypeStringEnum;
  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. dimension,
  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. const defaultIndexType = useMemo(() => {
  46. switch (fieldType) {
  47. case DataTypeStringEnum.BinaryVector:
  48. return INDEX_TYPES_ENUM.BIN_IVF_FLAT;
  49. case DataTypeStringEnum.FloatVector:
  50. return INDEX_TYPES_ENUM.IVF_FLAT;
  51. case DataTypeStringEnum.VarChar:
  52. return INDEX_TYPES_ENUM.MARISA_TRIE;
  53. default:
  54. return INDEX_TYPES_ENUM.SORT;
  55. }
  56. }, [fieldType]);
  57. const defaultMetricType = useMemo(() => {
  58. switch (fieldType) {
  59. case DataTypeStringEnum.BinaryVector:
  60. return METRIC_TYPES_VALUES.HAMMING;
  61. case DataTypeStringEnum.FloatVector:
  62. return METRIC_TYPES_VALUES.L2;
  63. default:
  64. return '';
  65. }
  66. }, [fieldType]);
  67. const [indexSetting, setIndexSetting] = useState<{
  68. index_type: IndexType;
  69. [x: string]: string;
  70. }>({
  71. index_name: '',
  72. index_type: defaultIndexType,
  73. metric_type: defaultMetricType,
  74. M: '',
  75. m: '4',
  76. efConstruction: '',
  77. nlist: '',
  78. nbits: '',
  79. n_trees: '',
  80. outDegree: '',
  81. candidatePoolSize: '',
  82. searchLength: '',
  83. knng: '',
  84. });
  85. // control whether show code mode
  86. const [showCode, setShowCode] = useState<boolean>(false);
  87. const indexCreateParams = useMemo(() => {
  88. if (!INDEX_CONFIG[indexSetting.index_type]) {
  89. return [];
  90. }
  91. return INDEX_CONFIG[indexSetting.index_type].create;
  92. }, [indexSetting.index_type]);
  93. const metricOptions = useMemo(() => {
  94. const vectorType = [
  95. DataTypeStringEnum.BinaryVector,
  96. DataTypeStringEnum.FloatVector,
  97. ];
  98. return vectorType.includes(fieldType)
  99. ? getMetricOptions(indexSetting.index_type, fieldType)
  100. : [];
  101. }, [indexSetting.index_type, fieldType]);
  102. const extraParams = useMemo(() => {
  103. const params: { [x: string]: string } = {};
  104. indexCreateParams.forEach(v => {
  105. params[v] = indexSetting[v];
  106. });
  107. const { index_type, metric_type } = indexSetting;
  108. const extraParams: IndexExtraParam = {
  109. index_type,
  110. metric_type,
  111. params: JSON.stringify(params),
  112. };
  113. return extraParams;
  114. }, [indexCreateParams, indexSetting]);
  115. const indexOptions = useMemo(() => {
  116. switch (fieldType) {
  117. case DataTypeStringEnum.BinaryVector:
  118. return INDEX_OPTIONS_MAP[DataTypeEnum.BinaryVector];
  119. case DataTypeStringEnum.FloatVector:
  120. return INDEX_OPTIONS_MAP[DataTypeEnum.FloatVector];
  121. case DataTypeStringEnum.VarChar:
  122. return INDEX_OPTIONS_MAP[DataTypeEnum.VarChar];
  123. default:
  124. return [{ label: 'Ascending', value: 'sort' }];
  125. }
  126. }, [fieldType]);
  127. const checkedForm = useMemo(() => {
  128. if (
  129. fieldType !== DataTypeStringEnum.BinaryVector &&
  130. fieldType !== DataTypeStringEnum.FloatVector
  131. ) {
  132. return [];
  133. }
  134. const paramsForm: any = { metric_type: indexSetting.metric_type };
  135. indexCreateParams.forEach(v => {
  136. paramsForm[v] = indexSetting[v];
  137. });
  138. const form = formatForm(paramsForm);
  139. return form;
  140. }, [indexSetting, indexCreateParams, fieldType]);
  141. // sizing info needed param
  142. const sizingInfo = useMemo(() => {
  143. const { index_type } = indexSetting;
  144. const { nlist, m } = indexSetting;
  145. const floatTypes = [
  146. INDEX_TYPES_ENUM.IVF_FLAT,
  147. INDEX_TYPES_ENUM.IVF_PQ,
  148. INDEX_TYPES_ENUM.IVF_SQ8,
  149. INDEX_TYPES_ENUM.IVF_SQ8_HYBRID,
  150. INDEX_TYPES_ENUM.FLAT,
  151. ];
  152. const bytesTyps = [
  153. INDEX_TYPES_ENUM.BIN_FLAT,
  154. INDEX_TYPES_ENUM.BIN_IVF_FLAT,
  155. ];
  156. const supportedTypes = [...floatTypes, ...bytesTyps];
  157. // check param validation
  158. if (!supportedTypes.includes(index_type)) {
  159. return null;
  160. }
  161. if (!nlist) {
  162. return null;
  163. }
  164. if (index_type === INDEX_TYPES_ENUM.IVF_PQ && !m) {
  165. return null;
  166. }
  167. // vector 100000, segment file size 1024 as default value
  168. const milvusRecommends = computMilvusRecommonds(
  169. DEFAULT_VECTORS,
  170. dimension,
  171. Number(nlist),
  172. Number(m),
  173. DEFAULT_SEFMENT_FILE_SIZE * 1024 * 1024
  174. );
  175. let memoryType = 'byteMemorySize';
  176. let diskType = 'byteDiskSize';
  177. if (floatTypes.includes(index_type)) {
  178. memoryType = 'memorySize';
  179. diskType = 'diskSize';
  180. }
  181. const memorySize = milvusRecommends[memoryType][index_type];
  182. const diskSize = milvusRecommends[diskType][index_type];
  183. return {
  184. memory: formatSize(memorySize),
  185. disk: formatSize(diskSize),
  186. };
  187. }, [dimension, indexSetting]);
  188. /**
  189. * create index code mode
  190. */
  191. const codeBlockData: CodeViewData[] = useMemo(() => {
  192. const vectorTypes = [
  193. DataTypeStringEnum.BinaryVector,
  194. DataTypeStringEnum.FloatVector,
  195. ];
  196. const isScalarField = !vectorTypes.includes(fieldType);
  197. const getCodeParams = {
  198. collectionName,
  199. fieldName,
  200. extraParams,
  201. isScalarField,
  202. indexName: indexSetting.index_name,
  203. metricType: indexSetting.metric_type,
  204. indexType: indexSetting.index_type,
  205. };
  206. return [
  207. {
  208. label: commonTrans('py'),
  209. language: CodeLanguageEnum.python,
  210. code: getCreateIndexPYCode(getCodeParams),
  211. },
  212. {
  213. label: commonTrans('java'),
  214. language: CodeLanguageEnum.java,
  215. code: getCreateIndexJavaCode(getCodeParams),
  216. },
  217. {
  218. label: commonTrans('js'),
  219. language: CodeLanguageEnum.javascript,
  220. code: getCreateIndexJSCode(getCodeParams),
  221. },
  222. ];
  223. }, [
  224. commonTrans,
  225. extraParams,
  226. collectionName,
  227. fieldName,
  228. indexSetting.index_name,
  229. fieldType,
  230. ]);
  231. const { validation, checkIsValid, disabled, setDisabled, resetValidation } =
  232. useFormValidation(checkedForm);
  233. // reset index params
  234. useEffect(() => {
  235. // no need
  236. // setDisabled(true);
  237. setIndexSetting(v => ({
  238. ...v,
  239. index_name: v.index_name,
  240. metric_type: defaultMetricType,
  241. M: '',
  242. m: '4',
  243. efConstruction: '',
  244. nlist: '',
  245. nbits: '8', // 8 by default
  246. n_trees: '',
  247. out_degree: '',
  248. candidate_pool_size: '',
  249. search_length: '',
  250. knng: '',
  251. }));
  252. }, [indexCreateParams, setDisabled, defaultMetricType]);
  253. const updateStepTwoForm = (type: string, value: string) => {
  254. setIndexSetting(v => ({ ...v, [type]: value }));
  255. };
  256. const onIndexTypeChange = (type: string) => {
  257. let paramsForm: { [key in string]: string } = {};
  258. // m is selector not input
  259. (INDEX_CONFIG[type].create || [])
  260. .filter(t => t !== 'm')
  261. .forEach(item => {
  262. paramsForm[item] = '';
  263. });
  264. // if no other params, the form should be valid.
  265. setDisabled((INDEX_CONFIG[type].create || []).length === 0 ? false : true);
  266. const form = formatForm(paramsForm);
  267. resetValidation(form);
  268. };
  269. const handleCreateIndex = () => {
  270. handleCreate(extraParams, indexSetting.index_name);
  271. };
  272. const handleShowCode = (event: React.ChangeEvent<{ checked: boolean }>) => {
  273. const isChecked = event.target.checked;
  274. setShowCode(isChecked);
  275. };
  276. return (
  277. <DialogTemplate
  278. title={dialogTrans('createTitle', {
  279. type: indexTrans('index'),
  280. name: collectionName,
  281. })}
  282. handleClose={handleCancel}
  283. confirmLabel={btnTrans('create')}
  284. handleConfirm={handleCreateIndex}
  285. confirmDisabled={disabled}
  286. leftActions={<CustomSwitch onChange={handleShowCode} />}
  287. showCode={showCode}
  288. codeBlocksData={codeBlockData}
  289. >
  290. <>
  291. <CreateForm
  292. updateForm={updateStepTwoForm}
  293. metricOptions={metricOptions}
  294. indexOptions={indexOptions}
  295. formValue={indexSetting}
  296. checkIsValid={checkIsValid}
  297. validation={validation}
  298. indexParams={indexCreateParams}
  299. indexTypeChange={onIndexTypeChange}
  300. />
  301. <SizingInfo info={sizingInfo} />
  302. </>
  303. </DialogTemplate>
  304. );
  305. };
  306. export default CreateIndex;