From e4947811a5dc5b21288ff130377f00f7e32a2c41 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:07:32 +0800 Subject: [PATCH] refactor(web): localize retrieval method query (#39795) --- web/__mocks__/provider-context.ts | 1 - .../settings-modal/__tests__/index.spec.tsx | 12 +++--- .../__tests__/retrieval-section.spec.tsx | 19 +++++---- .../__tests__/test-utils.tsx | 1 - .../__tests__/index.spec.tsx | 39 ++++++++++--------- .../common/retrieval-method-config/index.tsx | 14 ++++--- .../hit-testing/__tests__/index.spec.tsx | 7 ---- .../settings/form/__tests__/index.spec.tsx | 1 - web/context/provider-context-provider.tsx | 8 +--- web/context/provider-context.ts | 3 -- web/service/use-common.ts | 9 ----- 11 files changed, 48 insertions(+), 66 deletions(-) diff --git a/web/__mocks__/provider-context.ts b/web/__mocks__/provider-context.ts index c4d33e30fb2..2c8e2e44989 100644 --- a/web/__mocks__/provider-context.ts +++ b/web/__mocks__/provider-context.ts @@ -10,7 +10,6 @@ export const baseProviderContextValue: ProviderContextState = { refreshModelProviders: noop, isLoadingModelProviders: false, textGenerationModelList: [], - supportRetrievalMethods: [], isAPIKeySet: true, plan: defaultPlan, isFetchedPlan: false, diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx index 81d0904bc6c..8fe18a162b0 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx @@ -13,6 +13,7 @@ import { DataSourceType, RerankingModeEnum, } from '@/models/datasets' +import { consoleQuery } from '@/service/client' import { updateDatasetSetting } from '@/service/datasets' import { useMembers } from '@/service/use-common' import { renderWithConsoleQuery as render } from '@/test/console/query-data' @@ -93,12 +94,6 @@ vi.mock('@/context/provider-context', () => ({ useProviderContext: () => ({ modelProviders: [], textGenerationModelList: [], - supportRetrievalMethods: [ - RETRIEVE_METHOD.semantic, - RETRIEVE_METHOD.fullText, - RETRIEVE_METHOD.hybrid, - RETRIEVE_METHOD.keywordSearch, - ], }), })) @@ -206,9 +201,12 @@ const createDataset = ( const renderWithProviders = (dataset: DataSet) => { const queryClient = new QueryClient({ - defaultOptions: { queries: { retry: false } }, + defaultOptions: { queries: { retry: false, staleTime: Number.POSITIVE_INFINITY } }, }) queryClient.setQueryData(systemFeaturesQueryOptions().queryKey, createSystemFeaturesFixture()) + queryClient.setQueryData(consoleQuery.datasets.retrievalSetting.get.queryOptions().queryKey, { + retrieval_method: [RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.fullText, RETRIEVE_METHOD.hybrid], + }) return render( diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx index 06d8c7e2a14..1453738ead0 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx @@ -1,7 +1,8 @@ +import type { ReactElement } from 'react' import type { DataSet } from '@/models/datasets' import type { RetrievalConfig } from '@/types/app' import type { DocPathWithoutLang } from '@/types/doc-paths' -import { render, screen } from '@testing-library/react' +import { screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { IndexingType } from '@/app/components/datasets/create/step-two' import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' @@ -11,6 +12,8 @@ import { DataSourceType, RerankingModeEnum, } from '@/models/datasets' +import { consoleQuery } from '@/service/client' +import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data' import { withSelectorKey } from '@/test/i18n-mock' import { RETRIEVE_METHOD } from '@/types/app' import { RetrievalChangeTip, RetrievalSection } from '../retrieval-section' @@ -31,12 +34,6 @@ vi.mock('@/context/provider-context', () => ({ useProviderContext: () => ({ modelProviders: [], textGenerationModelList: [], - supportRetrievalMethods: [ - RETRIEVE_METHOD.semantic, - RETRIEVE_METHOD.fullText, - RETRIEVE_METHOD.hybrid, - RETRIEVE_METHOD.keywordSearch, - ], }), })) @@ -63,6 +60,14 @@ vi.mock('@/app/components/datasets/create/step-two', () => ({ }, })) +const render = (ui: ReactElement) => { + const queryClient = createConsoleQueryClient() + queryClient.setQueryData(consoleQuery.datasets.retrievalSetting.get.queryOptions().queryKey, { + retrieval_method: [RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.fullText, RETRIEVE_METHOD.hybrid], + }) + return renderWithConsoleQuery(ui, { queryClient }) +} + const createRetrievalConfig = (overrides: Partial = {}): RetrievalConfig => ({ search_method: RETRIEVE_METHOD.semantic, reranking_enable: false, diff --git a/web/app/components/app/overview/apikey-info-panel/__tests__/test-utils.tsx b/web/app/components/app/overview/apikey-info-panel/__tests__/test-utils.tsx index 321dbe73ed2..ebbedd319cf 100644 --- a/web/app/components/app/overview/apikey-info-panel/__tests__/test-utils.tsx +++ b/web/app/components/app/overview/apikey-info-panel/__tests__/test-utils.tsx @@ -42,7 +42,6 @@ const defaultProviderContext = { refreshModelProviders: noop, isLoadingModelProviders: false, textGenerationModelList: [], - supportRetrievalMethods: [], isAPIKeySet: false, plan: defaultPlan, isFetchedPlan: false, diff --git a/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx b/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx index 973bde347bd..c09d2909ceb 100644 --- a/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx +++ b/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx @@ -1,23 +1,18 @@ import type { RetrievalConfig } from '@/types/app' -import { fireEvent, render, screen } from '@testing-library/react' +import { fireEvent, screen } from '@testing-library/react' import * as React from 'react' import { DEFAULT_WEIGHTED_SCORE, RerankingModeEnum, WeightedScoreEnum } from '@/models/datasets' +import { consoleQuery } from '@/service/client' +import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data' import { RETRIEVE_METHOD } from '@/types/app' import RetrievalMethodConfig from '../index' -// Mock provider context with controllable supportRetrievalMethods -let mockSupportRetrievalMethods: RETRIEVE_METHOD[] = [ +let mockRetrievalMethods: string[] = [ RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.fullText, RETRIEVE_METHOD.hybrid, ] -vi.mock('@/context/provider-context', () => ({ - useProviderContext: () => ({ - supportRetrievalMethods: mockSupportRetrievalMethods, - }), -})) - // Mock model hooks with controllable return values let mockRerankDefaultModel: { provider: { provider: string }; model: string } | undefined = { provider: { provider: 'test-provider' }, @@ -72,6 +67,14 @@ const createMockRetrievalConfig = (overrides: Partial = {}): Re ...overrides, }) +const render = (ui: React.ReactElement) => { + const queryClient = createConsoleQueryClient() + queryClient.setQueryData(consoleQuery.datasets.retrievalSetting.get.queryOptions().queryKey, { + retrieval_method: mockRetrievalMethods, + }) + return renderWithConsoleQuery(ui, { queryClient }) +} + // Helper to render component with default props const renderComponent = ( props: Partial> = {}, @@ -87,7 +90,7 @@ describe('RetrievalMethodConfig', () => { beforeEach(() => { vi.clearAllMocks() // Reset mock values to defaults - mockSupportRetrievalMethods = [ + mockRetrievalMethods = [ RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.fullText, RETRIEVE_METHOD.hybrid, @@ -118,7 +121,7 @@ describe('RetrievalMethodConfig', () => { }) it('should only render semantic search when only semantic is supported', () => { - mockSupportRetrievalMethods = [RETRIEVE_METHOD.semantic] + mockRetrievalMethods = [RETRIEVE_METHOD.semantic] renderComponent() expect(screen.getByText('dataset.retrieval.semantic_search.title')).toBeInTheDocument() @@ -127,7 +130,7 @@ describe('RetrievalMethodConfig', () => { }) it('should only render fullText search when only fullText is supported', () => { - mockSupportRetrievalMethods = [RETRIEVE_METHOD.fullText] + mockRetrievalMethods = [RETRIEVE_METHOD.fullText] renderComponent() expect(screen.queryByText('dataset.retrieval.semantic_search.title')).not.toBeInTheDocument() @@ -136,7 +139,7 @@ describe('RetrievalMethodConfig', () => { }) it('should only render hybrid search when only hybrid is supported', () => { - mockSupportRetrievalMethods = [RETRIEVE_METHOD.hybrid] + mockRetrievalMethods = [RETRIEVE_METHOD.hybrid] renderComponent() expect(screen.queryByText('dataset.retrieval.semantic_search.title')).not.toBeInTheDocument() @@ -145,7 +148,7 @@ describe('RetrievalMethodConfig', () => { }) it('should render nothing when no retrieval methods are supported', () => { - mockSupportRetrievalMethods = [] + mockRetrievalMethods = [] const { container } = renderComponent() // Only the wrapper div should exist @@ -763,15 +766,15 @@ describe('RetrievalMethodConfig', () => { expect(onChange).toHaveBeenCalledTimes(3) }) - it('should handle empty supportRetrievalMethods array', () => { - mockSupportRetrievalMethods = [] + it('should ignore unknown retrieval methods from the API', () => { + mockRetrievalMethods = ['unknown_search'] const { container } = renderComponent() expect(container.querySelector('[class*="flex-col"]')?.childNodes.length).toBe(0) }) - it('should handle partial supportRetrievalMethods', () => { - mockSupportRetrievalMethods = [RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.hybrid] + it('should handle partial retrieval methods', () => { + mockRetrievalMethods = [RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.hybrid] renderComponent() expect(screen.getByText('dataset.retrieval.semantic_search.title')).toBeInTheDocument() diff --git a/web/app/components/datasets/common/retrieval-method-config/index.tsx b/web/app/components/datasets/common/retrieval-method-config/index.tsx index 8b716f9fde4..b5fed072075 100644 --- a/web/app/components/datasets/common/retrieval-method-config/index.tsx +++ b/web/app/components/datasets/common/retrieval-method-config/index.tsx @@ -1,6 +1,7 @@ 'use client' import type { FC } from 'react' import type { RetrievalConfig } from '@/types/app' +import { useQuery } from '@tanstack/react-query' import * as React from 'react' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' @@ -11,8 +12,8 @@ import { } from '@/app/components/base/icons/src/vender/knowledge' import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' -import { useProviderContext } from '@/context/provider-context' import { DEFAULT_WEIGHTED_SCORE, RerankingModeEnum, WeightedScoreEnum } from '@/models/datasets' +import { consoleQuery } from '@/service/client' import { RETRIEVE_METHOD } from '@/types/app' import { EffectColor } from '../../settings/chunk-structure/types' import OptionCard from '../../settings/option-card' @@ -32,7 +33,10 @@ const RetrievalMethodConfig: FC = ({ onChange, }) => { const { t } = useTranslation() - const { supportRetrievalMethods } = useProviderContext() + const { data: retrievalSetting } = useQuery( + consoleQuery.datasets.retrievalSetting.get.queryOptions(), + ) + const supportedRetrievalMethods = new Set(retrievalSetting?.retrieval_method ?? []) const { defaultModel: rerankDefaultModel, currentModel: isRerankDefaultModelValid } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank) @@ -107,7 +111,7 @@ const RetrievalMethodConfig: FC = ({ return (
- {supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && ( + {supportedRetrievalMethods.has(RETRIEVE_METHOD.semantic) && ( = ({ /> )} - {supportRetrievalMethods.includes(RETRIEVE_METHOD.fullText) && ( + {supportedRetrievalMethods.has(RETRIEVE_METHOD.fullText) && ( = ({ /> )} - {supportRetrievalMethods.includes(RETRIEVE_METHOD.hybrid) && ( + {supportedRetrievalMethods.has(RETRIEVE_METHOD.hybrid) && ( ({ useDocLink: vi.fn(() => () => 'https://docs.example.com'), })) -// Mock provider context for retrieval method config -vi.mock('@/context/provider-context', () => ({ - useProviderContext: vi.fn(() => ({ - supportRetrievalMethods: ['semantic_search', 'full_text_search', 'hybrid_search'], - })), -})) - // Mock model list hook - include all exports used by child components vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', () => ({ useModelList: vi.fn(() => ({ diff --git a/web/app/components/datasets/settings/form/__tests__/index.spec.tsx b/web/app/components/datasets/settings/form/__tests__/index.spec.tsx index 78c6556f422..bf7622291e6 100644 --- a/web/app/components/datasets/settings/form/__tests__/index.spec.tsx +++ b/web/app/components/datasets/settings/form/__tests__/index.spec.tsx @@ -227,7 +227,6 @@ vi.mock('@/context/provider-context', () => ({ plan: { type: 'free' }, enableBilling: false, onPlanInfoChanged: vi.fn(), - supportRetrievalMethods: ['semantic_search', 'full_text_search', 'hybrid_search'], }), })) diff --git a/web/context/provider-context-provider.tsx b/web/context/provider-context-provider.tsx index 60b7bc62ce6..b4e9ebf8e07 100644 --- a/web/context/provider-context-provider.tsx +++ b/web/context/provider-context-provider.tsx @@ -19,11 +19,7 @@ import { import { ZENDESK_FIELD_IDS } from '@/config' import { deploymentEditionAtom } from '@/context/system-features-state' import { fetchCurrentPlanInfo } from '@/service/billing' -import { - useModelListByType, - useModelProviders, - useSupportRetrievalMethods, -} from '@/service/use-common' +import { useModelListByType, useModelProviders } from '@/service/use-common' import { useEducationStatus } from '@/service/use-education' import { ProviderContext } from './provider-context' import { useAnthropicQuotaNotice } from './provider-storage' @@ -69,7 +65,6 @@ export const ProviderContextProvider = ({ children }: ProviderContextProviderPro const queryClient = useQueryClient() const { data: providersData, isLoading: isLoadingModelProviders } = useModelProviders() const { data: textGenerationModelList } = useModelListByType(ModelTypeEnum.textGeneration) - const { data: supportRetrievalMethods } = useSupportRetrievalMethods() const [plan, setPlan] = useState(defaultPlan) const [isFetchedPlan, setIsFetchedPlan] = useState(false) @@ -205,7 +200,6 @@ export const ProviderContextProvider = ({ children }: ProviderContextProviderPro isAPIKeySet: !!textGenerationModelList?.data?.some( (model) => model.status === ModelStatusEnum.active, ), - supportRetrievalMethods: supportRetrievalMethods?.retrieval_method || [], plan, isFetchedPlan, isFetchedPlanInfo, diff --git a/web/context/provider-context.ts b/web/context/provider-context.ts index f366f7e1340..161a9bd5328 100644 --- a/web/context/provider-context.ts +++ b/web/context/provider-context.ts @@ -5,7 +5,6 @@ import type { Model, ModelProvider, } from '@/app/components/header/account-setting/model-provider-page/declarations' -import type { RETRIEVE_METHOD } from '@/types/app' import { noop } from 'es-toolkit/function' import { createContext, useContext, useContextSelector } from 'use-context-selector' import { defaultPlan } from '@/app/components/billing/config' @@ -15,7 +14,6 @@ export type ProviderContextState = { isLoadingModelProviders: boolean refreshModelProviders: () => void textGenerationModelList: Model[] - supportRetrievalMethods: RETRIEVE_METHOD[] isAPIKeySet: boolean plan: { type: Plan @@ -55,7 +53,6 @@ export const baseProviderContextValue: ProviderContextState = { isLoadingModelProviders: false, refreshModelProviders: noop, textGenerationModelList: [], - supportRetrievalMethods: [], isAPIKeySet: true, plan: defaultPlan, isFetchedPlan: false, diff --git a/web/service/use-common.ts b/web/service/use-common.ts index e3259a3f88d..e0c74a1b997 100644 --- a/web/service/use-common.ts +++ b/web/service/use-common.ts @@ -14,7 +14,6 @@ import type { StructuredOutputRulesRequestBody, StructuredOutputRulesResponse, } from '@/models/common' -import type { RETRIEVE_METHOD } from '@/types/app' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' // oxlint-disable-next-line no-restricted-imports import { get, post } from './base' @@ -29,7 +28,6 @@ export const commonQueryKeys = { modelProviders: [NAME_SPACE, 'model-providers'] as const, modelList: (type: ModelTypeEnum) => [NAME_SPACE, 'model-list', type] as const, defaultModel: (type: ModelTypeEnum) => [NAME_SPACE, 'default-model', type] as const, - retrievalMethods: [NAME_SPACE, 'support-retrieval-methods'] as const, accountIntegrates: [NAME_SPACE, 'account-integrates'] as const, notionConnection: [NAME_SPACE, 'notion-connection'] as const, codeBasedExtensions: (module?: string) => [NAME_SPACE, 'code-based-extensions', module] as const, @@ -211,13 +209,6 @@ export const useModelListByType = (type: ModelTypeEnum, enabled = true) => { }) } -export const useSupportRetrievalMethods = () => { - return useQuery<{ retrieval_method: RETRIEVE_METHOD[] }>({ - queryKey: commonQueryKeys.retrievalMethods, - queryFn: () => get<{ retrieval_method: RETRIEVE_METHOD[] }>('/datasets/retrieval-setting'), - }) -} - export const useCodeBasedExtensions = (module: string) => { return useQuery({ queryKey: commonQueryKeys.codeBasedExtensions(module),