diff --git a/src/renderer/src/assets/json/chat-models.json b/src/renderer/src/assets/json/chat-models.json
index 6ca8fcf..822ef41 100644
--- a/src/renderer/src/assets/json/chat-models.json
+++ b/src/renderer/src/assets/json/chat-models.json
@@ -84,8 +84,18 @@
],
"Tiangong": [{ "name": "SkyChat-MegaVerse", "value": "SkyChat-MegaVerse", "type": "text" }],
"MoonshotAI": [
- { "name": "moonshot-v1-128k", "value": "moonshot-v1-128k", "type": "text" },
- { "name": "moonshot-v1-32k", "value": "moonshot-v1-32k", "type": "text" },
- { "name": "moonshot-v1-8k", "value": "moonshot-v1-8k", "type": "text" }
+ {
+ "name": "moonshot-v1-128k",
+ "value": "moonshot-v1-128k",
+ "type": "text",
+ "isSupportPlugin": true
+ },
+ {
+ "name": "moonshot-v1-32k",
+ "value": "moonshot-v1-32k",
+ "type": "text",
+ "isSupportPlugin": true
+ },
+ { "name": "moonshot-v1-8k", "value": "moonshot-v1-8k", "type": "text", "isSupportPlugin": true }
]
}
diff --git a/src/renderer/src/assets/json/drawing-models.json b/src/renderer/src/assets/json/drawing-models.json
index d153620..129a340 100644
--- a/src/renderer/src/assets/json/drawing-models.json
+++ b/src/renderer/src/assets/json/drawing-models.json
@@ -5,5 +5,6 @@
],
"Tongyi": [{ "name": "wanx-v1", "value": "wanx-v1" }],
"ERNIE": [{ "name": "stable-diffusion-xl", "value": "sd_xl" }],
- "Spark": [{ "name": "tti-v2.1", "value": "tti-v2.1" }]
+ "Spark": [{ "name": "tti-v2.1", "value": "tti-v2.1" }],
+ "ZhipuAI": [{ "name": "cogview-3", "value": "cogview-3" }]
}
diff --git a/src/renderer/src/components/views/ai-calendar/AICalendar.vue b/src/renderer/src/components/views/ai-calendar/AICalendar.vue
index f7a729d..3a741fe 100644
--- a/src/renderer/src/components/views/ai-calendar/AICalendar.vue
+++ b/src/renderer/src/components/views/ai-calendar/AICalendar.vue
@@ -225,12 +225,7 @@ const generateReport = async () => {
}
// 各家大模型特有选项
- // 各家大模型特有选项
- const otherOption = settingStore.getBigModelConfig(
- settingStore.aiCalendar.bigModel.provider,
- null,
- null
- )
+ const otherOption = settingStore.getBigModelConfig(settingStore.aiCalendar.bigModel.provider)
// 大模型能力调用
await chat2bigModel(settingStore.aiCalendar.bigModel.provider, {
diff --git a/src/renderer/src/components/views/ai-drawing/AIDrawing.vue b/src/renderer/src/components/views/ai-drawing/AIDrawing.vue
index d93d463..b0b9c08 100644
--- a/src/renderer/src/components/views/ai-drawing/AIDrawing.vue
+++ b/src/renderer/src/components/views/ai-drawing/AIDrawing.vue
@@ -54,30 +54,7 @@ const newDrawingTask = () => {
// 开始生成
const startGenerate = () => {
// 检查大模型配置
- let configErrorFlag = false
- switch (drawingStore.getCurrentTask.provider) {
- case 'OpenAI':
- if (!settingStore.openAI.baseUrl || !settingStore.openAI.key) {
- configErrorFlag = true
- }
- break
- case 'Tongyi':
- if (!settingStore.tongyi.apiKey) {
- configErrorFlag = true
- }
- break
- case 'ERNIE':
- if (!settingStore.ernie.apiKey || !settingStore.ernie.secretKey) {
- configErrorFlag = true
- }
- break
- case 'Spark':
- if (!settingStore.spark.appId || !settingStore.spark.secret || !settingStore.spark.key) {
- configErrorFlag = true
- }
- break
- }
- if (configErrorFlag) {
+ if (settingStore.checkBigModelConfig(drawingStore.getCurrentTask.provider)) {
Modal.confirm({
title: t('common.configError'),
content: t(`chatWindow.configMiss.${drawingStore.getCurrentTask.provider}`),
@@ -127,34 +104,9 @@ const startGenerate = () => {
},
abortCtr: abortCtr
}
+
// 各家大模型特有选项
- let otherOption = {}
- switch (drawingStore.getCurrentTask.provider) {
- case 'OpenAI':
- otherOption = {
- apiKey: settingStore.openAI.key,
- baseURL: settingStore.openAI.baseUrl
- }
- break
- case 'Tongyi':
- otherOption = {
- apiKey: settingStore.tongyi.apiKey
- }
- break
- case 'ERNIE':
- otherOption = {
- apiKey: settingStore.ernie.apiKey,
- secretKey: settingStore.ernie.secretKey
- }
- break
- case 'Spark':
- otherOption = {
- appId: settingStore.spark.appId,
- secretKey: settingStore.spark.secret,
- apiKey: settingStore.spark.key
- }
- break
- }
+ const otherOption = settingStore.getBigModelConfig(drawingStore.getCurrentTask.provider)
// 调用能力
drawingByBigModel(drawingStore.getCurrentTask.provider, {
diff --git a/src/renderer/src/components/views/ai-drawing/AIDrawingConsole.vue b/src/renderer/src/components/views/ai-drawing/AIDrawingConsole.vue
index d9f5b6d..b270201 100644
--- a/src/renderer/src/components/views/ai-drawing/AIDrawingConsole.vue
+++ b/src/renderer/src/components/views/ai-drawing/AIDrawingConsole.vue
@@ -11,19 +11,8 @@ watch(
() => drawingStore.getCurrentTask.provider,
(value) => {
drawingStore.getCurrentTask.options = {}
- switch (value) {
- case 'OpenAI':
- drawingStore.getCurrentTask.model = 'dall-e-3'
- break
- case 'Spark':
- drawingStore.getCurrentTask.model = 'tti-v2.1'
- break
- case 'Tongyi':
- drawingStore.getCurrentTask.model = 'wanx-v1'
- break
- case 'ERNIE':
- drawingStore.getCurrentTask.model = 'sd_xl'
- break
+ if (drawingModels[value]) {
+ drawingStore.getCurrentTask.model = drawingModels[value][0].name
}
}
)
@@ -85,7 +74,11 @@ watch(
-
+
256x256
diff --git a/src/renderer/src/components/views/chat2assistant/chat-window/ChatWindow.vue b/src/renderer/src/components/views/chat2assistant/chat-window/ChatWindow.vue
index b20ab05..4c07e1a 100644
--- a/src/renderer/src/components/views/chat2assistant/chat-window/ChatWindow.vue
+++ b/src/renderer/src/components/views/chat2assistant/chat-window/ChatWindow.vue
@@ -284,6 +284,8 @@ const useBigModel = async () => {
maxTokens: data.currentAssistant.maxTokens,
contextSize: data.currentAssistant.contextSize,
messages: copyObj(bigModelMessageList),
+ abortCtr: abortCtr,
+ chatPlugins: chatPluginStore.getPluginListByIds(data.currentAssistant.chatPluginIdList, true),
startAnswer: (sessionId: string, content?: string) => {
if (data.currentSessionId != sessionId) {
return
@@ -324,11 +326,7 @@ const useBigModel = async () => {
}
// 各家大模型特有选项
- const otherOption = settingStore.getBigModelConfig(
- data.currentAssistant.provider,
- abortCtr,
- chatPluginStore.getPluginListByIds(data.currentAssistant.chatPluginIdList)
- )
+ const otherOption = settingStore.getBigModelConfig(data.currentAssistant.provider)
// 大模型能力调用
await chat2bigModel(data.currentAssistant.provider, {
diff --git a/src/renderer/src/env.d.ts b/src/renderer/src/env.d.ts
index f9908bb..29e9945 100644
--- a/src/renderer/src/env.d.ts
+++ b/src/renderer/src/env.d.ts
@@ -33,7 +33,7 @@ type BigModelProvider =
| 'Spark'
| 'Tiangong'
| 'MoonshotAI'
-type AIDrawingProvider = 'OpenAI' | 'Tongyi' | 'ERNIE' | 'Spark'
+type AIDrawingProvider = 'OpenAI' | 'ZhipuAI' | 'Tongyi' | 'ERNIE' | 'Spark'
type AIAudioProvider = 'OpenAI'
type TranslatorProvider = 'youdao' | 'baiduTranslation'
type AssistantType = 'chat'
diff --git a/src/renderer/src/store/chat-plugin.ts b/src/renderer/src/store/chat-plugin.ts
index 28ae83d..dfb6a12 100644
--- a/src/renderer/src/store/chat-plugin.ts
+++ b/src/renderer/src/store/chat-plugin.ts
@@ -33,11 +33,21 @@ export const useChatPluginStore = defineStore({
}
return importFlag
},
- getPluginListByIds(ids: string[]): ChatPlugin[] {
+ getPluginListByIds(ids: string[], newId?: boolean): ChatPlugin[] {
if (!ids || ids.length === 0) {
return []
}
- return copyObj(this.chatPluginList.filter((p) => ids.includes(p.id)))
+
+ const pluginList = copyObj(this.chatPluginList.filter((p) => ids.includes(p.id)))
+
+ if (newId) {
+ // 重新设置插件id
+ for (let i = 0; i < pluginList.length; i++) {
+ pluginList[i].id = `plugin_${i}`
+ }
+ }
+
+ return pluginList
}
},
persist: {
diff --git a/src/renderer/src/store/setting.ts b/src/renderer/src/store/setting.ts
index 60f56bc..5b36a28 100644
--- a/src/renderer/src/store/setting.ts
+++ b/src/renderer/src/store/setting.ts
@@ -195,18 +195,13 @@ export const useSettingStore = defineStore({
}
return configErrorFlag
},
- getBigModelConfig(
- provider: BigModelProvider,
- abortCtr: AbortController | null,
- chatPlugins: ChatPlugin[] | null
- ) {
+ getBigModelConfig(provider: BigModelProvider) {
let otherOption = {}
switch (provider) {
case 'OpenAI':
otherOption = {
apiKey: this.openAI.key,
- baseURL: this.openAI.baseUrl,
- chatPlugins
+ baseURL: this.openAI.baseUrl
}
break
case 'Ollama':
@@ -217,15 +212,12 @@ export const useSettingStore = defineStore({
case 'Gemini':
otherOption = {
apiKey: this.gemini.key,
- baseURL: this.gemini.baseUrl,
- abortCtr
+ baseURL: this.gemini.baseUrl
}
break
case 'ZhipuAI':
otherOption = {
- apiKey: this.zhipuAI.apiKey,
- abortCtr,
- chatPlugins
+ apiKey: this.zhipuAI.apiKey
}
break
case 'Spark':
@@ -238,15 +230,12 @@ export const useSettingStore = defineStore({
case 'ERNIE':
otherOption = {
apiKey: this.ernie.apiKey,
- secretKey: this.ernie.secretKey,
- abortCtr
+ secretKey: this.ernie.secretKey
}
break
case 'Tongyi':
otherOption = {
- apiKey: this.tongyi.apiKey,
- chatPlugins,
- abortCtr
+ apiKey: this.tongyi.apiKey
}
break
case 'Tiangong':
diff --git a/src/renderer/src/utils/big-model/index.ts b/src/renderer/src/utils/big-model/index.ts
index b4d8b24..445616c 100644
--- a/src/renderer/src/utils/big-model/index.ts
+++ b/src/renderer/src/utils/big-model/index.ts
@@ -6,7 +6,7 @@ import { chat2openai, drawingByOpenAI, speechByOpenAI } from '@renderer/utils/bi
import { chat2spark, drawingBySpark } from '@renderer/utils/big-model/spark-util'
import { chat2tiangong } from '@renderer/utils/big-model/tiangong-util'
import { chat2tongyi, drawingByTongyi } from '@renderer/utils/big-model/tongyi-util'
-import { chat2zhipu } from '@renderer/utils/big-model/zhipu-util'
+import { chat2zhipu, drawingByZhipu } from '@renderer/utils/big-model/zhipu-util'
type ChatFunctionMap = {
[provider in BigModelProvider]: (option: CommonChatOption) => Promise
@@ -83,6 +83,7 @@ const chatFunctionMap: ChatFunctionMap = {
const drawingFunctionMap: DrawingFunctionMap = {
OpenAI: drawingByOpenAI,
+ ZhipuAI: drawingByZhipu,
Tongyi: drawingByTongyi,
ERNIE: drawingByERNIE,
Spark: drawingBySpark
diff --git a/src/renderer/src/utils/big-model/moonshot-util.ts b/src/renderer/src/utils/big-model/moonshot-util.ts
index 0e9a838..f70925b 100644
--- a/src/renderer/src/utils/big-model/moonshot-util.ts
+++ b/src/renderer/src/utils/big-model/moonshot-util.ts
@@ -1,8 +1,12 @@
import { CommonChatOption } from '.'
import { limitContext, turnChat } from '@renderer/utils/big-model/base-util'
+import { executeJavaScript, readLocalImageBase64 } from '@renderer/utils/ipc-util'
import { Logger } from '@renderer/utils/logger'
import OpenAI from 'openai'
import { ChatCompletionMessageParam } from 'openai/resources/chat'
+import { ChatCompletion } from 'openai/src/resources/chat/completions'
+
+const baseURL = 'https://api.moonshot.cn/v1'
export const chat2moonshot = async (option: CommonChatOption) => {
const {
@@ -14,6 +18,7 @@ export const chat2moonshot = async (option: CommonChatOption) => {
maxTokens,
messages,
sessionId,
+ chatPlugins,
startAnswer,
appendAnswer,
end
@@ -22,18 +27,74 @@ export const chat2moonshot = async (option: CommonChatOption) => {
// OpenAI实例
const openai = new OpenAI({
apiKey,
- baseURL: 'https://api.moonshot.cn/v1',
+ baseURL,
dangerouslyAllowBrowser: true
})
+ // 是否有插件
+ let pluginAnswer: ChatCompletion | null = null
+ if (chatPlugins && chatPlugins.length > 0) {
+ // 非流式插件提问
+ pluginAnswer = await openai.chat.completions.create({
+ messages: (await getMoonshotMessages(
+ messages!,
+ instruction,
+ inputMaxTokens,
+ contextSize
+ )) as ChatCompletionMessageParam[],
+ tools: chatPlugins.map((p) => {
+ return {
+ type: p.type,
+ function: {
+ name: p.id,
+ description: p.description,
+ parameters: {
+ type: 'object',
+ properties: p.parameters.reduce((acc, param) => {
+ acc[param.name] = {
+ type: param.type,
+ description: param.description
+ }
+ return acc
+ }, {}),
+ required: p.parameters.map((param) => param.name)
+ }
+ }
+ }
+ }),
+ model,
+ stream: false,
+ max_tokens: maxTokens
+ })
+ }
+
// 现有消息列表
- const chatMessages = (await getMoonshotAIMessages(
+ const chatMessages = (await getMoonshotMessages(
messages!,
instruction,
inputMaxTokens,
contextSize
)) as ChatCompletionMessageParam[]
+ // 是否有插件
+ if (chatPlugins && pluginAnswer && pluginAnswer.choices[0].message.tool_calls) {
+ // 插件运行
+ const tool_call_id = pluginAnswer.choices[0].message.tool_calls[0].id
+ const pluginId = pluginAnswer.choices[0].message.tool_calls[0].function.name
+ const pluginParams = pluginAnswer.choices[0].message.tool_calls[0].function.arguments
+ const pluginResult = await executeJavaScript(
+ `var params = ${pluginParams};${chatPlugins.find((p) => p.id === pluginId)?.code}`
+ )
+ Logger.info('chat2moonshot pluginResult: ', pluginResult)
+ // 插件回复
+ chatMessages.push(pluginAnswer.choices[0].message)
+ chatMessages.push({
+ role: 'tool',
+ tool_call_id: tool_call_id,
+ content: pluginResult
+ })
+ }
+
// 流式对话
const stream = await openai.chat.completions.create({
messages: chatMessages,
@@ -55,7 +116,7 @@ export const chat2moonshot = async (option: CommonChatOption) => {
end && end(sessionId)
}
-export const getMoonshotAIMessages = async (
+export const getMoonshotMessages = async (
chatMessageList: ChatMessage[],
instruction: string,
inputMaxTokens: number | undefined,
@@ -75,5 +136,32 @@ export const getMoonshotAIMessages = async (
})
}
- return messages
+ // 转换消息结构
+ const openaiMessages: ChatCompletionMessageParam[] = []
+ for (const m of messages) {
+ // 处理用户消息中的图片
+ if (m.image && m.role === 'user') {
+ const imageBase64Data = await readLocalImageBase64(m.image)
+ openaiMessages.push({
+ role: 'user',
+ content: [
+ { type: 'text', text: m.content },
+ {
+ type: 'image_url',
+ image_url: {
+ // 这里和 OpenAI 不一样,不需要前缀
+ url: imageBase64Data
+ }
+ }
+ ]
+ })
+ } else {
+ openaiMessages.push({
+ role: m.role,
+ content: m.content
+ } as ChatCompletionMessageParam)
+ }
+ }
+
+ return openaiMessages
}
diff --git a/src/renderer/src/utils/big-model/openai-util.ts b/src/renderer/src/utils/big-model/openai-util.ts
index 9d9487c..a9e5d71 100644
--- a/src/renderer/src/utils/big-model/openai-util.ts
+++ b/src/renderer/src/utils/big-model/openai-util.ts
@@ -202,7 +202,7 @@ export const drawingByOpenAI = async (option: CommonDrawingOption) => {
style: style as 'vivid' | 'natural' | null,
n: n
})
- Logger.info('chat2openai:', imagesResponse)
+ Logger.info('drawingByOpenAI:', imagesResponse)
// 获取图片地址
const imageUrls: string[] = []
diff --git a/src/renderer/src/utils/big-model/zhipu-util.ts b/src/renderer/src/utils/big-model/zhipu-util.ts
index 8856983..888de06 100644
--- a/src/renderer/src/utils/big-model/zhipu-util.ts
+++ b/src/renderer/src/utils/big-model/zhipu-util.ts
@@ -1,11 +1,19 @@
-import { CommonChatOption } from '.'
+import { CommonChatOption, CommonDrawingOption } from '.'
import { limitContext, turnChat } from '@renderer/utils/big-model/base-util'
-import { executeJavaScript, readLocalImageBase64 } from '@renderer/utils/ipc-util'
+import { randomUUID } from '@renderer/utils/id-util'
+import {
+ executeJavaScript,
+ readLocalImageBase64,
+ saveFileByBase64,
+ saveFileByUrl
+} from '@renderer/utils/ipc-util'
import { Logger } from '@renderer/utils/logger'
import OpenAI from 'openai'
import { ChatCompletionMessageParam } from 'openai/resources/chat'
import { ChatCompletion } from 'openai/src/resources/chat/completions'
+const baseURL = 'https://open.bigmodel.cn/api/paas/v4/'
+
export const chat2zhipu = async (option: CommonChatOption) => {
const {
model,
@@ -25,7 +33,7 @@ export const chat2zhipu = async (option: CommonChatOption) => {
// OpenAI实例
const openai = new OpenAI({
apiKey,
- baseURL: 'https://open.bigmodel.cn/api/paas/v4/',
+ baseURL,
dangerouslyAllowBrowser: true
})
@@ -163,3 +171,46 @@ export const getZhipuMessages = async (
return openaiMessages
}
+
+export const drawingByZhipu = async (option: CommonDrawingOption) => {
+ const { apiKey, sessionId, prompt, model, imageGenerated, end } = option
+
+ // OpenAI实例
+ const openai = new OpenAI({
+ apiKey,
+ baseURL,
+ dangerouslyAllowBrowser: true
+ })
+
+ // OpenAI 绘画
+ try {
+ const imagesResponse = await openai.images.generate({
+ prompt: prompt!,
+ model
+ })
+
+ Logger.info('drawingByZhipu:', imagesResponse)
+
+ // 获取图片地址
+ const imageUrls: string[] = []
+ if (imagesResponse.data) {
+ // 保存图片
+ for (const imgData of imagesResponse.data) {
+ if (imgData.url) {
+ imageUrls.push(await saveFileByUrl(imgData.url, `${randomUUID()}.png`))
+ } else if (imgData.b64_json) {
+ imageUrls.push(await saveFileByBase64(imgData.b64_json, `${randomUUID()}.png`))
+ }
+ }
+ }
+
+ // 返回图片本地地址
+ imageGenerated && imageGenerated(sessionId, imageUrls)
+
+ // 结束
+ end && end(sessionId)
+ } catch (e: any) {
+ Logger.error('drawingByZhipu error:', e.message)
+ end && end(sessionId, e.message)
+ }
+}