feat: add function call model type
This commit is contained in:
parent
85160c2d29
commit
74567d5e17
@ -69,7 +69,7 @@ export default defineConfig({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
exclude: ['chunk-PZ64DZKH.js', 'chunk-JMKENWIY.js', 'chunk-UXYB6GHG.js']
|
exclude: ['chunk-PZ64DZKH.js', 'chunk-JMKENWIY.js', 'chunk-UXYB6GHG.js', 'chunk-ALDIEZMG.js']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -28,7 +28,6 @@ export default class MCPService extends EventEmitter {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.createServerLoadingPromise()
|
this.createServerLoadingPromise()
|
||||||
this.requestServers()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,19 +39,6 @@ export default class MCPService extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Request server data from renderer process Redux
|
|
||||||
*/
|
|
||||||
public requestServers(): void {
|
|
||||||
const mainWindow = windowService.getMainWindow()
|
|
||||||
if (mainWindow) {
|
|
||||||
log.info('[MCP] Requesting servers from Redux')
|
|
||||||
mainWindow.webContents.send('mcp:request-servers')
|
|
||||||
} else {
|
|
||||||
log.warn('[MCP] Main window not available, cannot request servers')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set servers received from Redux and trigger initialization if needed
|
* Set servers received from Redux and trigger initialization if needed
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const ToolsCallingIcon: FC<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElem
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Tooltip title={t('models.tool_calling')} placement="top">
|
<Tooltip title={t('models.function_calling')} placement="top">
|
||||||
<Icon {...(props as any)} />
|
<Icon {...(props as any)} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
isEmbeddingModel,
|
isEmbeddingModel,
|
||||||
|
isFunctionCallingModel,
|
||||||
isReasoningModel,
|
isReasoningModel,
|
||||||
isToolCallingModel,
|
|
||||||
isVisionModel,
|
isVisionModel,
|
||||||
isWebSearchModel
|
isWebSearchModel
|
||||||
} from '@renderer/config/models'
|
} from '@renderer/config/models'
|
||||||
@ -31,7 +31,7 @@ const ModelTags: FC<ModelTagsProps> = ({ model, showFree = true, showReasoning =
|
|||||||
{isVisionModel(model) && <VisionIcon />}
|
{isVisionModel(model) && <VisionIcon />}
|
||||||
{isWebSearchModel(model) && <WebSearchIcon />}
|
{isWebSearchModel(model) && <WebSearchIcon />}
|
||||||
{showReasoning && isReasoningModel(model) && <ReasoningIcon />}
|
{showReasoning && isReasoningModel(model) && <ReasoningIcon />}
|
||||||
{showToolsCalling && isToolCallingModel(model) && <ToolsCallingIcon />}
|
{showToolsCalling && isFunctionCallingModel(model) && <ToolsCallingIcon />}
|
||||||
{isEmbeddingModel(model) && <Tag color="orange">{t('models.embedding')}</Tag>}
|
{isEmbeddingModel(model) && <Tag color="orange">{t('models.embedding')}</Tag>}
|
||||||
{showFree && isFreeModel(model) && <Tag color="green">{t('models.free')}</Tag>}
|
{showFree && isFreeModel(model) && <Tag color="green">{t('models.free')}</Tag>}
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -178,14 +178,18 @@ export const EMBEDDING_REGEX = /(?:^text-|embed|bge-|e5-|LLM2Vec|retrieval|uae-|
|
|||||||
export const NOT_SUPPORTED_REGEX = /(?:^tts|rerank|whisper|speech)/i
|
export const NOT_SUPPORTED_REGEX = /(?:^tts|rerank|whisper|speech)/i
|
||||||
|
|
||||||
// Tool calling models
|
// Tool calling models
|
||||||
export const TOOL_CALLING_MODELS = ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-4.5', 'claude', 'qwen']
|
export const FUNCTION_CALLING_MODELS = ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-4.5', 'claude', 'qwen']
|
||||||
export const TOOL_CALLING_REGEX = new RegExp(`\\b(?:${TOOL_CALLING_MODELS.join('|')})\\b`, 'i')
|
export const FUNCTION_CALLING_REGEX = new RegExp(`\\b(?:${FUNCTION_CALLING_MODELS.join('|')})\\b`, 'i')
|
||||||
export function isToolCallingModel(model: Model): boolean {
|
export function isFunctionCallingModel(model: Model): boolean {
|
||||||
|
if (model.type?.includes('function_calling')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if (['gemini', 'deepseek', 'anthropic'].includes(model.provider)) {
|
if (['gemini', 'deepseek', 'anthropic'].includes(model.provider)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return TOOL_CALLING_REGEX.test(model.id)
|
return FUNCTION_CALLING_REGEX.test(model.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getModelLogo(modelId: string) {
|
export function getModelLogo(modelId: string) {
|
||||||
@ -1741,21 +1745,7 @@ export const SYSTEM_MODELS: Record<string, Model[]> = {
|
|||||||
group: 'Jina'
|
group: 'Jina'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
//加前缀是为了展示图标
|
xirang: [],
|
||||||
xirang: [
|
|
||||||
{
|
|
||||||
id: 'xirang-4bd107bff85941239e27b1509eccfe98',
|
|
||||||
provider: 'xirang',
|
|
||||||
name: 'DeepSeek-R1',
|
|
||||||
group: 'xirang'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'xirang-9dc913a037774fc0b248376905c85da5',
|
|
||||||
provider: 'xirang',
|
|
||||||
name: 'DeepSeek-V3',
|
|
||||||
group: 'xirang'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'tencent-cloud-ti': [
|
'tencent-cloud-ti': [
|
||||||
{
|
{
|
||||||
id: 'deepseek-r1',
|
id: 'deepseek-r1',
|
||||||
|
|||||||
@ -5,12 +5,6 @@ import { useEffect } from 'react'
|
|||||||
|
|
||||||
const ipcRenderer = window.electron.ipcRenderer
|
const ipcRenderer = window.electron.ipcRenderer
|
||||||
|
|
||||||
// Set up IPC listener for main process requests
|
|
||||||
ipcRenderer.on('mcp:request-servers', () => {
|
|
||||||
const servers = store.getState().mcp.servers
|
|
||||||
ipcRenderer.send('mcp:servers-from-renderer', servers)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Listen for server changes from main process
|
// Listen for server changes from main process
|
||||||
ipcRenderer.on('mcp:servers-changed', (_event, servers) => {
|
ipcRenderer.on('mcp:servers-changed', (_event, servers) => {
|
||||||
store.dispatch(setMCPServers(servers))
|
store.dispatch(setMCPServers(servers))
|
||||||
|
|||||||
@ -505,13 +505,14 @@
|
|||||||
"reasoning": "Reasoning",
|
"reasoning": "Reasoning",
|
||||||
"search": "Search models...",
|
"search": "Search models...",
|
||||||
"stream_output": "Stream output",
|
"stream_output": "Stream output",
|
||||||
"tool_calling": "Tool Calling",
|
"function_calling": "Function Calling",
|
||||||
"type": {
|
"type": {
|
||||||
"embedding": "Embedding",
|
"embedding": "Embedding",
|
||||||
"reasoning": "Reasoning",
|
"reasoning": "Reasoning",
|
||||||
"select": "Select Model Types",
|
"select": "Select Model Types",
|
||||||
"text": "Text",
|
"text": "Text",
|
||||||
"vision": "Vision"
|
"vision": "Vision",
|
||||||
|
"function_calling": "Function Calling"
|
||||||
},
|
},
|
||||||
"vision": "Vision",
|
"vision": "Vision",
|
||||||
"websearch": "WebSearch"
|
"websearch": "WebSearch"
|
||||||
|
|||||||
@ -505,13 +505,14 @@
|
|||||||
"reasoning": "推論",
|
"reasoning": "推論",
|
||||||
"search": "モデルを検索...",
|
"search": "モデルを検索...",
|
||||||
"stream_output": "ストリーム出力",
|
"stream_output": "ストリーム出力",
|
||||||
"tool_calling": "ツールコール",
|
"function_calling": "関数呼び出し",
|
||||||
"type": {
|
"type": {
|
||||||
"embedding": "埋め込み",
|
"embedding": "埋め込み",
|
||||||
"reasoning": "推論",
|
"reasoning": "推論",
|
||||||
"select": "モデルタイプを選択",
|
"select": "モデルタイプを選択",
|
||||||
"text": "テキスト",
|
"text": "テキスト",
|
||||||
"vision": "画像"
|
"vision": "画像",
|
||||||
|
"function_calling": "関数呼び出し"
|
||||||
},
|
},
|
||||||
"vision": "画像",
|
"vision": "画像",
|
||||||
"websearch": "ウェブ検索"
|
"websearch": "ウェブ検索"
|
||||||
|
|||||||
@ -505,13 +505,14 @@
|
|||||||
"reasoning": "Рассуждение",
|
"reasoning": "Рассуждение",
|
||||||
"search": "Поиск моделей...",
|
"search": "Поиск моделей...",
|
||||||
"stream_output": "Потоковый вывод",
|
"stream_output": "Потоковый вывод",
|
||||||
"tool_calling": "Инструмент вызова",
|
"function_calling": "Вызов функции",
|
||||||
"type": {
|
"type": {
|
||||||
"embedding": "Встраиваемые",
|
"embedding": "Встраиваемые",
|
||||||
"reasoning": "Рассуждение",
|
"reasoning": "Рассуждение",
|
||||||
"select": "Выберите тип модели",
|
"select": "Выберите тип модели",
|
||||||
"text": "Текст",
|
"text": "Текст",
|
||||||
"vision": "Изображение"
|
"vision": "Изображение",
|
||||||
|
"function_calling": "Вызов функции"
|
||||||
},
|
},
|
||||||
"vision": "Визуальные",
|
"vision": "Визуальные",
|
||||||
"websearch": "Веб-поисковые"
|
"websearch": "Веб-поисковые"
|
||||||
|
|||||||
@ -505,13 +505,14 @@
|
|||||||
"reasoning": "推理",
|
"reasoning": "推理",
|
||||||
"search": "搜索模型...",
|
"search": "搜索模型...",
|
||||||
"stream_output": "流式输出",
|
"stream_output": "流式输出",
|
||||||
"tool_calling": "工具调用",
|
"function_calling": "函数调用",
|
||||||
"type": {
|
"type": {
|
||||||
"embedding": "嵌入",
|
"embedding": "嵌入",
|
||||||
"reasoning": "推理",
|
"reasoning": "推理",
|
||||||
"select": "选择模型类型",
|
"select": "选择模型类型",
|
||||||
"text": "文本",
|
"text": "文本",
|
||||||
"vision": "图像"
|
"vision": "图像",
|
||||||
|
"function_calling": "函数调用"
|
||||||
},
|
},
|
||||||
"vision": "视觉",
|
"vision": "视觉",
|
||||||
"websearch": "联网"
|
"websearch": "联网"
|
||||||
|
|||||||
@ -505,13 +505,14 @@
|
|||||||
"reasoning": "推理",
|
"reasoning": "推理",
|
||||||
"search": "搜尋模型...",
|
"search": "搜尋模型...",
|
||||||
"stream_output": "串流輸出",
|
"stream_output": "串流輸出",
|
||||||
"tool_calling": "工具調用",
|
"function_calling": "函數調用",
|
||||||
"type": {
|
"type": {
|
||||||
"embedding": "嵌入",
|
"embedding": "嵌入",
|
||||||
"reasoning": "推理",
|
"reasoning": "推理",
|
||||||
"select": "選擇模型類型",
|
"select": "選擇模型類型",
|
||||||
"text": "文字",
|
"text": "文字",
|
||||||
"vision": "影像"
|
"vision": "影像",
|
||||||
|
"function_calling": "函數調用"
|
||||||
},
|
},
|
||||||
"vision": "視覺",
|
"vision": "視覺",
|
||||||
"websearch": "網路搜尋"
|
"websearch": "網路搜尋"
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { useKnowledgeFiles } from '@renderer/hooks/useKnowledgeFiles'
|
|||||||
import { reset } from '@renderer/services/BackupService'
|
import { reset } from '@renderer/services/BackupService'
|
||||||
import { AppInfo } from '@renderer/types'
|
import { AppInfo } from '@renderer/types'
|
||||||
import { formatFileSize } from '@renderer/utils'
|
import { formatFileSize } from '@renderer/utils'
|
||||||
import { Button, Modal, Typography } from 'antd'
|
import { Button, Typography } from 'antd'
|
||||||
import { FC, useEffect, useState } from 'react'
|
import { FC, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
@ -49,7 +49,7 @@ const DataSettings: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleClearCache = () => {
|
const handleClearCache = () => {
|
||||||
Modal.confirm({
|
window.modal.confirm({
|
||||||
title: t('settings.data.clear_cache.title'),
|
title: t('settings.data.clear_cache.title'),
|
||||||
content: t('settings.data.clear_cache.confirm'),
|
content: t('settings.data.clear_cache.confirm'),
|
||||||
okText: t('settings.data.clear_cache.button'),
|
okText: t('settings.data.clear_cache.button'),
|
||||||
@ -69,7 +69,7 @@ const DataSettings: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleRemoveAllFiles = () => {
|
const handleRemoveAllFiles = () => {
|
||||||
Modal.confirm({
|
window.modal.confirm({
|
||||||
centered: true,
|
centered: true,
|
||||||
title: t('settings.data.app_knowledge.remove_all') + ` (${formatFileSize(size)}) `,
|
title: t('settings.data.app_knowledge.remove_all') + ` (${formatFileSize(size)}) `,
|
||||||
content: t('settings.data.app_knowledge.remove_all_confirm'),
|
content: t('settings.data.app_knowledge.remove_all_confirm'),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
||||||
import { isEmbeddingModel, isReasoningModel, isVisionModel } from '@renderer/config/models'
|
import { isEmbeddingModel, isFunctionCallingModel, isReasoningModel, isVisionModel } from '@renderer/config/models'
|
||||||
import { Model, ModelType } from '@renderer/types'
|
import { Model, ModelType } from '@renderer/types'
|
||||||
import { getDefaultGroupName } from '@renderer/utils'
|
import { getDefaultGroupName } from '@renderer/utils'
|
||||||
import { Button, Checkbox, Divider, Flex, Form, Input, Modal } from 'antd'
|
import { Button, Checkbox, Divider, Flex, Form, Input, Modal } from 'antd'
|
||||||
@ -112,14 +112,15 @@ const ModelEditContent: FC<ModelEditContentProps> = ({ model, onUpdateModel, ope
|
|||||||
const defaultTypes = [
|
const defaultTypes = [
|
||||||
...(isVisionModel(model) ? ['vision'] : []),
|
...(isVisionModel(model) ? ['vision'] : []),
|
||||||
...(isEmbeddingModel(model) ? ['embedding'] : []),
|
...(isEmbeddingModel(model) ? ['embedding'] : []),
|
||||||
...(isReasoningModel(model) ? ['reasoning'] : [])
|
...(isReasoningModel(model) ? ['reasoning'] : []),
|
||||||
|
...(isFunctionCallingModel(model) ? ['tools'] : [])
|
||||||
] as ModelType[]
|
] as ModelType[]
|
||||||
|
|
||||||
// 合并现有选择和默认类型
|
// 合并现有选择和默认类型
|
||||||
const selectedTypes = [...new Set([...(model.type || []), ...defaultTypes])]
|
const selectedTypes = [...new Set([...(model.type || []), ...defaultTypes])]
|
||||||
|
|
||||||
const showTypeConfirmModal = (type: string) => {
|
const showTypeConfirmModal = (type: string) => {
|
||||||
Modal.confirm({
|
window.modal.confirm({
|
||||||
title: t('settings.moresetting.warn'),
|
title: t('settings.moresetting.warn'),
|
||||||
content: t('settings.moresetting.check.warn'),
|
content: t('settings.moresetting.check.warn'),
|
||||||
okText: t('settings.moresetting.check.confirm'),
|
okText: t('settings.moresetting.check.confirm'),
|
||||||
@ -161,6 +162,11 @@ const ModelEditContent: FC<ModelEditContentProps> = ({ model, onUpdateModel, ope
|
|||||||
label: t('models.type.reasoning'),
|
label: t('models.type.reasoning'),
|
||||||
value: 'reasoning',
|
value: 'reasoning',
|
||||||
disabled: isReasoningModel(model) && !selectedTypes.includes('reasoning')
|
disabled: isReasoningModel(model) && !selectedTypes.includes('reasoning')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('models.type.function_calling'),
|
||||||
|
value: 'function_calling',
|
||||||
|
disabled: isFunctionCallingModel(model) && !selectedTypes.includes('function_calling')
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -119,7 +119,7 @@ export type Provider = {
|
|||||||
|
|
||||||
export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'qwenlm' | 'azure-openai'
|
export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'qwenlm' | 'azure-openai'
|
||||||
|
|
||||||
export type ModelType = 'text' | 'vision' | 'embedding' | 'reasoning'
|
export type ModelType = 'text' | 'vision' | 'embedding' | 'reasoning' | 'function_calling'
|
||||||
|
|
||||||
export type Model = {
|
export type Model = {
|
||||||
id: string
|
id: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user