/** * Agnes AI Provider Adapter * * OpenAI 兼容 API,免费使用。 * 支持 Tool Calling、Thinking 模式、512K 上下文、多模态(图片 base64)。 * * 差异于 DeepSeek: * - Thinking 模式使用 chat_template_kwargs(非 thinking 字段) * - 图片使用 base64 格式(与 Ollama 一致,通过 images 字段传递) * - 512K 上下文,65.5K 最大输出 * * @see apis/agnes-ai-api-docs-20260625.html */ import { DeepSeekAdapter } from './deepseek.adapter'; import type { MetonaRequest } from '../types'; export class AgnesAdapter extends DeepSeekAdapter { override readonly provider: string = 'agnes'; readonly supportedModels = ['agnes-2.0-flash']; readonly supportsToolCalling = true; readonly supportsThinking = true; /** * 覆盖原生请求构建 * * 差异: * 1. Thinking 模式使用 chat_template_kwargs * 2. 图片使用 OpenAI 多模态 content 数组格式 */ protected override toNativeRequest(request: MetonaRequest): Record { const base = super.toNativeRequest(request) as Record; // Agnes Thinking 模式:使用 chat_template_kwargs if (request.params?.thinkingEnabled) { delete base.thinking; delete base.reasoning_effort; base.chat_template_kwargs = { enable_thinking: true }; } // Agnes 默认 max_tokens 更大 if (!request.params.maxTokens) { base.max_tokens = 65536; } // 图片处理:将 images 转为 OpenAI 多模态 content 数组格式 const messages = base.messages as Array>; for (let i = 0; i < messages.length; i++) { const msg = messages[i]; // 找到对应的原始消息(跳过 system 消息) const origMsg = request.messages.filter((m) => m.role !== 'system')[i]; if (!origMsg?.images || origMsg.images.length === 0) continue; // 将 content 转为数组格式:[{type: "text", text: ...}, {type: "image_url", ...}] const contentParts: Array> = []; if (msg.content && typeof msg.content === 'string') { contentParts.push({ type: 'text', text: msg.content }); } for (const img of origMsg.images) { contentParts.push({ type: 'image_url', image_url: { url: img.url, detail: img.detail ?? 'auto' }, }); } msg.content = contentParts; } return base; } }