Function calling for Claude and OpenRouter

This commit is contained in:
Cohee 2024-05-29 00:56:55 +03:00
parent 865c48bcc0
commit 309eb80748
3 changed files with 31 additions and 4 deletions

View File

@ -1739,7 +1739,7 @@
</span>
</div>
</div>
<div class="range-block" data-source="openai,cohere,mistralai,custom">
<div class="range-block" data-source="openai,cohere,mistralai,custom,claude,openrouter">
<label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand">
<input id="openai_function_calling" type="checkbox" />
<span data-i18n="Enable function calling">Enable function calling</span>

View File

@ -1968,7 +1968,7 @@ async function registerFunctionTools(type, data) {
}
async function checkFunctionToolCalls(data) {
if ([chat_completion_sources.OPENAI, chat_completion_sources.CUSTOM, chat_completion_sources.MISTRALAI].includes(oai_settings.chat_completion_source)) {
if ([chat_completion_sources.OPENAI, chat_completion_sources.CUSTOM, chat_completion_sources.MISTRALAI, chat_completion_sources.OPENROUTER].includes(oai_settings.chat_completion_source)) {
if (!Array.isArray(data?.choices)) {
return;
}
@ -1999,6 +1999,21 @@ async function checkFunctionToolCalls(data) {
}
}
if ([chat_completion_sources.CLAUDE].includes(oai_settings.chat_completion_source)) {
if (!Array.isArray(data?.content)) {
return;
}
for (const content of data.content) {
if (content.type === 'tool_use') {
/** @type {FunctionToolCall} */
const args = { name: content.name, arguments: JSON.stringify(content.input) };
await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);
data.allowEmptyResponse = true;
}
}
}
if ([chat_completion_sources.COHERE].includes(oai_settings.chat_completion_source)) {
if (!Array.isArray(data?.tool_calls)) {
return;
@ -2028,6 +2043,8 @@ export function isFunctionCallingSupported() {
chat_completion_sources.COHERE,
chat_completion_sources.CUSTOM,
chat_completion_sources.MISTRALAI,
chat_completion_sources.CLAUDE,
chat_completion_sources.OPENROUTER,
];
return supportedSources.includes(oai_settings.chat_completion_source);
}

View File

@ -115,6 +115,7 @@ async function sendClaudeRequest(request, response) {
request.socket.on('close', function () {
controller.abort();
});
const additionalHeaders = {};
let use_system_prompt = (request.body.model.startsWith('claude-2') || request.body.model.startsWith('claude-3')) && request.body.claude_use_sysprompt;
let converted_prompt = convertClaudeMessages(request.body.messages, request.body.assistant_prefill, use_system_prompt, request.body.human_sysprompt_message, request.body.char_name, request.body.user_name);
// Add custom stop sequences
@ -136,6 +137,14 @@ async function sendClaudeRequest(request, response) {
if (use_system_prompt) {
requestBody.system = converted_prompt.systemPrompt;
}
if (Array.isArray(request.body.tools) && request.body.tools.length > 0) {
additionalHeaders['anthropic-beta'] = 'tools-2024-05-16';
requestBody.tool_choice = { type: request.body.tool_choice === 'required' ? 'any' : 'auto' };
requestBody.tools = request.body.tools
.filter(tool => tool.type === 'function')
.map(tool => tool.function)
.map(fn => ({ name: fn.name, description: fn.description, input_schema: fn.parameters }));
}
console.log('Claude request:', requestBody);
const generateResponse = await fetch(apiUrl + '/messages', {
@ -146,6 +155,7 @@ async function sendClaudeRequest(request, response) {
'Content-Type': 'application/json',
'anthropic-version': '2023-06-01',
'x-api-key': apiKey,
...additionalHeaders,
},
timeout: 0,
});
@ -163,8 +173,8 @@ async function sendClaudeRequest(request, response) {
const responseText = generateResponseJson.content[0].text;
console.log('Claude response:', generateResponseJson);
// Wrap it back to OAI format
const reply = { choices: [{ 'message': { 'content': responseText } }] };
// Wrap it back to OAI format + save the original content
const reply = { choices: [{ 'message': { 'content': responseText } }], content: generateResponseJson.content };
return response.send(reply);
}
} catch (error) {