|
1 | 1 | import { useEffect, useState } from "react";
|
2 |
| -import { Stack, IDropdownOption, Dropdown, IDropdownProps } from "@fluentui/react"; |
| 2 | +import { Stack, IDropdownOption, Dropdown, Checkbox, IDropdownProps } from "@fluentui/react"; |
3 | 3 | import { useId } from "@fluentui/react-hooks";
|
4 | 4 | import { useTranslation } from "react-i18next";
|
5 | 5 |
|
6 | 6 | import styles from "./VectorSettings.module.css";
|
7 | 7 | import { HelpCallout } from "../../components/HelpCallout";
|
8 |
| -import { RetrievalMode, VectorFields } from "../../api"; |
| 8 | +import { RetrievalMode } from "../../api"; |
9 | 9 |
|
10 | 10 | interface Props {
|
11 | 11 | showImageOptions?: boolean;
|
12 | 12 | defaultRetrievalMode: RetrievalMode;
|
13 |
| - defaultVectorFields?: VectorFields; |
| 13 | + defaultSearchTextEmbeddings?: boolean; |
| 14 | + defaultSearchImageEmbeddings?: boolean; |
14 | 15 | updateRetrievalMode: (retrievalMode: RetrievalMode) => void;
|
15 |
| - updateVectorFields: (vectorFields: VectorFields) => void; |
| 16 | + updateSearchTextEmbeddings: (searchTextEmbeddings: boolean) => void; |
| 17 | + updateSearchImageEmbeddings: (searchImageEmbeddings: boolean) => void; |
16 | 18 | }
|
17 | 19 |
|
18 |
| -export const VectorSettings = ({ updateRetrievalMode, updateVectorFields, showImageOptions, defaultRetrievalMode, defaultVectorFields }: Props) => { |
| 20 | +export const VectorSettings = ({ |
| 21 | + updateRetrievalMode, |
| 22 | + updateSearchTextEmbeddings, |
| 23 | + updateSearchImageEmbeddings, |
| 24 | + showImageOptions, |
| 25 | + defaultRetrievalMode, |
| 26 | + defaultSearchTextEmbeddings = true, |
| 27 | + defaultSearchImageEmbeddings = true |
| 28 | +}: Props) => { |
19 | 29 | const [retrievalMode, setRetrievalMode] = useState<RetrievalMode>(defaultRetrievalMode || RetrievalMode.Hybrid);
|
20 |
| - const [vectorFields, setVectorFields] = useState<VectorFields>(defaultVectorFields || VectorFields.TextAndImageEmbeddings); |
| 30 | + const [searchTextEmbeddings, setSearchTextEmbeddings] = useState<boolean>(defaultSearchTextEmbeddings); |
| 31 | + const [searchImageEmbeddings, setSearchImageEmbeddings] = useState<boolean>(defaultSearchImageEmbeddings); |
21 | 32 |
|
22 | 33 | const onRetrievalModeChange = (_ev: React.FormEvent<HTMLDivElement>, option?: IDropdownOption<RetrievalMode> | undefined) => {
|
23 | 34 | setRetrievalMode(option?.data || RetrievalMode.Hybrid);
|
24 | 35 | updateRetrievalMode(option?.data || RetrievalMode.Hybrid);
|
25 | 36 | };
|
26 | 37 |
|
27 |
| - const onVectorFieldsChange = (_ev: React.FormEvent<HTMLDivElement>, option?: IDropdownOption<VectorFields> | undefined) => { |
28 |
| - setVectorFields(option?.data || VectorFields.TextAndImageEmbeddings); |
29 |
| - updateVectorFields(option?.data || VectorFields.TextAndImageEmbeddings); |
| 38 | + const onSearchTextEmbeddingsChange = (_ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean) => { |
| 39 | + setSearchTextEmbeddings(checked || false); |
| 40 | + updateSearchTextEmbeddings(checked || false); |
| 41 | + }; |
| 42 | + |
| 43 | + const onSearchImageEmbeddingsChange = (_ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean) => { |
| 44 | + setSearchImageEmbeddings(checked || false); |
| 45 | + updateSearchImageEmbeddings(checked || false); |
30 | 46 | };
|
31 | 47 |
|
32 | 48 | // Only run if showImageOptions changes from true to false or false to true
|
33 | 49 | useEffect(() => {
|
34 | 50 | if (!showImageOptions) {
|
35 |
| - // If images are disabled, we must force to text-only embeddings |
36 |
| - setVectorFields(VectorFields.Embedding); |
37 |
| - updateVectorFields(VectorFields.Embedding); |
| 51 | + // If images are disabled, we must disable image embeddings |
| 52 | + setSearchImageEmbeddings(false); |
| 53 | + updateSearchImageEmbeddings(false); |
38 | 54 | } else {
|
39 |
| - // When image options become available, reset to default or use TextAndImageEmbeddings |
40 |
| - setVectorFields(defaultVectorFields || VectorFields.TextAndImageEmbeddings); |
41 |
| - updateVectorFields(defaultVectorFields || VectorFields.TextAndImageEmbeddings); |
| 55 | + // When image options become available, reset to default |
| 56 | + setSearchImageEmbeddings(defaultSearchImageEmbeddings); |
| 57 | + updateSearchImageEmbeddings(defaultSearchImageEmbeddings); |
42 | 58 | }
|
43 |
| - }, [showImageOptions, updateVectorFields, defaultVectorFields]); |
| 59 | + }, [showImageOptions, updateSearchImageEmbeddings, defaultSearchImageEmbeddings]); |
44 | 60 |
|
45 | 61 | const retrievalModeId = useId("retrievalMode");
|
46 | 62 | const retrievalModeFieldId = useId("retrievalModeField");
|
@@ -78,36 +94,43 @@ export const VectorSettings = ({ updateRetrievalMode, updateVectorFields, showIm
|
78 | 94 | />
|
79 | 95 |
|
80 | 96 | {showImageOptions && [RetrievalMode.Vectors, RetrievalMode.Hybrid].includes(retrievalMode) && (
|
81 |
| - <Dropdown |
82 |
| - id={vectorFieldsFieldId} |
83 |
| - label={t("labels.vector.label")} |
84 |
| - selectedKey={vectorFields} |
85 |
| - options={[ |
86 |
| - { |
87 |
| - key: VectorFields.Embedding, |
88 |
| - text: t("labels.vector.options.embedding"), |
89 |
| - selected: vectorFields === VectorFields.Embedding, |
90 |
| - data: VectorFields.Embedding |
91 |
| - }, |
92 |
| - { |
93 |
| - key: VectorFields.ImageEmbedding, |
94 |
| - text: t("labels.vector.options.imageEmbedding"), |
95 |
| - selected: vectorFields === VectorFields.ImageEmbedding, |
96 |
| - data: VectorFields.ImageEmbedding |
97 |
| - }, |
98 |
| - { |
99 |
| - key: VectorFields.TextAndImageEmbeddings, |
100 |
| - text: t("labels.vector.options.both"), |
101 |
| - selected: vectorFields === VectorFields.TextAndImageEmbeddings, |
102 |
| - data: VectorFields.TextAndImageEmbeddings |
103 |
| - } |
104 |
| - ]} |
105 |
| - onChange={onVectorFieldsChange} |
106 |
| - aria-labelledby={vectorFieldsId} |
107 |
| - onRenderLabel={(props: IDropdownProps | undefined) => ( |
108 |
| - <HelpCallout labelId={vectorFieldsId} fieldId={vectorFieldsFieldId} helpText={t("helpTexts.vectorFields")} label={props?.label} /> |
109 |
| - )} |
110 |
| - /> |
| 97 | + <fieldset className={styles.fieldset}> |
| 98 | + <legend className={styles.legend}>{t("labels.vector.label")}</legend> |
| 99 | + <Stack tokens={{ childrenGap: 8 }}> |
| 100 | + <Checkbox |
| 101 | + id={vectorFieldsFieldId + "-text"} |
| 102 | + className={styles.settingsSeparator} |
| 103 | + label={t("labels.vector.options.embedding")} |
| 104 | + checked={searchTextEmbeddings} |
| 105 | + onChange={onSearchTextEmbeddingsChange} |
| 106 | + aria-labelledby={vectorFieldsId + "-text"} |
| 107 | + onRenderLabel={props => ( |
| 108 | + <HelpCallout |
| 109 | + labelId={vectorFieldsId + "-text"} |
| 110 | + fieldId={vectorFieldsFieldId + "-text"} |
| 111 | + helpText={t("helpTexts.textEmbeddings")} |
| 112 | + label={props?.label} |
| 113 | + /> |
| 114 | + )} |
| 115 | + /> |
| 116 | + <Checkbox |
| 117 | + id={vectorFieldsFieldId + "-image"} |
| 118 | + className={styles.settingsSeparator} |
| 119 | + label={t("labels.vector.options.imageEmbedding")} |
| 120 | + checked={searchImageEmbeddings} |
| 121 | + onChange={onSearchImageEmbeddingsChange} |
| 122 | + aria-labelledby={vectorFieldsId + "-image"} |
| 123 | + onRenderLabel={props => ( |
| 124 | + <HelpCallout |
| 125 | + labelId={vectorFieldsId + "-image"} |
| 126 | + fieldId={vectorFieldsFieldId + "-image"} |
| 127 | + helpText={t("helpTexts.imageEmbeddings")} |
| 128 | + label={props?.label} |
| 129 | + /> |
| 130 | + )} |
| 131 | + /> |
| 132 | + </Stack> |
| 133 | + </fieldset> |
111 | 134 | )}
|
112 | 135 | </Stack>
|
113 | 136 | );
|
|
0 commit comments