fix: 对照 API 文档修复 3 个 Adapter 的 8 个实现差异
通过逐接口对比 DeepSeek/AgnesAI/Ollama 官方文档与实现代码,发现并修复:
DeepSeek (4 fix):
- temperature 默认值: 错误发送 0(API默认=1),改为 undefined 让 API 用默认值
- thinking 禁用: API 默认 enabled,不传=开启。改为显式发送 {type:disabled}
- reasoning_effort: 补充 xhigh→max 映射(文档规定)
- stream 请求: 补充 AbortSignal.timeout 超时控制
Agnes AI (2 fix):
- temperature 默认值: 同上
- 图片 image_url: 移除文档未提及的 detail 字段
Ollama (3 fix):
- temperature 默认值: 同上(Ollama默认≈0.8)
- tool_calls arguments: 从对象改为 JSON 字符串(REST API 要求)
- finishReason: 使用 done_reason 字段正确映射(之前始终返回 STOP)
This commit is contained in:
@@ -122,7 +122,7 @@ export class AgnesAdapter extends BaseAdapter {
|
|||||||
for (const img of origMsg.images) {
|
for (const img of origMsg.images) {
|
||||||
contentParts.push({
|
contentParts.push({
|
||||||
type: 'image_url',
|
type: 'image_url',
|
||||||
image_url: { url: img.url, detail: img.detail ?? 'auto' },
|
image_url: { url: img.url },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
messages[i].content = contentParts;
|
messages[i].content = contentParts;
|
||||||
@@ -131,7 +131,7 @@ export class AgnesAdapter extends BaseAdapter {
|
|||||||
const body: Record<string, unknown> = {
|
const body: Record<string, unknown> = {
|
||||||
model: this.config.defaultModel,
|
model: this.config.defaultModel,
|
||||||
messages,
|
messages,
|
||||||
temperature: request.params.temperature ?? 0,
|
temperature: request.params.temperature,
|
||||||
max_tokens: request.params.maxTokens ?? 65536,
|
max_tokens: request.params.maxTokens ?? 65536,
|
||||||
stream,
|
stream,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ export class DeepSeekAdapter extends BaseAdapter {
|
|||||||
...this.config.headers,
|
...this.config.headers,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
signal: AbortSignal.timeout(this.config.timeoutMs ?? 300_000),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok || !response.body) {
|
if (!response.ok || !response.body) {
|
||||||
@@ -150,7 +151,7 @@ export class DeepSeekAdapter extends BaseAdapter {
|
|||||||
const body: Record<string, unknown> = {
|
const body: Record<string, unknown> = {
|
||||||
model: this.config.defaultModel,
|
model: this.config.defaultModel,
|
||||||
messages,
|
messages,
|
||||||
temperature: request.params.temperature ?? 0,
|
temperature: request.params.temperature,
|
||||||
max_tokens: request.params.maxTokens,
|
max_tokens: request.params.maxTokens,
|
||||||
stream,
|
stream,
|
||||||
};
|
};
|
||||||
@@ -164,10 +165,13 @@ export class DeepSeekAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Thinking 模式
|
// Thinking 模式
|
||||||
if (request.params.thinkingEnabled) {
|
// API 默认 thinking.type = "enabled",必须显式发送 disabled 才能关闭
|
||||||
|
if (request.params.thinkingEnabled === false) {
|
||||||
|
body.thinking = { type: 'disabled' };
|
||||||
|
} else if (request.params.thinkingEnabled) {
|
||||||
body.thinking = { type: 'enabled' };
|
body.thinking = { type: 'enabled' };
|
||||||
const effortMap: Record<string, string> = {
|
const effortMap: Record<string, string> = {
|
||||||
low: 'high', medium: 'high', high: 'high', max: 'max',
|
low: 'high', medium: 'high', high: 'high', xhigh: 'max', max: 'max',
|
||||||
};
|
};
|
||||||
body.reasoning_effort = effortMap[request.params.thinkingEffort ?? 'high'] ?? 'high';
|
body.reasoning_effort = effortMap[request.params.thinkingEffort ?? 'high'] ?? 'high';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,10 +370,10 @@ export class OllamaAdapter extends BaseAdapter {
|
|||||||
? m.toolResult.result
|
? m.toolResult.result
|
||||||
: JSON.stringify(m.toolResult.result);
|
: JSON.stringify(m.toolResult.result);
|
||||||
}
|
}
|
||||||
// assistant 工具调用
|
// assistant 工具调用(Ollama REST API 要求 arguments 为 JSON 字符串)
|
||||||
if (m.role === 'assistant' && m.toolCalls?.length) {
|
if (m.role === 'assistant' && m.toolCalls?.length) {
|
||||||
msg.tool_calls = m.toolCalls.map((tc) => ({
|
msg.tool_calls = m.toolCalls.map((tc) => ({
|
||||||
function: { name: tc.name, arguments: tc.args },
|
function: { name: tc.name, arguments: JSON.stringify(tc.args) },
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return msg;
|
return msg;
|
||||||
@@ -384,7 +384,7 @@ export class OllamaAdapter extends BaseAdapter {
|
|||||||
model: this.config.defaultModel,
|
model: this.config.defaultModel,
|
||||||
messages,
|
messages,
|
||||||
options: {
|
options: {
|
||||||
temperature: request.params.temperature ?? 0,
|
temperature: request.params.temperature,
|
||||||
num_predict: request.params.maxTokens,
|
num_predict: request.params.maxTokens,
|
||||||
top_p: request.params.topP,
|
top_p: request.params.topP,
|
||||||
stop: request.params.stopSequences,
|
stop: request.params.stopSequences,
|
||||||
@@ -448,7 +448,26 @@ export class OllamaAdapter extends BaseAdapter {
|
|||||||
outputTokens: (data.eval_count as number) ?? 0,
|
outputTokens: (data.eval_count as number) ?? 0,
|
||||||
totalTokens: ((data.prompt_eval_count as number) ?? 0) + ((data.eval_count as number) ?? 0),
|
totalTokens: ((data.prompt_eval_count as number) ?? 0) + ((data.eval_count as number) ?? 0),
|
||||||
},
|
},
|
||||||
finishReason: data.done ? MetonaFinishReason.STOP : MetonaFinishReason.LENGTH,
|
finishReason: mapOllamaDoneReason(data.done_reason as string | undefined, !!message?.tool_calls),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射 Ollama done_reason → MetonaFinishReason
|
||||||
|
*
|
||||||
|
* @see apis/ollama-api-docs-20260518.html — /api/chat 响应字段
|
||||||
|
*/
|
||||||
|
function mapOllamaDoneReason(
|
||||||
|
reason: string | undefined,
|
||||||
|
hasToolCalls: boolean,
|
||||||
|
): MetonaFinishReason {
|
||||||
|
if (hasToolCalls) return MetonaFinishReason.TOOL_CALLS;
|
||||||
|
switch (reason) {
|
||||||
|
case 'stop': return MetonaFinishReason.STOP;
|
||||||
|
case 'length': return MetonaFinishReason.LENGTH;
|
||||||
|
case 'load': return MetonaFinishReason.ERROR;
|
||||||
|
case 'unload': return MetonaFinishReason.ERROR;
|
||||||
|
default: return MetonaFinishReason.STOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user