From a823d6e2eab24e775f8db8c90af9a24f23618afb Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 4 Feb 2025 17:01:00 -0800 Subject: [PATCH] Added deepseek-v3 function calling --- providers/deepseek/index.ts | 128 ++++++++++++++++++++++++++++++++++++ providers/service.ts | 4 +- providers/types.ts | 2 +- 3 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 providers/deepseek/index.ts diff --git a/providers/deepseek/index.ts b/providers/deepseek/index.ts new file mode 100644 index 0000000000..d18e20d024 --- /dev/null +++ b/providers/deepseek/index.ts @@ -0,0 +1,128 @@ +import { ProviderConfig, FunctionCallResponse, ProviderToolConfig, ProviderRequest } from '../types' + +export const deepseekProvider: ProviderConfig = { + id: 'deepseek', + name: 'Deepseek', + description: "Deepseek's chat models", + version: '1.0.0', + models: ['deepseek-chat'], + defaultModel: 'deepseek-chat', + + baseUrl: 'https://api.deepseek.com/v1/chat/completions', + headers: (apiKey: string) => ({ + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }), + + transformToolsToFunctions: (tools: ProviderToolConfig[]) => { + if (!tools || tools.length === 0) { + return undefined + } + + return tools.map(tool => ({ + type: 'function', + function: { + name: tool.id, + description: tool.description, + parameters: tool.parameters + } + })) + }, + + transformFunctionCallResponse: (response: any, tools?: ProviderToolConfig[]): FunctionCallResponse => { + const toolCall = response.choices?.[0]?.message?.tool_calls?.[0] + if (!toolCall || !toolCall.function) { + throw new Error('No valid tool call found in response') + } + + const tool = tools?.find(t => t.id === toolCall.function.name) + if (!tool) { + throw new Error(`Tool not found: ${toolCall.function.name}`) + } + + let args = toolCall.function.arguments + if (typeof args === 'string') { + try { + args = JSON.parse(args) + } catch (e) { + console.error('Failed to parse tool arguments:', e) + args = {} + } + } + + return { + name: toolCall.function.name, + arguments: { + ...tool.params, + ...args + } + } + }, + + transformRequest: (request: ProviderRequest, functions?: any) => { + // Transform messages from internal format to Deepseek format + const messages = (request.messages || []).map(msg => { + if (msg.role === 'function') { + return { + role: 'tool', + content: msg.content, + tool_call_id: msg.name + } + } + + if (msg.function_call) { + return { + role: 'assistant', + content: null, + tool_calls: [{ + id: msg.function_call.name, + type: 'function', + function: { + name: msg.function_call.name, + arguments: msg.function_call.arguments + } + }] + } + } + + return msg + }) + + const payload = { + model: 'deepseek-chat', + messages: [ + { role: 'system', content: request.systemPrompt }, + ...(request.context ? [{ role: 'user', content: request.context }] : []), + ...messages + ], + temperature: request.temperature || 0.7, + max_tokens: request.maxTokens || 1024, + ...(functions && { tools: functions }) + } + + return payload + }, + + transformResponse: (response: any) => { + if (!response) { + console.warn('Received undefined response from Deepseek API') + return { content: '' } + } + + const output = response.choices?.[0]?.message + + return { + content: output?.content || '', + tokens: response.usage && { + prompt: response.usage.prompt_tokens, + completion: response.usage.completion_tokens, + total: response.usage.total_tokens + } + } + }, + + hasFunctionCall: (response: any) => { + if (!response) return false + return !!response.choices?.[0]?.message?.tool_calls?.[0] + } +} \ No newline at end of file diff --git a/providers/service.ts b/providers/service.ts index f81e114f03..afd02bb1d1 100644 --- a/providers/service.ts +++ b/providers/service.ts @@ -3,12 +3,14 @@ import { openaiProvider } from './openai' import { anthropicProvider } from './anthropic' import { googleProvider } from './google' import { getTool, executeTool } from '@/tools' +import { deepseekProvider } from './deepseek' // Register providers const providers: Record = { openai: openaiProvider, anthropic: anthropicProvider, - google: googleProvider + google: googleProvider, + deepseek: deepseekProvider } export async function executeProviderRequest( diff --git a/providers/types.ts b/providers/types.ts index 6483a53398..a65509b5ae 100644 --- a/providers/types.ts +++ b/providers/types.ts @@ -68,7 +68,7 @@ export interface ProviderToolConfig { } export interface Message { - role: 'system' | 'user' | 'assistant' | 'function' + role: 'system' | 'user' | 'assistant' | 'function' | 'tool' content: string | null name?: string function_call?: {