feat: add search enhance mode switch
This commit is contained in:
parent
b89213b1ab
commit
11620828ad
@ -80,8 +80,8 @@ afterPack: scripts/after-pack.js
|
||||
afterSign: scripts/notarize.js
|
||||
releaseInfo:
|
||||
releaseNotes: |
|
||||
支持引文预览功能
|
||||
界面显示优化
|
||||
修复快捷弹窗无法对话问题
|
||||
MCP:修复豆包无法使用问题
|
||||
MCP:修复 Linux 上无法安装问题
|
||||
知识库设置增加重排模型,提升知识库的准确性
|
||||
自定义服务商增加兼容模式
|
||||
增加 Github Copilot 服务商
|
||||
PlantUML 预览支持放大和缩小
|
||||
联网模式支持增强模式
|
||||
|
||||
@ -1075,6 +1075,8 @@
|
||||
"search_provider_placeholder": "Choose a search service provider.",
|
||||
"search_result_default": "Default",
|
||||
"search_with_time": "Search with dates included",
|
||||
"enhance_mode": "Search enhance mode",
|
||||
"enhance_mode_tooltip": "Use the default model to extract search keywords from the problem and search",
|
||||
"tavily": {
|
||||
"api_key": "Tavily API Key",
|
||||
"api_key.placeholder": "Enter Tavily API Key",
|
||||
|
||||
@ -1075,6 +1075,8 @@
|
||||
"search_provider_placeholder": "検索サービスプロバイダーを選択する",
|
||||
"search_result_default": "デフォルト",
|
||||
"search_with_time": "日付を含む検索",
|
||||
"enhance_mode": "検索強化モード",
|
||||
"enhance_mode_tooltip": "デフォルトモデルを使用して問題から検索キーワードを抽出し、検索を実行します",
|
||||
"tavily": {
|
||||
"api_key": "Tavily API キー",
|
||||
"api_key.placeholder": "Tavily API キーを入力してください",
|
||||
|
||||
@ -1075,6 +1075,8 @@
|
||||
"search_provider_placeholder": "Выберите поставщика поисковых услуг",
|
||||
"search_result_default": "По умолчанию",
|
||||
"search_with_time": "Поиск, содержащий дату",
|
||||
"enhance_mode": "Режим улучшения поиска",
|
||||
"enhance_mode_tooltip": "Используйте модель по умолчанию для извлечения ключевых слов из проблемы и поиска",
|
||||
"tavily": {
|
||||
"api_key": "Ключ API Tavily",
|
||||
"api_key.placeholder": "Введите ключ API Tavily",
|
||||
|
||||
@ -1075,6 +1075,8 @@
|
||||
"search_provider_placeholder": "选择一个搜索服务商",
|
||||
"search_result_default": "默认",
|
||||
"search_with_time": "搜索包含日期",
|
||||
"enhance_mode": "搜索增强模式",
|
||||
"enhance_mode_tooltip": "使用默认模型提取关键词后搜索",
|
||||
"tavily": {
|
||||
"api_key": "Tavily API 密钥",
|
||||
"api_key.placeholder": "请输入 Tavily API 密钥",
|
||||
|
||||
@ -1075,6 +1075,8 @@
|
||||
"search_provider_placeholder": "選擇一個搜尋服務商",
|
||||
"search_result_default": "預設",
|
||||
"search_with_time": "搜尋包含日期",
|
||||
"enhance_mode": "搜索增強模式",
|
||||
"enhance_mode_tooltip": "使用預設模型提取關鍵詞後搜索",
|
||||
"tavily": {
|
||||
"api_key": "Tavily API 金鑰",
|
||||
"api_key.placeholder": "請輸入 Tavily API 金鑰",
|
||||
|
||||
@ -80,6 +80,7 @@ const MCPSettings: FC = () => {
|
||||
|
||||
return (
|
||||
<Paragraph
|
||||
className="selectable"
|
||||
ellipsis={{
|
||||
rows: 1,
|
||||
expandable: 'collapsible',
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { setMaxResult, setSearchWithTime } from '@renderer/store/websearch'
|
||||
import { Slider, Switch } from 'antd'
|
||||
import { setEnhanceMode, setMaxResult, setSearchWithTime } from '@renderer/store/websearch'
|
||||
import { Slider, Switch, Tooltip } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { FC } from 'react'
|
||||
|
||||
@ -10,21 +11,32 @@ import { SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle
|
||||
const BasicSettings: FC = () => {
|
||||
const { theme } = useTheme()
|
||||
const searchWithTime = useAppSelector((state) => state.websearch.searchWithTime)
|
||||
const enhanceMode = useAppSelector((state) => state.websearch.enhanceMode)
|
||||
const maxResults = useAppSelector((state) => state.websearch.maxResults)
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingGroup theme={theme} style={{ paddingBottom: 8 }}>
|
||||
<SettingTitle>{t('settings.general.title')}</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.websearch.search_with_time')}</SettingRowTitle>
|
||||
<Switch checked={searchWithTime} onChange={(checked) => dispatch(setSearchWithTime(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider style={{ marginTop: 15, marginBottom: 5 }} />
|
||||
<SettingRow style={{ marginBottom: -10 }}>
|
||||
<SettingDivider style={{ marginTop: 15, marginBottom: 12 }} />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
{t('settings.websearch.enhance_mode')}
|
||||
<Tooltip title={t('settings.websearch.enhance_mode_tooltip')} placement="right">
|
||||
<InfoCircleOutlined style={{ marginLeft: 5, color: 'var(--color-icon)', cursor: 'pointer' }} />
|
||||
</Tooltip>
|
||||
</SettingRowTitle>
|
||||
<Switch checked={enhanceMode} onChange={(checked) => dispatch(setEnhanceMode(checked))} />
|
||||
</SettingRow>
|
||||
<SettingDivider style={{ marginTop: 15, marginBottom: 12 }} />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.websearch.search_max_result')}</SettingRowTitle>
|
||||
<Slider
|
||||
defaultValue={maxResults}
|
||||
|
||||
@ -476,13 +476,18 @@ export default class AnthropicProvider extends BaseProvider {
|
||||
content: messages.map((m) => m.content).join('\n')
|
||||
}
|
||||
|
||||
const response = await this.sdk.messages.create({
|
||||
const response = await this.sdk.messages.create(
|
||||
{
|
||||
messages: [userMessage] as Anthropic.Messages.MessageParam[],
|
||||
model: model.id,
|
||||
system: systemMessage.content,
|
||||
stream: false,
|
||||
max_tokens: 4096
|
||||
})
|
||||
},
|
||||
{
|
||||
timeout: 20 * 1000
|
||||
}
|
||||
)
|
||||
|
||||
const content = response.content[0].type === 'text' ? response.content[0].text : ''
|
||||
|
||||
|
||||
@ -518,7 +518,10 @@ export default class GeminiProvider extends BaseProvider {
|
||||
temperature: assistant?.settings?.temperature
|
||||
}
|
||||
},
|
||||
this.requestOptions
|
||||
{
|
||||
...this.requestOptions,
|
||||
timeout: 20 * 1000
|
||||
}
|
||||
)
|
||||
|
||||
const chat = await geminiModel.startChat()
|
||||
|
||||
@ -780,13 +780,18 @@ export default class OpenAIProvider extends BaseProvider {
|
||||
content: messages.map((m) => m.content).join('\n')
|
||||
}
|
||||
// @ts-ignore key is not typed
|
||||
const response = await this.sdk.chat.completions.create({
|
||||
const response = await this.sdk.chat.completions.create(
|
||||
{
|
||||
model: model.id,
|
||||
messages: [systemMessage, userMessage] as ChatCompletionMessageParam[],
|
||||
stream: false,
|
||||
keep_alive: this.keepAliveTime,
|
||||
max_tokens: 1000
|
||||
})
|
||||
},
|
||||
{
|
||||
timeout: 20 * 1000
|
||||
}
|
||||
)
|
||||
|
||||
// 针对思考类模型的返回,总结仅截取</think>之后的内容
|
||||
let content = response.choices[0].message?.content || ''
|
||||
|
||||
@ -49,6 +49,7 @@ export async function fetchChatCompletion({
|
||||
const lastMessage = findLast(messages, (m) => m.role === 'user')
|
||||
const lastAnswer = findLast(messages, (m) => m.role === 'assistant')
|
||||
const hasKnowledgeBase = !isEmpty(lastMessage?.knowledgeBaseIds)
|
||||
|
||||
if (lastMessage) {
|
||||
if (hasKnowledgeBase) {
|
||||
window.message.info({
|
||||
@ -57,25 +58,28 @@ export async function fetchChatCompletion({
|
||||
})
|
||||
}
|
||||
|
||||
// 更新消息状态为搜索中
|
||||
onResponse({ ...message, status: 'searching' })
|
||||
|
||||
try {
|
||||
// 等待关键词生成完成
|
||||
const searchSummaryAssistant = getDefaultAssistant()
|
||||
searchSummaryAssistant.model = assistant.model || getDefaultModel()
|
||||
searchSummaryAssistant.prompt = SEARCH_SUMMARY_PROMPT
|
||||
|
||||
// 如果启用搜索增强模式,则使用搜索增强模式
|
||||
if (WebSearchService.isEnhanceModeEnabled()) {
|
||||
const keywords = await fetchSearchSummary({
|
||||
messages: lastAnswer ? [lastAnswer, lastMessage] : [lastMessage],
|
||||
assistant: searchSummaryAssistant
|
||||
})
|
||||
|
||||
if (keywords) {
|
||||
query = keywords
|
||||
}
|
||||
} else {
|
||||
query = lastMessage.content
|
||||
}
|
||||
|
||||
// 更新消息状态为搜索中
|
||||
onResponse({ ...message, status: 'searching' })
|
||||
|
||||
// 等待搜索完成
|
||||
const webSearch = await WebSearchService.search(webSearchProvider, query)
|
||||
|
||||
@ -84,6 +88,7 @@ export async function fetchChatCompletion({
|
||||
...message.metadata,
|
||||
webSearch: webSearch
|
||||
}
|
||||
|
||||
window.keyv.set(`web-search-${lastMessage?.id}`, webSearch)
|
||||
} catch (error) {
|
||||
console.error('Web search failed:', error)
|
||||
@ -93,6 +98,7 @@ export async function fetchChatCompletion({
|
||||
}
|
||||
|
||||
const allMCPTools = await window.api.mcp.listTools()
|
||||
|
||||
await AI.completions({
|
||||
messages: filterUsefulMessages(messages),
|
||||
assistant,
|
||||
|
||||
@ -1,23 +1,10 @@
|
||||
import store from '@renderer/store'
|
||||
import { setDefaultProvider } from '@renderer/store/websearch'
|
||||
import { setDefaultProvider, WebSearchState } from '@renderer/store/websearch'
|
||||
import { WebSearchProvider, WebSearchResponse } from '@renderer/types'
|
||||
import { hasObjectKey } from '@renderer/utils'
|
||||
import WebSearchEngineProvider from '@renderer/webSearchProvider/WebSearchEngineProvider'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
interface WebSearchState {
|
||||
// 默认搜索提供商的ID
|
||||
defaultProvider: string
|
||||
// 所有可用的搜索提供商列表
|
||||
providers: WebSearchProvider[]
|
||||
// 是否在搜索查询中添加当前日期
|
||||
searchWithTime: boolean
|
||||
// 搜索结果的最大数量
|
||||
maxResults: number
|
||||
// 要排除的域名列表
|
||||
excludeDomains: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供网络搜索相关功能的服务类
|
||||
*/
|
||||
@ -55,6 +42,16 @@ class WebSearchService {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否启用搜索增强模式
|
||||
* @public
|
||||
* @returns 如果启用搜索增强模式则返回true,否则返回false
|
||||
*/
|
||||
public isEnhanceModeEnabled(): boolean {
|
||||
const { enhanceMode } = this.getWebSearchState()
|
||||
return enhanceMode
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前默认的网络搜索提供商
|
||||
* @public
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import type { WebSearchProvider } from '@renderer/types'
|
||||
|
||||
export interface WebSearchState {
|
||||
// 默认搜索提供商的ID
|
||||
defaultProvider: string
|
||||
// 所有可用的搜索提供商列表
|
||||
providers: WebSearchProvider[]
|
||||
// 是否在搜索查询中添加当前日期
|
||||
searchWithTime: boolean
|
||||
// 搜索结果的最大数量
|
||||
maxResults: number
|
||||
// 要排除的域名列表
|
||||
excludeDomains: string[]
|
||||
// 是否启用搜索增强模式
|
||||
enhanceMode: boolean
|
||||
}
|
||||
|
||||
const initialState: WebSearchState = {
|
||||
@ -29,7 +37,8 @@ const initialState: WebSearchState = {
|
||||
],
|
||||
searchWithTime: true,
|
||||
maxResults: 5,
|
||||
excludeDomains: []
|
||||
excludeDomains: [],
|
||||
enhanceMode: false
|
||||
}
|
||||
|
||||
const websearchSlice = createSlice({
|
||||
@ -59,6 +68,9 @@ const websearchSlice = createSlice({
|
||||
},
|
||||
setExcludeDomains: (state, action: PayloadAction<string[]>) => {
|
||||
state.excludeDomains = action.payload
|
||||
},
|
||||
setEnhanceMode: (state, action: PayloadAction<boolean>) => {
|
||||
state.enhanceMode = action.payload
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -70,7 +82,8 @@ export const {
|
||||
setDefaultProvider,
|
||||
setSearchWithTime,
|
||||
setExcludeDomains,
|
||||
setMaxResult
|
||||
setMaxResult,
|
||||
setEnhanceMode
|
||||
} = websearchSlice.actions
|
||||
|
||||
export default websearchSlice.reducer
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user