feat(websearch): add overwrite functionality for search service (#4530)
* feat(websearch): add overwrite functionality for search service - Introduced new settings to allow users to override the default search service. - Updated localization files for English, Japanese, Russian, Simplified Chinese, and Traditional Chinese to include new overwrite options and tooltips. - Modified relevant components and services to support the new overwrite feature in the web search settings. * feat(websearch): enhance web search model integration * chore(websearch): unnecessary return
This commit is contained in:
parent
2a0d6eb08a
commit
ab1a5f18c9
@ -2244,7 +2244,7 @@ export function isWebSearchModel(model: Model): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return model.type?.includes('web_search') || false
|
||||
}
|
||||
|
||||
export function isGenerateImageModel(model: Model): boolean {
|
||||
|
||||
@ -27,6 +27,7 @@ export function getWebSearchTools(model: Model): ChatCompletionTool[] {
|
||||
]
|
||||
}
|
||||
|
||||
if (model?.id.includes('gemini')) {
|
||||
return [
|
||||
{
|
||||
type: 'function',
|
||||
@ -35,4 +36,6 @@ export function getWebSearchTools(model: Model): ChatCompletionTool[] {
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
@ -1292,7 +1292,9 @@
|
||||
"description": "Tavily is a search engine tailored for AI agents, delivering real-time, accurate results, intelligent query suggestions, and in-depth research capabilities.",
|
||||
"title": "Tavily"
|
||||
},
|
||||
"title": "Web Search"
|
||||
"title": "Web Search",
|
||||
"overwrite": "Override search service",
|
||||
"overwrite_tooltip": "Force use search service instead of LLM"
|
||||
},
|
||||
"quickPhrase": {
|
||||
"title": "Quick Phrases",
|
||||
|
||||
@ -1291,7 +1291,9 @@
|
||||
"description": "Tavily は、AI エージェントのために特別に開発された検索エンジンで、最新の結果、インテリジェントな検索提案、そして深い研究能力を提供します",
|
||||
"title": "Tavily"
|
||||
},
|
||||
"title": "ウェブ検索"
|
||||
"title": "ウェブ検索",
|
||||
"overwrite": "サービス検索を上書き",
|
||||
"overwrite_tooltip": "大規模言語モデルではなく、サービス検索を使用する"
|
||||
},
|
||||
"general.auto_check_update.title": "自動更新チェックを有効にする",
|
||||
"quickPhrase": {
|
||||
|
||||
@ -1291,7 +1291,9 @@
|
||||
"description": "Tavily — это поисковая система, специально разработанная для ИИ-агентов, предоставляющая актуальные результаты, умные предложения по запросам и глубокие исследовательские возможности",
|
||||
"title": "Tavily"
|
||||
},
|
||||
"title": "Поиск в Интернете"
|
||||
"title": "Поиск в Интернете",
|
||||
"overwrite": "Переопределить поставщика поиска",
|
||||
"overwrite_tooltip": "Использовать поставщика поиска вместо LLM"
|
||||
},
|
||||
"general.auto_check_update.title": "Включить автоматическую проверку обновлений",
|
||||
"quickPhrase": {
|
||||
|
||||
@ -1279,6 +1279,8 @@
|
||||
"check_success": "验证成功",
|
||||
"enhance_mode": "搜索增强模式",
|
||||
"enhance_mode_tooltip": "使用默认模型提取关键词后搜索",
|
||||
"overwrite": "覆盖服务商搜索",
|
||||
"overwrite_tooltip": "强制使用搜索服务商而不是大语言模型进行搜索",
|
||||
"get_api_key": "点击这里获取密钥",
|
||||
"no_provider_selected": "请选择搜索服务商后再检查",
|
||||
"search_max_result": "搜索结果个数",
|
||||
|
||||
@ -1291,7 +1291,9 @@
|
||||
"description": "Tavily 是一個為 AI 代理量身訂製的搜尋引擎,提供即時、準確的結果、智慧查詢建議和深入的研究能力",
|
||||
"title": "Tavily"
|
||||
},
|
||||
"title": "網路搜尋"
|
||||
"title": "網路搜尋",
|
||||
"overwrite": "覆蓋搜尋服務商",
|
||||
"overwrite_tooltip": "強制使用搜尋服務商而不是大語言模型進行搜尋"
|
||||
},
|
||||
"general.auto_check_update.title": "啟用自動更新檢查",
|
||||
"quickPhrase": {
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { isEmbeddingModel, isFunctionCallingModel, isReasoningModel, isVisionModel } from '@renderer/config/models'
|
||||
import {
|
||||
isEmbeddingModel,
|
||||
isFunctionCallingModel,
|
||||
isReasoningModel,
|
||||
isVisionModel,
|
||||
isWebSearchModel
|
||||
} from '@renderer/config/models'
|
||||
import { Model, ModelType } from '@renderer/types'
|
||||
import { getDefaultGroupName } from '@renderer/utils'
|
||||
import { Button, Checkbox, Divider, Flex, Form, Input, message, Modal } from 'antd'
|
||||
@ -121,7 +127,8 @@ const ModelEditContent: FC<ModelEditContentProps> = ({ model, onUpdateModel, ope
|
||||
...(isVisionModel(model) ? ['vision'] : []),
|
||||
...(isEmbeddingModel(model) ? ['embedding'] : []),
|
||||
...(isReasoningModel(model) ? ['reasoning'] : []),
|
||||
...(isFunctionCallingModel(model) ? ['function_calling'] : [])
|
||||
...(isFunctionCallingModel(model) ? ['function_calling'] : []),
|
||||
...(isWebSearchModel(model) ? ['web_search'] : [])
|
||||
] as ModelType[]
|
||||
|
||||
// 合并现有选择和默认类型
|
||||
@ -161,6 +168,11 @@ const ModelEditContent: FC<ModelEditContentProps> = ({ model, onUpdateModel, ope
|
||||
value: 'vision',
|
||||
disabled: isVisionModel(model) && !selectedTypes.includes('vision')
|
||||
},
|
||||
{
|
||||
label: t('models.type.websearch'),
|
||||
value: 'web_search',
|
||||
disabled: isWebSearchModel(model) && !selectedTypes.includes('web_search')
|
||||
},
|
||||
{
|
||||
label: t('models.type.embedding'),
|
||||
value: 'embedding',
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { setEnhanceMode, setMaxResult, setSearchWithTime } from '@renderer/store/websearch'
|
||||
import { setEnhanceMode, setMaxResult, setOverwrite, setSearchWithTime } from '@renderer/store/websearch'
|
||||
import { Slider, Switch, Tooltip } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { FC } from 'react'
|
||||
@ -12,6 +12,7 @@ const BasicSettings: FC = () => {
|
||||
const { theme } = useTheme()
|
||||
const searchWithTime = useAppSelector((state) => state.websearch.searchWithTime)
|
||||
const enhanceMode = useAppSelector((state) => state.websearch.enhanceMode)
|
||||
const overwrite = useAppSelector((state) => state.websearch.overwrite)
|
||||
const maxResults = useAppSelector((state) => state.websearch.maxResults)
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
@ -26,6 +27,16 @@ const BasicSettings: FC = () => {
|
||||
<Switch checked={searchWithTime} onChange={(checked) => dispatch(setSearchWithTime(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider style={{ marginTop: 15, marginBottom: 12 }} />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
{t('settings.websearch.overwrite')}
|
||||
<Tooltip title={t('settings.websearch.overwrite_tooltip')} placement="right">
|
||||
<InfoCircleOutlined style={{ marginLeft: 5, color: 'var(--color-icon)', cursor: 'pointer' }} />
|
||||
</Tooltip>
|
||||
</SettingRowTitle>
|
||||
<Switch checked={overwrite} onChange={(checked) => dispatch(setOverwrite(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider style={{ marginTop: 15, marginBottom: 12 }} />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
{t('settings.websearch.enhance_mode')}
|
||||
|
||||
@ -30,6 +30,7 @@ import {
|
||||
filterEmptyMessages,
|
||||
filterUserRoleStartMessages
|
||||
} from '@renderer/services/MessagesService'
|
||||
import WebSearchService from '@renderer/services/WebSearchService'
|
||||
import { Assistant, FileType, FileTypes, MCPToolResponse, Message, Model, Provider, Suggestion } from '@renderer/types'
|
||||
import { removeSpecialCharactersForTopicName } from '@renderer/utils'
|
||||
import {
|
||||
@ -232,7 +233,7 @@ export default class GeminiProvider extends BaseProvider {
|
||||
const tools = mcpToolsToGeminiTools(mcpTools)
|
||||
const toolResponses: MCPToolResponse[] = []
|
||||
|
||||
if (assistant.enableWebSearch && isWebSearchModel(model)) {
|
||||
if (!WebSearchService.isOverwriteEnabled() && assistant.enableWebSearch && isWebSearchModel(model)) {
|
||||
tools.push({
|
||||
// @ts-ignore googleSearch is not a valid tool for Gemini
|
||||
googleSearch: {}
|
||||
|
||||
@ -58,7 +58,10 @@ export async function fetchChatCompletion({
|
||||
|
||||
// Search web
|
||||
if (WebSearchService.isWebSearchEnabled() && assistant.enableWebSearch && assistant.model) {
|
||||
const webSearchParams = getOpenAIWebSearchParams(assistant, assistant.model)
|
||||
let webSearchParams = getOpenAIWebSearchParams(assistant, assistant.model)
|
||||
if (WebSearchService.isOverwriteEnabled()) {
|
||||
webSearchParams = {}
|
||||
}
|
||||
|
||||
if (isEmpty(webSearchParams) && !isOpenAIWebSearch(assistant.model)) {
|
||||
const lastMessage = findLast(messages, (m) => m.role === 'user')
|
||||
|
||||
@ -52,6 +52,16 @@ class WebSearchService {
|
||||
return enhanceMode
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否启用覆盖搜索
|
||||
* @public
|
||||
* @returns 如果启用覆盖搜索则返回true,否则返回false
|
||||
*/
|
||||
public isOverwriteEnabled(): boolean {
|
||||
const { overwrite } = this.getWebSearchState()
|
||||
return overwrite
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前默认的网络搜索提供商
|
||||
* @public
|
||||
|
||||
@ -14,6 +14,8 @@ export interface WebSearchState {
|
||||
excludeDomains: string[]
|
||||
// 是否启用搜索增强模式
|
||||
enhanceMode: boolean
|
||||
// 是否覆盖服务商搜索
|
||||
overwrite: boolean
|
||||
}
|
||||
|
||||
const initialState: WebSearchState = {
|
||||
@ -38,7 +40,8 @@ const initialState: WebSearchState = {
|
||||
searchWithTime: true,
|
||||
maxResults: 5,
|
||||
excludeDomains: [],
|
||||
enhanceMode: false
|
||||
enhanceMode: false,
|
||||
overwrite: true
|
||||
}
|
||||
|
||||
const websearchSlice = createSlice({
|
||||
@ -71,6 +74,9 @@ const websearchSlice = createSlice({
|
||||
},
|
||||
setEnhanceMode: (state, action: PayloadAction<boolean>) => {
|
||||
state.enhanceMode = action.payload
|
||||
},
|
||||
setOverwrite: (state, action: PayloadAction<boolean>) => {
|
||||
state.overwrite = action.payload
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -83,7 +89,8 @@ export const {
|
||||
setSearchWithTime,
|
||||
setExcludeDomains,
|
||||
setMaxResult,
|
||||
setEnhanceMode
|
||||
setEnhanceMode,
|
||||
setOverwrite
|
||||
} = websearchSlice.actions
|
||||
|
||||
export default websearchSlice.reducer
|
||||
|
||||
@ -136,7 +136,7 @@ export type Provider = {
|
||||
|
||||
export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'qwenlm' | 'azure-openai'
|
||||
|
||||
export type ModelType = 'text' | 'vision' | 'embedding' | 'reasoning' | 'function_calling'
|
||||
export type ModelType = 'text' | 'vision' | 'embedding' | 'reasoning' | 'function_calling' | 'web_search'
|
||||
|
||||
export type Model = {
|
||||
id: string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user