Create.tsx 9.3 KB

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