diff --git a/app/frontend/src/components/Settings/Settings.module.css b/app/frontend/src/components/Settings/Settings.module.css new file mode 100644 index 0000000000..1d512e58e2 --- /dev/null +++ b/app/frontend/src/components/Settings/Settings.module.css @@ -0,0 +1,3 @@ +.settingsSeparator { + margin-top: 0.75rem; +} diff --git a/app/frontend/src/components/Settings/Settings.tsx b/app/frontend/src/components/Settings/Settings.tsx new file mode 100644 index 0000000000..de404297ab --- /dev/null +++ b/app/frontend/src/components/Settings/Settings.tsx @@ -0,0 +1,316 @@ +import { useId } from "@fluentui/react-hooks"; +import { useTranslation } from "react-i18next"; +import { TextField, ITextFieldProps, Checkbox, ICheckboxProps, Dropdown, IDropdownProps, IDropdownOption } from "@fluentui/react"; +import { HelpCallout } from "../HelpCallout"; +import { GPT4VSettings } from "../GPT4VSettings"; +import { VectorSettings } from "../VectorSettings"; +import { RetrievalMode, VectorFieldOptions, GPT4VInput } from "../../api"; +import styles from "./Settings.module.css"; + +// Add type for onRenderLabel +type RenderLabelType = ITextFieldProps | IDropdownProps | ICheckboxProps; + +export interface SettingsProps { + promptTemplate: string; + temperature: number; + retrieveCount: number; + seed: number | null; + minimumSearchScore: number; + minimumRerankerScore: number; + useSemanticRanker: boolean; + useSemanticCaptions: boolean; + excludeCategory: string; + includeCategory: string; + retrievalMode: RetrievalMode; + useGPT4V: boolean; + gpt4vInput: GPT4VInput; + vectorFieldList: VectorFieldOptions[]; + showSemanticRankerOption: boolean; + showGPT4VOptions: boolean; + showVectorOption: boolean; + useOidSecurityFilter: boolean; + useGroupsSecurityFilter: boolean; + useLogin: boolean; + loggedIn: boolean; + requireAccessControl: boolean; + className?: string; + onChange: (field: string, value: any) => void; + shouldStream?: boolean; // Only used in Chat + useSuggestFollowupQuestions?: boolean; // Only used in Chat + promptTemplatePrefix?: string; + promptTemplateSuffix?: string; + showSuggestFollowupQuestions?: boolean; +} + +export const Settings = ({ + promptTemplate, + temperature, + retrieveCount, + seed, + minimumSearchScore, + minimumRerankerScore, + useSemanticRanker, + useSemanticCaptions, + excludeCategory, + includeCategory, + retrievalMode, + useGPT4V, + gpt4vInput, + vectorFieldList, + showSemanticRankerOption, + showGPT4VOptions, + showVectorOption, + useOidSecurityFilter, + useGroupsSecurityFilter, + useLogin, + loggedIn, + requireAccessControl, + className, + onChange, + shouldStream, + useSuggestFollowupQuestions, + promptTemplatePrefix, + promptTemplateSuffix, + showSuggestFollowupQuestions +}: SettingsProps) => { + const { t } = useTranslation(); + + // Form field IDs + const promptTemplateId = useId("promptTemplate"); + const promptTemplateFieldId = useId("promptTemplateField"); + const temperatureId = useId("temperature"); + const temperatureFieldId = useId("temperatureField"); + const seedId = useId("seed"); + const seedFieldId = useId("seedField"); + const searchScoreId = useId("searchScore"); + const searchScoreFieldId = useId("searchScoreField"); + const rerankerScoreId = useId("rerankerScore"); + const rerankerScoreFieldId = useId("rerankerScoreField"); + const retrieveCountId = useId("retrieveCount"); + const retrieveCountFieldId = useId("retrieveCountField"); + const includeCategoryId = useId("includeCategory"); + const includeCategoryFieldId = useId("includeCategoryField"); + const excludeCategoryId = useId("excludeCategory"); + const excludeCategoryFieldId = useId("excludeCategoryField"); + const semanticRankerId = useId("semanticRanker"); + const semanticRankerFieldId = useId("semanticRankerField"); + const semanticCaptionsId = useId("semanticCaptions"); + const semanticCaptionsFieldId = useId("semanticCaptionsField"); + const useOidSecurityFilterId = useId("useOidSecurityFilter"); + const useOidSecurityFilterFieldId = useId("useOidSecurityFilterField"); + const useGroupsSecurityFilterId = useId("useGroupsSecurityFilter"); + const useGroupsSecurityFilterFieldId = useId("useGroupsSecurityFilterField"); + const shouldStreamId = useId("shouldStream"); + const shouldStreamFieldId = useId("shouldStreamField"); + const suggestFollowupQuestionsId = useId("suggestFollowupQuestions"); + const suggestFollowupQuestionsFieldId = useId("suggestFollowupQuestionsField"); + + const renderLabel = (props: RenderLabelType | undefined, labelId: string, fieldId: string, helpText: string) => ( + + ); + + return ( +
+ onChange("promptTemplate", val || "")} + aria-labelledby={promptTemplateId} + onRenderLabel={props => renderLabel(props, promptTemplateId, promptTemplateFieldId, t("helpTexts.promptTemplate"))} + /> + + onChange("temperature", parseFloat(val || "0"))} + aria-labelledby={temperatureId} + onRenderLabel={props => renderLabel(props, temperatureId, temperatureFieldId, t("helpTexts.temperature"))} + /> + + onChange("seed", val ? parseInt(val) : null)} + aria-labelledby={seedId} + onRenderLabel={props => renderLabel(props, seedId, seedFieldId, t("helpTexts.seed"))} + /> + + onChange("minimumSearchScore", parseFloat(val || "0"))} + aria-labelledby={searchScoreId} + onRenderLabel={props => renderLabel(props, searchScoreId, searchScoreFieldId, t("helpTexts.searchScore"))} + /> + + {showSemanticRankerOption && ( + onChange("minimumRerankerScore", parseFloat(val || "0"))} + aria-labelledby={rerankerScoreId} + onRenderLabel={props => renderLabel(props, rerankerScoreId, rerankerScoreFieldId, t("helpTexts.rerankerScore"))} + /> + )} + + onChange("retrieveCount", parseInt(val || "3"))} + aria-labelledby={retrieveCountId} + onRenderLabel={props => renderLabel(props, retrieveCountId, retrieveCountFieldId, t("helpTexts.retrieveNumber"))} + /> + + , option?: IDropdownOption) => onChange("includeCategory", option?.key || "")} + aria-labelledby={includeCategoryId} + options={[ + { key: "", text: t("labels.includeCategoryOptions.all") } + // { key: "example", text: "Example Category" } // Add more categories as needed + ]} + onRenderLabel={props => renderLabel(props, includeCategoryId, includeCategoryFieldId, t("helpTexts.includeCategory"))} + /> + + onChange("excludeCategory", val || "")} + aria-labelledby={excludeCategoryId} + onRenderLabel={props => renderLabel(props, excludeCategoryId, excludeCategoryFieldId, t("helpTexts.excludeCategory"))} + /> + + {showSemanticRankerOption && ( + <> + onChange("useSemanticRanker", !!checked)} + aria-labelledby={semanticRankerId} + onRenderLabel={props => renderLabel(props, semanticRankerId, semanticRankerFieldId, t("helpTexts.useSemanticReranker"))} + /> + + onChange("useSemanticCaptions", !!checked)} + disabled={!useSemanticRanker} + aria-labelledby={semanticCaptionsId} + onRenderLabel={props => renderLabel(props, semanticCaptionsId, semanticCaptionsFieldId, t("helpTexts.useSemanticCaptions"))} + /> + + )} + + {useLogin && ( + <> + onChange("useOidSecurityFilter", !!checked)} + aria-labelledby={useOidSecurityFilterId} + onRenderLabel={props => renderLabel(props, useOidSecurityFilterId, useOidSecurityFilterFieldId, t("helpTexts.useOidSecurityFilter"))} + /> + onChange("useGroupsSecurityFilter", !!checked)} + aria-labelledby={useGroupsSecurityFilterId} + onRenderLabel={props => + renderLabel(props, useGroupsSecurityFilterId, useGroupsSecurityFilterFieldId, t("helpTexts.useGroupsSecurityFilter")) + } + /> + + )} + + {showGPT4VOptions && ( + onChange("useGPT4V", val)} + updateGPT4VInputs={val => onChange("gpt4vInput", val)} + /> + )} + + {showVectorOption && ( + onChange("vectorFieldList", val)} + updateRetrievalMode={val => onChange("retrievalMode", val)} + /> + )} + + {/* Streaming checkbox for Chat */} + {shouldStream !== undefined && ( + onChange("shouldStream", !!checked)} + aria-labelledby={shouldStreamId} + onRenderLabel={props => renderLabel(props, shouldStreamId, shouldStreamFieldId, t("helpTexts.streamChat"))} + /> + )} + + {/* Followup questions checkbox for Chat */} + {showSuggestFollowupQuestions && ( + onChange("useSuggestFollowupQuestions", !!checked)} + aria-labelledby={suggestFollowupQuestionsId} + onRenderLabel={props => + renderLabel(props, suggestFollowupQuestionsId, suggestFollowupQuestionsFieldId, t("helpTexts.suggestFollowupQuestions")) + } + /> + )} +
+ ); +}; diff --git a/app/frontend/src/pages/ask/Ask.tsx b/app/frontend/src/pages/ask/Ask.tsx index d336a4566c..35137afb3d 100644 --- a/app/frontend/src/pages/ask/Ask.tsx +++ b/app/frontend/src/pages/ask/Ask.tsx @@ -1,19 +1,7 @@ import { useContext, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { Helmet } from "react-helmet-async"; -import { - Checkbox, - Panel, - DefaultButton, - Spinner, - TextField, - ICheckboxProps, - ITextFieldProps, - Dropdown, - IDropdownOption, - IDropdownProps -} from "@fluentui/react"; -import { useId } from "@fluentui/react-hooks"; +import { Panel, DefaultButton, Spinner } from "@fluentui/react"; import styles from "./Ask.module.css"; @@ -22,13 +10,10 @@ import { Answer, AnswerError } from "../../components/Answer"; import { QuestionInput } from "../../components/QuestionInput"; import { ExampleList } from "../../components/Example"; import { AnalysisPanel, AnalysisPanelTabs } from "../../components/AnalysisPanel"; -import { HelpCallout } from "../../components/HelpCallout"; import { SettingsButton } from "../../components/SettingsButton/SettingsButton"; -import { useLogin, getToken, requireAccessControl, checkLoggedIn } from "../../authConfig"; -import { VectorSettings } from "../../components/VectorSettings"; -import { GPT4VSettings } from "../../components/GPT4VSettings"; +import { useLogin, getToken, requireAccessControl } from "../../authConfig"; import { UploadFile } from "../../components/UploadFile"; - +import { Settings } from "../../components/Settings/Settings"; import { useMsal } from "@azure/msal-react"; import { TokenClaimsDisplay } from "../../components/TokenClaimsDisplay"; import { LoginContext } from "../../loginContext"; @@ -163,43 +148,63 @@ export function Component(): JSX.Element { } }; - const onPromptTemplateChange = (_ev?: React.FormEvent, newValue?: string) => { - setPromptTemplate(newValue || ""); - }; - - const onTemperatureChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setTemperature(parseFloat(newValue || "0")); - }; - - const onSeedChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setSeed(parseInt(newValue || "")); - }; - - const onMinimumSearchScoreChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setMinimumSearchScore(parseFloat(newValue || "0")); - }; - - const onMinimumRerankerScoreChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setMinimumRerankerScore(parseFloat(newValue || "0")); - }; - const onRetrieveCountChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setRetrieveCount(parseInt(newValue || "3")); - }; - - const onUseSemanticRankerChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseSemanticRanker(!!checked); - }; - - const onUseSemanticCaptionsChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseSemanticCaptions(!!checked); - }; - - const onIncludeCategoryChanged = (_ev?: React.FormEvent, option?: IDropdownOption) => { - setIncludeCategory((option?.key as string) || ""); - }; - - const onExcludeCategoryChanged = (_ev?: React.FormEvent, newValue?: string) => { - setExcludeCategory(newValue || ""); + const handleSettingsChange = (field: string, value: any) => { + switch (field) { + case "promptTemplate": + setPromptTemplate(value); + break; + case "promptTemplatePrefix": + setPromptTemplatePrefix(value); + break; + case "promptTemplateSuffix": + setPromptTemplateSuffix(value); + break; + case "temperature": + setTemperature(value); + break; + case "seed": + setSeed(value); + break; + case "minimumRerankerScore": + setMinimumRerankerScore(value); + break; + case "minimumSearchScore": + setMinimumSearchScore(value); + break; + case "retrieveCount": + setRetrieveCount(value); + break; + case "useSemanticRanker": + setUseSemanticRanker(value); + break; + case "useSemanticCaptions": + setUseSemanticCaptions(value); + break; + case "excludeCategory": + setExcludeCategory(value); + break; + case "includeCategory": + setIncludeCategory(value); + break; + case "useOidSecurityFilter": + setUseOidSecurityFilter(value); + break; + case "useGroupsSecurityFilter": + setUseGroupsSecurityFilter(value); + break; + case "useGPT4V": + setUseGPT4V(value); + break; + case "gpt4vInput": + setGPT4VInput(value); + break; + case "vectorFieldList": + setVectorFieldList(value); + break; + case "retrievalMode": + setRetrievalMode(value); + break; + } }; const onExampleClicked = (example: string) => { @@ -232,31 +237,6 @@ export function Component(): JSX.Element { setUseGroupsSecurityFilter(!!checked); }; - // IDs for form labels and their associated callouts - const promptTemplateId = useId("promptTemplate"); - const promptTemplateFieldId = useId("promptTemplateField"); - const temperatureId = useId("temperature"); - const temperatureFieldId = useId("temperatureField"); - const seedId = useId("seed"); - const seedFieldId = useId("seedField"); - const searchScoreId = useId("searchScore"); - const searchScoreFieldId = useId("searchScoreField"); - const rerankerScoreId = useId("rerankerScore"); - const rerankerScoreFieldId = useId("rerankerScoreField"); - const retrieveCountId = useId("retrieveCount"); - const retrieveCountFieldId = useId("retrieveCountField"); - const includeCategoryId = useId("includeCategory"); - const includeCategoryFieldId = useId("includeCategoryField"); - const excludeCategoryId = useId("excludeCategory"); - const excludeCategoryFieldId = useId("excludeCategoryField"); - const semanticRankerId = useId("semanticRanker"); - const semanticRankerFieldId = useId("semanticRankerField"); - const semanticCaptionsId = useId("semanticCaptions"); - const semanticCaptionsFieldId = useId("semanticCaptionsField"); - const useOidSecurityFilterId = useId("useOidSecurityFilter"); - const useOidSecurityFilterFieldId = useId("useOidSecurityFilterField"); - const useGroupsSecurityFilterId = useId("useGroupsSecurityFilter"); - const useGroupsSecurityFilterFieldId = useId("useGroupsSecurityFilterField"); const { t, i18n } = useTranslation(); return ( @@ -330,234 +310,33 @@ export function Component(): JSX.Element { onRenderFooterContent={() => setIsConfigPanelOpen(false)}>{t("labels.closeButton")}} isFooterAtBottom={true} > - ( - - )} + - - ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - - {showSemanticRankerOption && ( - ( - - )} - /> - )} - - ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - - {showSemanticRankerOption && ( - <> - ( - - )} - /> - - ( - - )} - /> - - )} - - {showGPT4VOptions && ( - { - setUseGPT4V(useGPT4V); - }} - updateGPT4VInputs={inputs => setGPT4VInput(inputs)} - /> - )} - - {showVectorOption && ( - setVectorFieldList(options)} - updateRetrievalMode={(retrievalMode: RetrievalMode) => setRetrievalMode(retrievalMode)} - /> - )} - - {useLogin && ( - <> - ( - - )} - /> - ( - - )} - /> - - )} {useLogin && } diff --git a/app/frontend/src/pages/chat/Chat.tsx b/app/frontend/src/pages/chat/Chat.tsx index a68f47b9b0..1fa09ec511 100644 --- a/app/frontend/src/pages/chat/Chat.tsx +++ b/app/frontend/src/pages/chat/Chat.tsx @@ -1,9 +1,8 @@ import { useRef, useState, useEffect, useContext } from "react"; import { useTranslation } from "react-i18next"; import { Helmet } from "react-helmet-async"; -import { Checkbox, Panel, DefaultButton, TextField, ITextFieldProps, ICheckboxProps, Dropdown, IDropdownOption, IDropdownProps } from "@fluentui/react"; +import { Panel, DefaultButton } from "@fluentui/react"; import { SparkleFilled } from "@fluentui/react-icons"; -import { useId } from "@fluentui/react-hooks"; import readNDJSONStream from "ndjson-readablestream"; import styles from "./Chat.module.css"; @@ -24,7 +23,6 @@ import { Answer, AnswerError, AnswerLoading } from "../../components/Answer"; import { QuestionInput } from "../../components/QuestionInput"; import { ExampleList } from "../../components/Example"; import { UserChatMessage } from "../../components/UserChatMessage"; -import { HelpCallout } from "../../components/HelpCallout"; import { AnalysisPanel, AnalysisPanelTabs } from "../../components/AnalysisPanel"; import { HistoryPanel } from "../../components/HistoryPanel"; import { HistoryProviderOptions, useHistoryManager } from "../../components/HistoryProviders"; @@ -33,12 +31,11 @@ import { SettingsButton } from "../../components/SettingsButton"; import { ClearChatButton } from "../../components/ClearChatButton"; import { UploadFile } from "../../components/UploadFile"; import { useLogin, getToken, requireAccessControl } from "../../authConfig"; -import { VectorSettings } from "../../components/VectorSettings"; import { useMsal } from "@azure/msal-react"; import { TokenClaimsDisplay } from "../../components/TokenClaimsDisplay"; -import { GPT4VSettings } from "../../components/GPT4VSettings"; import { LoginContext } from "../../loginContext"; import { LanguagePicker } from "../../i18n/LanguagePicker"; +import { Settings } from "../../components/Settings/Settings"; const Chat = () => { const [isConfigPanelOpen, setIsConfigPanelOpen] = useState(false); @@ -257,60 +254,63 @@ const Chat = () => { getConfig(); }, []); - const onPromptTemplateChange = (_ev?: React.FormEvent, newValue?: string) => { - setPromptTemplate(newValue || ""); - }; - - const onTemperatureChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setTemperature(parseFloat(newValue || "0")); - }; - - const onSeedChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setSeed(parseInt(newValue || "")); - }; - - const onMinimumSearchScoreChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setMinimumSearchScore(parseFloat(newValue || "0")); - }; - - const onMinimumRerankerScoreChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setMinimumRerankerScore(parseFloat(newValue || "0")); - }; - - const onRetrieveCountChange = (_ev?: React.SyntheticEvent, newValue?: string) => { - setRetrieveCount(parseInt(newValue || "3")); - }; - - const onUseSemanticRankerChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseSemanticRanker(!!checked); - }; - - const onUseSemanticCaptionsChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseSemanticCaptions(!!checked); - }; - - const onShouldStreamChange = (_ev?: React.FormEvent, checked?: boolean) => { - setShouldStream(!!checked); - }; - - const onIncludeCategoryChanged = (_ev?: React.FormEvent, option?: IDropdownOption) => { - setIncludeCategory((option?.key as string) || ""); - }; - - const onExcludeCategoryChanged = (_ev?: React.FormEvent, newValue?: string) => { - setExcludeCategory(newValue || ""); - }; - - const onUseSuggestFollowupQuestionsChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseSuggestFollowupQuestions(!!checked); - }; - - const onUseOidSecurityFilterChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseOidSecurityFilter(!!checked); - }; - - const onUseGroupsSecurityFilterChange = (_ev?: React.FormEvent, checked?: boolean) => { - setUseGroupsSecurityFilter(!!checked); + const handleSettingsChange = (field: string, value: any) => { + switch (field) { + case "promptTemplate": + setPromptTemplate(value); + break; + case "temperature": + setTemperature(value); + break; + case "seed": + setSeed(value); + break; + case "minimumRerankerScore": + setMinimumRerankerScore(value); + break; + case "minimumSearchScore": + setMinimumSearchScore(value); + break; + case "retrieveCount": + setRetrieveCount(value); + break; + case "useSemanticRanker": + setUseSemanticRanker(value); + break; + case "useSemanticCaptions": + setUseSemanticCaptions(value); + break; + case "excludeCategory": + setExcludeCategory(value); + break; + case "includeCategory": + setIncludeCategory(value); + break; + case "useOidSecurityFilter": + setUseOidSecurityFilter(value); + break; + case "useGroupsSecurityFilter": + setUseGroupsSecurityFilter(value); + break; + case "shouldStream": + setShouldStream(value); + break; + case "useSuggestFollowupQuestions": + setUseSuggestFollowupQuestions(value); + break; + case "useGPT4V": + setUseGPT4V(value); + break; + case "gpt4vInput": + setGPT4VInput(value); + break; + case "vectorFieldList": + setVectorFieldList(value); + break; + case "retrievalMode": + setRetrievalMode(value); + break; + } }; const onExampleClicked = (example: string) => { @@ -338,35 +338,6 @@ const Chat = () => { setSelectedAnswer(index); }; - // IDs for form labels and their associated callouts - const promptTemplateId = useId("promptTemplate"); - const promptTemplateFieldId = useId("promptTemplateField"); - const temperatureId = useId("temperature"); - const temperatureFieldId = useId("temperatureField"); - const seedId = useId("seed"); - const seedFieldId = useId("seedField"); - const searchScoreId = useId("searchScore"); - const searchScoreFieldId = useId("searchScoreField"); - const rerankerScoreId = useId("rerankerScore"); - const rerankerScoreFieldId = useId("rerankerScoreField"); - const retrieveCountId = useId("retrieveCount"); - const retrieveCountFieldId = useId("retrieveCountField"); - const includeCategoryId = useId("includeCategory"); - const includeCategoryFieldId = useId("includeCategoryField"); - const excludeCategoryId = useId("excludeCategory"); - const excludeCategoryFieldId = useId("excludeCategoryField"); - const semanticRankerId = useId("semanticRanker"); - const semanticRankerFieldId = useId("semanticRankerField"); - const semanticCaptionsId = useId("semanticCaptions"); - const semanticCaptionsFieldId = useId("semanticCaptionsField"); - const suggestFollowupQuestionsId = useId("suggestFollowupQuestions"); - const suggestFollowupQuestionsFieldId = useId("suggestFollowupQuestionsField"); - const useOidSecurityFilterId = useId("useOidSecurityFilter"); - const useOidSecurityFilterFieldId = useId("useOidSecurityFilterField"); - const useGroupsSecurityFilterId = useId("useGroupsSecurityFilter"); - const useGroupsSecurityFilterFieldId = useId("useGroupsSecurityFilterField"); - const shouldStreamId = useId("shouldStream"); - const shouldStreamFieldId = useId("shouldStreamField"); const { t, i18n } = useTranslation(); return ( @@ -509,280 +480,34 @@ const Chat = () => { onRenderFooterContent={() => setIsConfigPanelOpen(false)}>{t("labels.closeButton")}} isFooterAtBottom={true} > - ( - - )} - /> - - ( - - )} + - - ( - - )} - /> - - ( - - )} - /> - - {showSemanticRankerOption && ( - ( - - )} - /> - )} - - ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - - {showSemanticRankerOption && ( - <> - ( - - )} - /> - - ( - - )} - /> - - )} - - ( - - )} - /> - - {showGPT4VOptions && ( - { - setUseGPT4V(useGPT4V); - }} - updateGPT4VInputs={inputs => setGPT4VInput(inputs)} - /> - )} - - {showVectorOption && ( - setVectorFieldList(options)} - updateRetrievalMode={(retrievalMode: RetrievalMode) => setRetrievalMode(retrievalMode)} - /> - )} - - {useLogin && ( - <> - ( - - )} - /> - ( - - )} - /> - - )} - - ( - - )} - /> - {useLogin && } diff --git a/docs/data_ingestion.md b/docs/data_ingestion.md index 1d317b6345..1837018154 100644 --- a/docs/data_ingestion.md +++ b/docs/data_ingestion.md @@ -57,7 +57,7 @@ If needed, you can modify the chunking algorithm in `scripts/prepdocslib/textspl To enhance search functionality, categorize data during the ingestion process with the `--category` argument, for example `scripts/prepdocs.ps1 --category ExampleCategoryName`. This argument specifies the category to which the data belongs, enabling you to filter search results based on these categories. -After running the script with the desired category, ensure these categories are added to the 'Include Category' dropdown list. This can be found in the developer settings of [`Chat.tsx`](../app/frontend/src/pages/chat/Chat.tsx) and [`Ask.tsx`](../app/frontend/src/pages/ask/Ask.tsx). The default option for this dropdown is "All". By including specific categories, you can refine your search results more effectively. +After running the script with the desired category, ensure these categories are added to the 'Include Category' dropdown list. This can be found in the developer settings in [`Settings.tsx`](/app/frontend/src/components/settings/Settings.tsx). The default option for this dropdown is "All". By including specific categories, you can refine your search results more effectively. ### Indexing additional documents diff --git a/tests/e2e.py b/tests/e2e.py index b176d6f6d0..de3f458ac9 100644 --- a/tests/e2e.py +++ b/tests/e2e.py @@ -145,12 +145,17 @@ def test_chat_customization(page: Page, live_server_url: str): # Set up a mock route to the /chat endpoint def handle(route: Route): overrides = route.request.post_data_json["context"]["overrides"] + assert overrides["temperature"] == 0.5 + assert overrides["seed"] == 123 + assert overrides["minimum_search_score"] == 0.5 + assert overrides["minimum_reranker_score"] == 0.5 assert overrides["retrieval_mode"] == "vectors" assert overrides["semantic_ranker"] is False assert overrides["semantic_captions"] is True assert overrides["top"] == 1 assert overrides["prompt_template"] == "You are a cat and only talk about tuna." assert overrides["exclude_category"] == "dogs" + assert overrides["suggest_followup_questions"] is True assert overrides["use_oid_security_filter"] is False assert overrides["use_groups_security_filter"] is False @@ -170,12 +175,23 @@ def handle(route: Route): page.get_by_role("button", name="Developer settings").click() page.get_by_label("Override prompt template").click() page.get_by_label("Override prompt template").fill("You are a cat and only talk about tuna.") + page.get_by_label("Temperature").click() + page.get_by_label("Temperature").fill("0.5") + page.get_by_label("Seed").click() + page.get_by_label("Seed").fill("123") + page.get_by_label("Minimum search score").click() + page.get_by_label("Minimum search score").fill("0.5") + page.get_by_label("Minimum reranker score").click() + page.get_by_label("Minimum reranker score").fill("0.5") page.get_by_label("Retrieve this many search results:").click() page.get_by_label("Retrieve this many search results:").fill("1") + page.get_by_label("Include category").click() + page.get_by_role("option", name="All", exact=True).click() page.get_by_label("Exclude category").click() page.get_by_label("Exclude category").fill("dogs") page.get_by_text("Use semantic captions").click() page.get_by_text("Use semantic ranker for retrieval").click() + page.get_by_text("Suggest follow-up questions").click() page.get_by_text("Vectors + Text (Hybrid)").click() page.get_by_role("option", name="Vectors", exact=True).click() page.get_by_text("Stream chat completion responses").click()