-
Hi, I'm using this library together with vllm, which has an OpenAI-compatible server together with Mistral Small. Until now, everything worked great. Today, I tried tool calling on the ChatEndpoint, but instead of the tools being called, I got the following text output: Input:
I know, this is probably out of scope for this library. Maybe you can help me to identify the problem. To ReproduceThis is the code I'm using. I'm using var tools = new List<Tool>
{
Tool.GetOrCreateTool(typeof(WeatherService), nameof(WeatherService.GetCurrentWeatherAsync))
};
var chatRequest = new ChatRequest(_messages, tools, "auto", Model.Id);
var sequence = 0L;
var response = await Api.ChatEndpoint.StreamCompletionAsync(chatRequest, async chatStreamingResponse =>
{
if (Streaming != null)
{
var delta = chatStreamingResponse.FirstChoice?.Delta?.Content;
if (delta != null && delta.Length > 0)
{
await Streaming.Invoke(sequence, delta, streamingData, this);
++sequence;
}
}
}, false, _tokenSource.Token); Expected behaviorThe tools should be called. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 8 replies
-
Not a bug since I don't officially support VLLM, but I do use it. Xfering this to Discussions. I do use VLLM, but have not attempted to do function calling. |
Beta Was this translation helpful? Give feedback.
-
Hi and thanks for your answer. And thanks for all the work you put in this library, it's awesome :) I can understand that you don't want to support anything else except the official OpenAI server. Anyway, I have no problem to work around this limitation. I wrote some test code and it's working fine. Basically, I check if the response starts with [TOOLS_CALL] and handle it differently. Here's the current code I'm using: if (isToolCalls)
{
string content = choice.Message.Content;
var toolCalls = content.Split("[TOOL_CALLS]", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
foreach (var toolCall in toolCalls)
{
var jsonIdx = toolCall.IndexOf('{');
var call = toolCall.Substring(0, jsonIdx);
var callParts = call.Split('_');
var json = toolCall.Substring(jsonIdx + 1);
var toolFunctionName = callParts[0];
var toolCallId = callParts[1];
var r = new Random();
var a = r.Next(10, 40);
var b = r.Next(40, 80);
_messages.Add(new Message(toolCallId, toolFunctionName, new List<Content> { $"The Temperator is between {a} and {b} degree." }));
}
return await SendMessage(null, null, streamingData);
} You see, I have the json string, the toolFunctionName and the toolCallId. I'm just returning a static tool call message instead of calling the tool directly. And this code works. And now, here's my question: The code to get the function and call it with the right parameters from the json array is probably already somewhere in the code. Is there a way to use it? Something like: |
Beta Was this translation helpful? Give feedback.
-
I have another question: How can I call a tool with a custom parameter? Just a stupid example: [Function("Get the current temperature for the current user location.")]
public static Task<string> GetCurrentWeatherAsync(Context context, [FunctionParameter("The units the user has requested temperature in. Typically this is based on the users location.")] WeatherUnit unit)
{
var userid = context.userid;
var userlocation = whatever.getlocation(userid)
return temp.bylocation(userlocation, unit)
} var functionResult = await toolCall.InvokeFunctionAsync(userContext); Real world use: In the tool function, I need to be able to identify the user or send something over the connected websocket to the client, independent from the output. |
Beta Was this translation helpful? Give feedback.
Sorry, I'm not using docker.
Anyway, with this pending PR: vllm-project/vllm#19425, everything is working now. It's a rework of the tool parsing for Mistral models and now it's compatible with this library 👍 Sorry for the hassle.