mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-10 09:21:25 +08:00
feat(chat): add Querit web search provider (#17813)
This commit is contained in:
@@ -6,8 +6,6 @@ import { MetadataFilter } from '@/components/metadata-filter';
|
||||
import { RerankFormFields } from '@/components/rerank';
|
||||
import { SimilaritySliderFormField } from '@/components/similarity-slider';
|
||||
import { SwitchFormField } from '@/components/switch-fom-field';
|
||||
import { TavilyFormField } from '@/components/tavily-form-field';
|
||||
|
||||
import { TopNFormField } from '@/components/top-n-item';
|
||||
import {
|
||||
FormControl,
|
||||
@@ -19,7 +17,7 @@ import {
|
||||
import { MultiSelect } from '@/components/ui/multi-select';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
|
||||
import { WebSearchFormField } from '@/components/web-search-form-field';
|
||||
import { useFetchKnowledgeMetadataKeys } from '@/hooks/use-knowledge-request';
|
||||
import { prefixName } from '@/utils/form';
|
||||
import { getDirAttribute } from '@/utils/text-direction';
|
||||
@@ -127,9 +125,7 @@ export function ChatPromptEngine({ prefix = '' }: ChatPromptEngineProps) {
|
||||
label={t('chat.tts')}
|
||||
tooltip={t('chat.ttsTip')}
|
||||
></SwitchFormField>
|
||||
<TavilyFormField
|
||||
name={prefixName(prefix, 'prompt_config.tavily_api_key')}
|
||||
></TavilyFormField>
|
||||
<WebSearchFormField prefix={prefix} />
|
||||
<MetadataFilter></MetadataFilter>
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
@@ -22,6 +22,7 @@ import ChatBasicSetting from './chat-basic-settings';
|
||||
import { ChatPromptEngine } from './chat-prompt-engine';
|
||||
import { SavingButton } from './saving-button';
|
||||
import { useChatSettingSchema } from './use-chat-setting-schema';
|
||||
import { getWebSearchProvider } from '../web-search-api-key';
|
||||
|
||||
type ChatSettingsProps = { hasSingleChatBox: boolean };
|
||||
|
||||
@@ -135,6 +136,7 @@ export function ChatSettings({ hasSingleChatBox }: ChatSettingsProps) {
|
||||
...data,
|
||||
prompt_config: {
|
||||
...data.prompt_config,
|
||||
web_search_provider: getWebSearchProvider(data.prompt_config),
|
||||
reference_metadata: normalizedReferenceMetadata,
|
||||
},
|
||||
...llmSettingEnabledValues,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
vectorSimilarityWeightSchema,
|
||||
} from '@/components/similarity-slider';
|
||||
import { topnSchema } from '@/components/top-n-item';
|
||||
import { WebSearchProvider } from '@/constants/chat';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { z } from 'zod';
|
||||
|
||||
@@ -32,6 +33,10 @@ export function useChatSettingSchema() {
|
||||
)
|
||||
.optional(),
|
||||
tavily_api_key: z.string().optional(),
|
||||
querit_api_key: z.string().optional(),
|
||||
web_search_provider: z
|
||||
.enum([WebSearchProvider.Tavily, WebSearchProvider.Querit])
|
||||
.optional(),
|
||||
reasoning: z.boolean().optional(),
|
||||
cross_languages: z.array(z.string()).optional(),
|
||||
reference_metadata: z
|
||||
|
||||
73
web/src/pages/next-chats/chat/use-show-internet.test.ts
Normal file
73
web/src/pages/next-chats/chat/use-show-internet.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { WebSearchProvider } from '@/constants/chat';
|
||||
import type { PromptConfig } from '@/interfaces/database/chat';
|
||||
import { getWebSearchApiKey, getWebSearchProvider } from './web-search-api-key';
|
||||
|
||||
describe('getWebSearchProvider', () => {
|
||||
it('does not select a provider for a new unconfigured dialog', () => {
|
||||
expect(getWebSearchProvider({} as PromptConfig)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('selects Tavily for a legacy dialog with a Tavily key', () => {
|
||||
const promptConfig = {
|
||||
tavily_api_key: 'tvly-test',
|
||||
} as PromptConfig;
|
||||
|
||||
expect(getWebSearchProvider(promptConfig)).toBe(WebSearchProvider.Tavily);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getWebSearchApiKey', () => {
|
||||
it('uses Tavily for dialogs saved before provider selection existed', () => {
|
||||
const promptConfig = {
|
||||
tavily_api_key: 'tvly-test',
|
||||
} as PromptConfig;
|
||||
|
||||
expect(getWebSearchApiKey(promptConfig)).toBe('tvly-test');
|
||||
});
|
||||
|
||||
it('uses only the selected Querit key', () => {
|
||||
const promptConfig = {
|
||||
web_search_provider: WebSearchProvider.Querit,
|
||||
querit_api_key: 'querit-test',
|
||||
tavily_api_key: 'tvly-test',
|
||||
} as PromptConfig;
|
||||
|
||||
expect(getWebSearchApiKey(promptConfig)).toBe('querit-test');
|
||||
});
|
||||
|
||||
it('does not fall back to Tavily when Querit is selected without a key', () => {
|
||||
const promptConfig = {
|
||||
web_search_provider: WebSearchProvider.Querit,
|
||||
tavily_api_key: 'tvly-test',
|
||||
} as PromptConfig;
|
||||
|
||||
expect(getWebSearchApiKey(promptConfig)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('treats a whitespace-only key as unconfigured', () => {
|
||||
const promptConfig = {
|
||||
web_search_provider: WebSearchProvider.Querit,
|
||||
querit_api_key: ' ',
|
||||
} as PromptConfig;
|
||||
|
||||
expect(getWebSearchApiKey(promptConfig)).toBe('');
|
||||
});
|
||||
|
||||
it('does not fall back to Tavily for an unsupported provider', () => {
|
||||
const promptConfig = {
|
||||
web_search_provider: 'unsupported',
|
||||
tavily_api_key: 'tvly-test',
|
||||
} as unknown as PromptConfig;
|
||||
|
||||
expect(getWebSearchApiKey(promptConfig)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('treats a non-string key as unconfigured', () => {
|
||||
const promptConfig = {
|
||||
web_search_provider: WebSearchProvider.Querit,
|
||||
querit_api_key: 123,
|
||||
} as unknown as PromptConfig;
|
||||
|
||||
expect(getWebSearchApiKey(promptConfig)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useFetchChat } from '@/hooks/use-chat-request';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { getWebSearchApiKey } from './web-search-api-key';
|
||||
|
||||
export function useShowInternet() {
|
||||
const { data: currentDialog } = useFetchChat();
|
||||
|
||||
return !isEmpty(currentDialog?.prompt_config?.tavily_api_key);
|
||||
return !isEmpty(getWebSearchApiKey(currentDialog?.prompt_config));
|
||||
}
|
||||
|
||||
41
web/src/pages/next-chats/chat/web-search-api-key.ts
Normal file
41
web/src/pages/next-chats/chat/web-search-api-key.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { WebSearchProvider } from '@/constants/chat';
|
||||
import type { PromptConfig } from '@/interfaces/database/chat';
|
||||
|
||||
export function getWebSearchProvider(promptConfig?: PromptConfig) {
|
||||
const provider = promptConfig?.web_search_provider;
|
||||
|
||||
if (
|
||||
provider === WebSearchProvider.Tavily ||
|
||||
provider === WebSearchProvider.Querit
|
||||
) {
|
||||
return provider;
|
||||
}
|
||||
|
||||
if (
|
||||
provider === undefined &&
|
||||
typeof promptConfig?.tavily_api_key === 'string' &&
|
||||
promptConfig.tavily_api_key.trim()
|
||||
) {
|
||||
return WebSearchProvider.Tavily;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getWebSearchApiKey(promptConfig?: PromptConfig) {
|
||||
const provider = getWebSearchProvider(promptConfig);
|
||||
let apiKey: unknown;
|
||||
|
||||
switch (provider) {
|
||||
case WebSearchProvider.Tavily:
|
||||
apiKey = promptConfig?.tavily_api_key;
|
||||
break;
|
||||
case WebSearchProvider.Querit:
|
||||
apiKey = promptConfig?.querit_api_key;
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return typeof apiKey === 'string' ? apiKey.trim() : undefined;
|
||||
}
|
||||
@@ -115,7 +115,9 @@ const ChatContainer = () => {
|
||||
showUploadIcon={false}
|
||||
stopOutputMessage={stopOutputMessage}
|
||||
showReasoning
|
||||
showInternet={chatInfo?.has_tavily_key}
|
||||
showInternet={
|
||||
chatInfo?.has_web_search_provider ?? chatInfo?.has_tavily_key
|
||||
}
|
||||
></NextMessageInput>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user