From afd85aabcf5d4413221d2289aca96d96c5bbe11c Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Wed, 16 Apr 2025 16:03:58 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=F0=9F=92=84=20style:=20add=20`SenseNova-?= =?UTF-8?q?V6`=20series=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/aiModels/sensenova.ts | 63 +++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/config/aiModels/sensenova.ts b/src/config/aiModels/sensenova.ts index 6b9f0d59297b6..a058f7198e419 100644 --- a/src/config/aiModels/sensenova.ts +++ b/src/config/aiModels/sensenova.ts @@ -4,6 +4,61 @@ import { AIChatModelCard } from '@/types/aiModel'; // https://www.sensecore.cn/help/docs/model-as-a-service/nova/release const sensenovaChatModels: AIChatModelCard[] = [ + { + abilities: { + vision: true, + reasoning: true, + }, + contextWindowTokens: 131_072, + description: + '兼顾视觉、语言深度推理,实现慢思考和深度推理,呈现完整的思维链过程。', + displayName: 'SenseNova V6 Reasoner', + enabled: true, + id: 'SenseNova-V6-Reasoner', + pricing: { + currency: 'CNY', + input: 4, + output: 16, + }, + releasedAt: '2025-04-14', + type: 'chat', + }, + { + abilities: { + vision: true, + }, + contextWindowTokens: 131_072, + description: + '实现图片、文本、视频能力的原生统一,突破传统多模态分立局限,在OpenCompass和SuperCLUE评测中斩获双冠军。', + displayName: 'SenseNova V6 Pro', + enabled: true, + id: 'SenseNova-V6-Pro', + pricing: { + currency: 'CNY', + input: 9, + output: 3, + }, + releasedAt: '2025-04-14', + type: 'chat', + }, + { + abilities: { + vision: true, + }, + contextWindowTokens: 131_072, + description: + '实现图片、文本、视频能力的原生统一,突破传统多模态分立局限,在多模基础能力、语言基础能力等核心维度全面领先,文理兼修,在多项测评中多次位列国内外第一梯队水平。', + displayName: 'SenseNova V6 Turbo', + enabled: true, + id: 'SenseNova-V6-Turbo', + pricing: { + currency: 'CNY', + input: 1.5, + output: 4.5, + }, + releasedAt: '2025-04-14', + type: 'chat', + }, { abilities: { functionCall: true, @@ -12,7 +67,6 @@ const sensenovaChatModels: AIChatModelCard[] = [ description: '是基于V5.5的最新版本,较上版本在中英文基础能力,聊天,理科知识, 文科知识,写作,数理逻辑,字数控制 等几个维度的表现有显著提升。', displayName: 'SenseChat 5.5 1202', - enabled: true, id: 'SenseChat-5-1202', pricing: { currency: 'CNY', @@ -30,7 +84,6 @@ const sensenovaChatModels: AIChatModelCard[] = [ description: '是最新的轻量版本模型,达到全量模型90%以上能力,显著降低推理成本。', displayName: 'SenseChat Turbo 1202', - enabled: true, id: 'SenseChat-Turbo-1202', pricing: { currency: 'CNY', @@ -48,7 +101,6 @@ const sensenovaChatModels: AIChatModelCard[] = [ description: '最新版本模型 (V5.5),128K上下文长度,在数学推理、英文对话、指令跟随以及长文本理解等领域能力显著提升,比肩GPT-4o。', displayName: 'SenseChat 5.5', - enabled: true, id: 'SenseChat-5', pricing: { currency: 'CNY', @@ -58,10 +110,12 @@ const sensenovaChatModels: AIChatModelCard[] = [ type: 'chat', }, { + abilities: { + vision: true, + }, contextWindowTokens: 32_768, description: '最新版本模型 (V5.5),支持多图的输入,全面实现模型基础能力优化,在对象属性识别、空间关系、动作事件识别、场景理解、情感识别、逻辑常识推理和文本理解生成上都实现了较大提升。', displayName: 'SenseChat 5.5 Vision', - enabled: true, id: 'SenseChat-Vision', pricing: { currency: 'CNY', @@ -78,7 +132,6 @@ const sensenovaChatModels: AIChatModelCard[] = [ contextWindowTokens: 32_768, description: '适用于快速问答、模型微调场景', displayName: 'SenseChat 5.0 Turbo', - enabled: true, id: 'SenseChat-Turbo', pricing: { currency: 'CNY', From 5613887e68e0601bf818301a0b670b1a192fa213 Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Wed, 16 Apr 2025 17:54:53 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fix=20`SenseNova-V6?= =?UTF-8?q?`=20series=20api=20calling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index e24ff58c49d47..cb8a9a5eae3c1 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -11,7 +11,7 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ baseURL: 'https://api.sensenova.cn/compatible-mode/v1', chatCompletion: { handlePayload: (payload) => { - const { frequency_penalty, temperature, top_p, ...rest } = payload; + const { frequency_penalty, messages, model, temperature, top_p, ...rest } = payload; return { ...rest, @@ -19,6 +19,20 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ frequency_penalty !== undefined && frequency_penalty > 0 && frequency_penalty <= 2 ? frequency_penalty : undefined, + messages: messages.map((message) => { + const isSenseNovaModel = model.startsWith('SenseNova-V6'); + let processedContent = message.content; + + if (isSenseNovaModel && typeof message.content === 'string') { + processedContent = [{ type: 'text', text: message.content }]; + } + + return { + ...message, + content: processedContent, + }; + }), + model, stream: true, temperature: temperature !== undefined && temperature > 0 && temperature <= 2 From 5d24a92ab087cc88d64063ceef9d631be654379d Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Wed, 16 Apr 2025 18:48:43 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=20=F0=9F=94=A8=20chore:=20rollback=20cha?= =?UTF-8?q?nges?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index cb8a9a5eae3c1..e24ff58c49d47 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -11,7 +11,7 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ baseURL: 'https://api.sensenova.cn/compatible-mode/v1', chatCompletion: { handlePayload: (payload) => { - const { frequency_penalty, messages, model, temperature, top_p, ...rest } = payload; + const { frequency_penalty, temperature, top_p, ...rest } = payload; return { ...rest, @@ -19,20 +19,6 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ frequency_penalty !== undefined && frequency_penalty > 0 && frequency_penalty <= 2 ? frequency_penalty : undefined, - messages: messages.map((message) => { - const isSenseNovaModel = model.startsWith('SenseNova-V6'); - let processedContent = message.content; - - if (isSenseNovaModel && typeof message.content === 'string') { - processedContent = [{ type: 'text', text: message.content }]; - } - - return { - ...message, - content: processedContent, - }; - }), - model, stream: true, temperature: temperature !== undefined && temperature > 0 && temperature <= 2 From 0458b63d475119a93e9f779fc93cae31dbed4030 Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Wed, 16 Apr 2025 20:10:25 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=F0=9F=92=84=20style:=20update=20model=20?= =?UTF-8?q?list=20&=20fix=20deepseek-v3=20fc=20tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/aiModels/sensenova.ts | 63 ++++++++++++++++++++++- src/libs/agent-runtime/sensenova/index.ts | 9 +++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/config/aiModels/sensenova.ts b/src/config/aiModels/sensenova.ts index a058f7198e419..4d90af817f5b2 100644 --- a/src/config/aiModels/sensenova.ts +++ b/src/config/aiModels/sensenova.ts @@ -6,8 +6,8 @@ import { AIChatModelCard } from '@/types/aiModel'; const sensenovaChatModels: AIChatModelCard[] = [ { abilities: { - vision: true, reasoning: true, + vision: true, }, contextWindowTokens: 131_072, description: @@ -213,6 +213,67 @@ const sensenovaChatModels: AIChatModelCard[] = [ }, type: 'chat', }, + { + contextWindowTokens: 32_768, + description: + 'DeepSeek-V3 是一款由深度求索公司自研的MoE模型。DeepSeek-V3 多项评测成绩超越了 Qwen2.5-72B 和 Llama-3.1-405B 等其他开源模型,并在性能上和世界顶尖的闭源模型 GPT-4o 以及 Claude-3.5-Sonnet 不分伯仲。', + displayName: 'DeepSeek V3', + id: 'DeepSeek-V3', + pricing: { + currency: 'CNY', + input: 2, + output: 8, + }, + type: 'chat', + }, + { + abilities: { + reasoning: true, + }, + contextWindowTokens: 32_768, + description: + 'DeepSeek-R1 在后训练阶段大规模使用了强化学习技术,在仅有极少标注数据的情况下,极大提升了模型推理能力。在数学、代码、自然语言推理等任务上,性能比肩 OpenAI o1 正式版。', + displayName: 'DeepSeek R1', + id: 'DeepSeek-R1', + pricing: { + currency: 'CNY', + input: 4, + output: 16, + }, + type: 'chat', + }, + { + abilities: { + reasoning: true, + }, + contextWindowTokens: 32_768, + description: + 'DeepSeek-R1-Distill 模型是在开源模型的基础上通过微调训练得到的,训练过程中使用了由 DeepSeek-R1 生成的样本数据。', + displayName: 'DeepSeek R1 Distill Qwen 14B', + id: 'DeepSeek-R1-Distill-Qwen-14B', + pricing: { + currency: 'CNY', + input: 0, + output: 0, + }, + type: 'chat', + }, + { + abilities: { + reasoning: true, + }, + contextWindowTokens: 8192, + description: + 'DeepSeek-R1-Distill 模型是在开源模型的基础上通过微调训练得到的,训练过程中使用了由 DeepSeek-R1 生成的样本数据。', + displayName: 'DeepSeek R1 Distill Qwen 32B', + id: 'DeepSeek-R1-Distill-Qwen-32B', + pricing: { + currency: 'CNY', + input: 0, + output: 0, + }, + type: 'chat', + }, ]; export const allModels = [...sensenovaChatModels]; diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index e24ff58c49d47..f80a529096bd3 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -35,12 +35,17 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels'); const functionCallKeywords = [ - 'deepseek-v3', 'sensechat-5', ]; + const visionKeywords = [ + 'vision', + 'sensenova-v6' + ]; + const reasoningKeywords = [ 'deepseek-r1' + 'sensenova-v6' ]; client.baseURL = 'https://api.sensenova.cn/v1/llm'; @@ -66,7 +71,7 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ || knownModel?.abilities?.reasoning || false, vision: - model.id.toLowerCase().includes('vision') + visionKeywords.some(keyword => model.id.toLowerCase().includes(keyword)) || knownModel?.abilities?.vision || false, }; From ed05af337bbff5d6d96128a77e307fe9b7f8d906 Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Wed, 16 Apr 2025 20:11:35 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fix=20ci=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index f80a529096bd3..9d9b715ad98ff 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -40,12 +40,12 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ const visionKeywords = [ 'vision', - 'sensenova-v6' + 'sensenova-v6', ]; const reasoningKeywords = [ - 'deepseek-r1' - 'sensenova-v6' + 'deepseek-r1', + 'sensenova-v6', ]; client.baseURL = 'https://api.sensenova.cn/v1/llm'; From 7789c2cfcceacafcf88cfb8466323c7b7f0bbb1c Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 18:34:12 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fix=20`SenseNova-V6?= =?UTF-8?q?`=20series=20calling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 42 ++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index 9d9b715ad98ff..1e27922995cbf 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -11,7 +11,7 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ baseURL: 'https://api.sensenova.cn/compatible-mode/v1', chatCompletion: { handlePayload: (payload) => { - const { frequency_penalty, temperature, top_p, ...rest } = payload; + const { frequency_penalty, messages, model, temperature, top_p, ...rest } = payload; return { ...rest, @@ -19,6 +19,46 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ frequency_penalty !== undefined && frequency_penalty > 0 && frequency_penalty <= 2 ? frequency_penalty : undefined, + messages: messages.map((message) => { + // 如果是非 V6 模型,则直接返回标准 message + if (!model.startsWith('SenseNova-V6') || message.role !== 'user') return message; + + const processContent = (content) => { + // 如果为单条 string 类 content,则格式转换为 text 类 + if (typeof content === 'string') { + return [{ type: 'text', text: content }]; + } + + // 如果内容包含图片内容,则需要对 array 类 content,进行格式转换 + return content + .map((item) => { + // 如果为 content,则格式转换为 text 类 + if (item.type === 'text') return item; + + // 如果为 image_url,则格式转换为 image_url 类 + if (item.type === 'image_url' && item.image_url?.url) { + const url = item.image_url.url; + + // 如果 image_url 为 base64 格式,则返回 image_base64 类 + return url.startsWith('data:image/jpeg;base64') + ? { + type: 'image_base64', + image_base64: url.split(',')[1] + } + : { type: 'image_url', image_url: url }; + } + + return null; + }) + .filter(Boolean); + }; + + return { + ...message, + content: processContent(message.content), + } as any; + }), + model, stream: true, temperature: temperature !== undefined && temperature > 0 && temperature <= 2 From 281dfd5744d7f4927b22f3a85259c7bb44500c80 Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 19:41:45 +0800 Subject: [PATCH 07/12] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20move=20S?= =?UTF-8?q?enseNova=20V6=20logic=20to=20`convertSenseNovaMessage`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 34 ++----------------- .../agent-runtime/utils/sensenovaHelpers.ts | 30 ++++++++++++++++ 2 files changed, 33 insertions(+), 31 deletions(-) create mode 100644 src/libs/agent-runtime/utils/sensenovaHelpers.ts diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index 1e27922995cbf..cf3fa6ba53434 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -1,6 +1,8 @@ import { ModelProvider } from '../types'; import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory'; +import { convertSenseNovaMessage } from '../utils/sensenovaHelpers'; + import type { ChatModelCard } from '@/types/llm'; export interface SenseNovaModelCard { @@ -23,39 +25,9 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ // 如果是非 V6 模型,则直接返回标准 message if (!model.startsWith('SenseNova-V6') || message.role !== 'user') return message; - const processContent = (content) => { - // 如果为单条 string 类 content,则格式转换为 text 类 - if (typeof content === 'string') { - return [{ type: 'text', text: content }]; - } - - // 如果内容包含图片内容,则需要对 array 类 content,进行格式转换 - return content - .map((item) => { - // 如果为 content,则格式转换为 text 类 - if (item.type === 'text') return item; - - // 如果为 image_url,则格式转换为 image_url 类 - if (item.type === 'image_url' && item.image_url?.url) { - const url = item.image_url.url; - - // 如果 image_url 为 base64 格式,则返回 image_base64 类 - return url.startsWith('data:image/jpeg;base64') - ? { - type: 'image_base64', - image_base64: url.split(',')[1] - } - : { type: 'image_url', image_url: url }; - } - - return null; - }) - .filter(Boolean); - }; - return { ...message, - content: processContent(message.content), + content: convertSenseNovaMessage(message.content), } as any; }), model, diff --git a/src/libs/agent-runtime/utils/sensenovaHelpers.ts b/src/libs/agent-runtime/utils/sensenovaHelpers.ts new file mode 100644 index 0000000000000..09536e32e2049 --- /dev/null +++ b/src/libs/agent-runtime/utils/sensenovaHelpers.ts @@ -0,0 +1,30 @@ +export const convertSenseNovaMessage = (content: any) => { + + // 如果为单条 string 类 content,则格式转换为 text 类 + if (typeof content === 'string') { + return [{ type: 'text', text: content }]; + } + + // 如果内容包含图片内容,则需要对 array 类 content,进行格式转换 + return content + ?.map((item: any) => { + // 如果为 content,则格式转换为 text 类 + if (item.type === 'text') return item; + + // 如果为 image_url,则格式转换为 image_url 类 + if (item.type === 'image_url' && item.image_url?.url) { + const url = item.image_url.url; + + // 如果 image_url 为 base64 格式,则返回 image_base64 类,否则返回 image_url 类 + return url.startsWith('data:image/jpeg;base64') + ? { + type: 'image_base64', + image_base64: url.split(',')[1] + } + : { type: 'image_url', image_url: url }; + } + + return null; + }) + .filter(Boolean); +}; From d92e1d4e6fc0a9e95c99357b73bd5de97d42044e Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 19:57:20 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=F0=9F=94=A8=20chore:=20add=20ci=20test?= =?UTF-8?q?=20for=20`convertSenseNovaMessage`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/sensenovaHelpers.test.ts | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/libs/agent-runtime/utils/sensenovaHelpers.test.ts diff --git a/src/libs/agent-runtime/utils/sensenovaHelpers.test.ts b/src/libs/agent-runtime/utils/sensenovaHelpers.test.ts new file mode 100644 index 0000000000000..d17c4ddd54df3 --- /dev/null +++ b/src/libs/agent-runtime/utils/sensenovaHelpers.test.ts @@ -0,0 +1,108 @@ +import { describe, expect, it } from 'vitest'; +import { convertSenseNovaMessage } from './sensenovaHelpers'; + +describe('convertSenseNovaMessage', () => { + it('should convert string content to text type array', () => { + const content = 'Hello world'; + const result = convertSenseNovaMessage(content); + + expect(result).toEqual([{ type: 'text', text: 'Hello world' }]); + }); + + it('should handle array content with text type', () => { + const content = [ + { type: 'text', text: 'Hello world' } + ]; + const result = convertSenseNovaMessage(content); + + expect(result).toEqual([{ type: 'text', text: 'Hello world' }]); + }); + + it('should convert image_url with base64 format to image_base64', () => { + const content = [ + { type: 'image_url', image_url: { url: 'data:image/jpeg;base64,ABCDEF123456' } } + ]; + const result = convertSenseNovaMessage(content); + + expect(result).toEqual([ + { type: 'image_base64', image_base64: 'ABCDEF123456' } + ]); + }); + + it('should keep image_url format for non-base64 urls', () => { + const content = [ + { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } } + ]; + const result = convertSenseNovaMessage(content); + + expect(result).toEqual([ + { type: 'image_url', image_url: 'https://example.com/image.jpg' } + ]); + }); + + it('should handle mixed content types', () => { + const content = [ + { type: 'text', text: 'Hello world' }, + { type: 'image_url', image_url: { url: 'data:image/jpeg;base64,ABCDEF123456' } }, + { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } } + ]; + const result = convertSenseNovaMessage(content); + + expect(result).toEqual([ + { type: 'text', text: 'Hello world' }, + { type: 'image_base64', image_base64: 'ABCDEF123456' }, + { type: 'image_url', image_url: 'https://example.com/image.jpg' } + ]); + }); + + it('should filter out invalid items', () => { + const content = [ + { type: 'text', text: 'Hello world' }, + { type: 'unknown', value: 'should be filtered' }, + { type: 'image_url', image_url: { notUrl: 'missing url field' } } + ]; + const result = convertSenseNovaMessage(content); + + expect(result).toEqual([ + { type: 'text', text: 'Hello world' } + ]); + }); + + it('should handle the example input format correctly', () => { + const messages = [ + { + content: [ + { + content: "Hi", + role: "user" + }, + { + image_url: { + detail: "auto", + url: "data:image/jpeg;base64,ABCDEF123456" + }, + type: "image_url" + } + ], + role: "user" + } + ]; + + // This is simulating how you might use convertSenseNovaMessage with the example input + // Note: The actual function only converts the content part, not the entire messages array + const content = messages[0].content; + + // This is how the function would be expected to handle a mixed array like this + // However, the actual test would need to be adjusted based on how your function + // is intended to handle this specific format with nested content objects + const result = convertSenseNovaMessage([ + { type: 'text', text: "Hi" }, + { type: 'image_url', image_url: { url: "data:image/jpeg;base64,ABCDEF123456" } } + ]); + + expect(result).toEqual([ + { type: 'text', text: "Hi" }, + { type: 'image_base64', image_base64: "ABCDEF123456" } + ]); + }); +}); From 4e3f8b9e07efa36cba5cd359d2cdb61ead8e146e Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 20:29:47 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=F0=9F=92=84=20style:=20fix=20`SenseNova-?= =?UTF-8?q?V6-Turbo`=20reasoning=20tag=20missing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/aiModels/sensenova.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/config/aiModels/sensenova.ts b/src/config/aiModels/sensenova.ts index 4d90af817f5b2..b1ebed6b3c5f2 100644 --- a/src/config/aiModels/sensenova.ts +++ b/src/config/aiModels/sensenova.ts @@ -25,18 +25,19 @@ const sensenovaChatModels: AIChatModelCard[] = [ }, { abilities: { + reasoning: true, vision: true, }, contextWindowTokens: 131_072, description: - '实现图片、文本、视频能力的原生统一,突破传统多模态分立局限,在OpenCompass和SuperCLUE评测中斩获双冠军。', - displayName: 'SenseNova V6 Pro', + '实现图片、文本、视频能力的原生统一,突破传统多模态分立局限,在多模基础能力、语言基础能力等核心维度全面领先,文理兼修,在多项测评中多次位列国内外第一梯队水平。', + displayName: 'SenseNova V6 Turbo', enabled: true, - id: 'SenseNova-V6-Pro', + id: 'SenseNova-V6-Turbo', pricing: { currency: 'CNY', - input: 9, - output: 3, + input: 1.5, + output: 4.5, }, releasedAt: '2025-04-14', type: 'chat', @@ -47,14 +48,14 @@ const sensenovaChatModels: AIChatModelCard[] = [ }, contextWindowTokens: 131_072, description: - '实现图片、文本、视频能力的原生统一,突破传统多模态分立局限,在多模基础能力、语言基础能力等核心维度全面领先,文理兼修,在多项测评中多次位列国内外第一梯队水平。', - displayName: 'SenseNova V6 Turbo', + '实现图片、文本、视频能力的原生统一,突破传统多模态分立局限,在OpenCompass和SuperCLUE评测中斩获双冠军。', + displayName: 'SenseNova V6 Pro', enabled: true, - id: 'SenseNova-V6-Turbo', + id: 'SenseNova-V6-Pro', pricing: { currency: 'CNY', - input: 1.5, - output: 4.5, + input: 9, + output: 3, }, releasedAt: '2025-04-14', type: 'chat', From 644b32645ea1e793873a5f170654c84bb484a37c Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 21:39:46 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fix=20`SenseChat-Vi?= =?UTF-8?q?sion`=20calling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index cf3fa6ba53434..eb02882eb7bfe 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -22,8 +22,10 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ ? frequency_penalty : undefined, messages: messages.map((message) => { - // 如果是非 V6 模型,则直接返回标准 message - if (!model.startsWith('SenseNova-V6') || message.role !== 'user') return message; + const isV6Model = model.startsWith('SenseNova-V6') && message.role === 'user'; + const isVisionModel = model.startsWith('SenseChat-Vision') && message.role === 'user'; + + if (!isV6Model && !isVisionModel) return message; return { ...message, From 13b298e45e902ddbb4bbcc37241f6b907ecc3f95 Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 22:09:02 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=F0=9F=94=A8=20chore:=20minor=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/sensenova/index.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/libs/agent-runtime/sensenova/index.ts b/src/libs/agent-runtime/sensenova/index.ts index eb02882eb7bfe..d7531c4b51184 100644 --- a/src/libs/agent-runtime/sensenova/index.ts +++ b/src/libs/agent-runtime/sensenova/index.ts @@ -21,17 +21,11 @@ export const LobeSenseNovaAI = LobeOpenAICompatibleFactory({ frequency_penalty !== undefined && frequency_penalty > 0 && frequency_penalty <= 2 ? frequency_penalty : undefined, - messages: messages.map((message) => { - const isV6Model = model.startsWith('SenseNova-V6') && message.role === 'user'; - const isVisionModel = model.startsWith('SenseChat-Vision') && message.role === 'user'; - - if (!isV6Model && !isVisionModel) return message; - - return { - ...message, - content: convertSenseNovaMessage(message.content), - } as any; - }), + messages: messages.map((message) => + message.role !== 'user' || !/^Sense(Nova-V6|Chat-Vision)/.test(model) + ? message + : { ...message, content: convertSenseNovaMessage(message.content) } + ) as any[], model, stream: true, temperature: From 0a4ba0bc222b16c38163b9bfc8b110c62de0ff28 Mon Sep 17 00:00:00 2001 From: Zhijie He Date: Thu, 17 Apr 2025 22:33:28 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=F0=9F=90=9B=20fix:=20fix=20build=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/agent-runtime/utils/sensenovaHelpers.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/agent-runtime/utils/sensenovaHelpers.ts b/src/libs/agent-runtime/utils/sensenovaHelpers.ts index 09536e32e2049..7c622940e8eac 100644 --- a/src/libs/agent-runtime/utils/sensenovaHelpers.ts +++ b/src/libs/agent-runtime/utils/sensenovaHelpers.ts @@ -2,7 +2,7 @@ export const convertSenseNovaMessage = (content: any) => { // 如果为单条 string 类 content,则格式转换为 text 类 if (typeof content === 'string') { - return [{ type: 'text', text: content }]; + return [{ text: content, type: 'text' }]; } // 如果内容包含图片内容,则需要对 array 类 content,进行格式转换 @@ -18,10 +18,10 @@ export const convertSenseNovaMessage = (content: any) => { // 如果 image_url 为 base64 格式,则返回 image_base64 类,否则返回 image_url 类 return url.startsWith('data:image/jpeg;base64') ? { - type: 'image_base64', - image_base64: url.split(',')[1] + image_base64: url.split(',')[1], + type: 'image_base64', } - : { type: 'image_url', image_url: url }; + : { image_url: url, type: 'image_url' }; } return null;