fix: 从共享工具中移除图片处理,DeepSeek 不应接收图片
问题:shared/openai-format.ts 对所有 OpenAI 兼容 Adapter 统一处理 多模态图片 → content 数组。但 DeepSeek 不支持多模态,不应发送图片。 修复: - shared/openai-format.ts: 移除图片处理逻辑(由各 Provider 自行决定) - AgnesAdapter.toNativeRequest: 添加多模态图片转换(OpenAI content 数组) - DeepSeekAdapter: 不处理图片(DeepSeek 不支持多模态) - OllamaAdapter: 已有独立的图片处理(images: [base64] 数组) 各 Provider 多模态支持: DeepSeek ❌ 不支持 → 不发送 images 字段 Agnes AI ✅ 支持 → OpenAI content 数组 [{type:image_url}] Ollama ✅ 支持 → images: [base64]
This commit is contained in:
@@ -98,6 +98,7 @@ export class AgnesAdapter extends BaseAdapter {
|
|||||||
* 构建 Agnes AI 原生请求体
|
* 构建 Agnes AI 原生请求体
|
||||||
*
|
*
|
||||||
* Agnes AI 特有参数:
|
* Agnes AI 特有参数:
|
||||||
|
* - 多模态图片:user 消息的 images[] → OpenAI content 数组 [{type:"text"}, {type:"image_url"}]
|
||||||
* - chat_template_kwargs: { enable_thinking: true } — 启用思考模式(非 thinking 字段)
|
* - chat_template_kwargs: { enable_thinking: true } — 启用思考模式(非 thinking 字段)
|
||||||
* - 默认 max_tokens: 65536(512K 上下文)
|
* - 默认 max_tokens: 65536(512K 上下文)
|
||||||
*/
|
*/
|
||||||
@@ -105,6 +106,28 @@ export class AgnesAdapter extends BaseAdapter {
|
|||||||
const messages = buildOpenAICompatibleMessages(request);
|
const messages = buildOpenAICompatibleMessages(request);
|
||||||
const tools = buildOpenAICompatibleTools(request.tools);
|
const tools = buildOpenAICompatibleTools(request.tools);
|
||||||
|
|
||||||
|
// === Agnes 多模态:将 images 转为 OpenAI content 数组 ===
|
||||||
|
// buildOpenAICompatibleMessages 不处理图片(各 Provider 自行处理)
|
||||||
|
const nonSystemMsgs = request.messages.filter((m) => m.role !== 'system');
|
||||||
|
for (let i = 0; i < messages.length; i++) {
|
||||||
|
// messages[0] 是 system,非 system 消息从 messages[1] 开始
|
||||||
|
if (i === 0) continue;
|
||||||
|
const origMsg = nonSystemMsgs[i - 1];
|
||||||
|
if (!origMsg?.images?.length) continue;
|
||||||
|
|
||||||
|
const contentParts: Array<Record<string, unknown>> = [];
|
||||||
|
if (origMsg.content) {
|
||||||
|
contentParts.push({ type: 'text', text: origMsg.content });
|
||||||
|
}
|
||||||
|
for (const img of origMsg.images) {
|
||||||
|
contentParts.push({
|
||||||
|
type: 'image_url',
|
||||||
|
image_url: { url: img.url, detail: img.detail ?? 'auto' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
messages[i].content = contentParts;
|
||||||
|
}
|
||||||
|
|
||||||
const body: Record<string, unknown> = {
|
const body: Record<string, unknown> = {
|
||||||
model: this.config.defaultModel,
|
model: this.config.defaultModel,
|
||||||
messages,
|
messages,
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ import type { MetonaRequest, MetonaToolDef } from '../../types';
|
|||||||
*
|
*
|
||||||
* 处理:
|
* 处理:
|
||||||
* - System Prompt 拼接(静态区 + 动态区 + 安全准则)
|
* - System Prompt 拼接(静态区 + 动态区 + 安全准则)
|
||||||
* - 图片 → 多模态 content 数组 [{type:"text"}, {type:"image_url"}]
|
|
||||||
* - 工具调用历史保留(reasoning_content + tool_calls)
|
* - 工具调用历史保留(reasoning_content + tool_calls)
|
||||||
* - 工具结果注入(tool_call_id + content)
|
* - 工具结果注入(tool_call_id + content)
|
||||||
|
*
|
||||||
|
* 注意:图片(多模态)处理不属于此共享函数。
|
||||||
|
* 各 Provider 对多模态的支持不同(DeepSeek 不支持,Agnes/Ollama 支持但格式各异),
|
||||||
|
* 应在各自 Adapter 的 toNativeRequest 中处理。
|
||||||
*/
|
*/
|
||||||
export function buildOpenAICompatibleMessages(
|
export function buildOpenAICompatibleMessages(
|
||||||
request: MetonaRequest,
|
request: MetonaRequest,
|
||||||
@@ -35,24 +38,7 @@ export function buildOpenAICompatibleMessages(
|
|||||||
const nonSystemMessages = request.messages
|
const nonSystemMessages = request.messages
|
||||||
.filter((m) => m.role !== 'system')
|
.filter((m) => m.role !== 'system')
|
||||||
.map((m) => {
|
.map((m) => {
|
||||||
const msg: Record<string, unknown> = { role: m.role };
|
const msg: Record<string, unknown> = { role: m.role, content: m.content };
|
||||||
|
|
||||||
// === 多模态图片处理 ===
|
|
||||||
if (m.images && m.images.length > 0) {
|
|
||||||
const contentParts: Array<Record<string, unknown>> = [];
|
|
||||||
if (m.content) {
|
|
||||||
contentParts.push({ type: 'text', text: m.content });
|
|
||||||
}
|
|
||||||
for (const img of m.images) {
|
|
||||||
contentParts.push({
|
|
||||||
type: 'image_url',
|
|
||||||
image_url: { url: img.url, detail: img.detail ?? 'auto' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
msg.content = contentParts;
|
|
||||||
} else {
|
|
||||||
msg.content = m.content;
|
|
||||||
}
|
|
||||||
|
|
||||||
// === Assistant 工具调用历史 ===
|
// === Assistant 工具调用历史 ===
|
||||||
if (m.role === 'assistant' && m.toolCalls?.length) {
|
if (m.role === 'assistant' && m.toolCalls?.length) {
|
||||||
|
|||||||
Reference in New Issue
Block a user