Skip to content

Commit 1baad66

Browse files
authored
feat: tool calling for local llm (#117) and release v0.9.0
* feat: Implement tool calling to local LLMs * Fix tool calling logic in multiple iterations loop - Prevent tool definition duplication in the system prompt during subsequent loop iterations. - Refine system prompt to enforce format more effectively. * fix(LLMService): minor fixes and code cleanup - Add invalid chat responses during ToolCalling to the chat, so it sees them in the next prompts. - Mark first message as processed after processing. - Removeunnecessary parsing methods. - Add messages about invalid formating to the promt so model sees what went wrong. - Format and clean the code. * refactor: tool code cleanup - OpenAICompatibleService and LLMService use Tool Classes Defined in the Domain. - Extract Json-Tool parse logic to helper function. * fix: minor fixes related to tool-calling * chore: bump version to 0.9.0 and update release notes
1 parent 6399106 commit 1baad66

File tree

11 files changed

+395
-52
lines changed

11 files changed

+395
-52
lines changed

Examples/Examples/Chat/ChatExampleToolsSimple.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ public class ChatExampleToolsSimple : IExample
99
public async Task Start()
1010
{
1111
OpenAiExample.Setup(); //We need to provide OpenAi API key
12-
13-
Console.WriteLine("(OpenAi) ChatExample with tools is running!");
14-
12+
13+
Console.WriteLine("(OpenAi) ChatExample with tools is running!");
14+
1515
await AIHub.Chat()
1616
.WithModel("gpt-5-nano")
1717
.WithMessage("What time is it right now?")
@@ -24,4 +24,4 @@ await AIHub.Chat()
2424
.Build())
2525
.CompleteAsync(interactive: true);
2626
}
27-
}
27+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Examples.Utils;
2+
using MaIN.Core.Hub;
3+
using MaIN.Core.Hub.Utils;
4+
5+
namespace Examples.Chat;
6+
7+
public class ChatExampleToolsSimpleLocalLLM : IExample
8+
{
9+
public async Task Start()
10+
{
11+
Console.WriteLine("Local LLM ChatExample with tools is running!");
12+
13+
await AIHub.Chat()
14+
.WithModel("gemma3:4b")
15+
.WithMessage("What time is it right now?")
16+
.WithTools(new ToolsConfigurationBuilder()
17+
.AddTool(
18+
name: "get_current_time",
19+
description: "Get the current date and time",
20+
execute: Tools.GetCurrentTime)
21+
.WithToolChoice("auto")
22+
.Build())
23+
.CompleteAsync(interactive: true);
24+
}
25+
}

Examples/Examples/Program.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static void RegisterExamples(IServiceCollection services)
5151
services.AddTransient<ChatFromExistingExample>();
5252
services.AddTransient<ChatWithReasoningExample>();
5353
services.AddTransient<ChatExampleToolsSimple>();
54+
services.AddTransient<ChatExampleToolsSimpleLocalLLM>();
5455
services.AddTransient<AgentExampleTools>();
5556
services.AddTransient<AgentExample>();
5657
services.AddTransient<AgentConversationExample>();
@@ -161,6 +162,7 @@ public class ExampleRegistry(IServiceProvider serviceProvider)
161162
("\u25a0 Chat with Files from stream", serviceProvider.GetRequiredService<ChatWithFilesFromStreamExample>()),
162163
("\u25a0 Chat with Vision", serviceProvider.GetRequiredService<ChatWithVisionExample>()),
163164
("\u25a0 Chat with Tools (simple)", serviceProvider.GetRequiredService<ChatExampleToolsSimple>()),
165+
("\u25a0 Chat with Tools (simple Local LLM)", serviceProvider.GetRequiredService<ChatExampleToolsSimpleLocalLLM>()),
164166
("\u25a0 Chat with Image Generation", serviceProvider.GetRequiredService<ChatWithImageGenExample>()),
165167
("\u25a0 Chat from Existing", serviceProvider.GetRequiredService<ChatFromExistingExample>()),
166168
("\u25a0 Chat with reasoning", serviceProvider.GetRequiredService<ChatWithReasoningExample>()),
@@ -197,4 +199,4 @@ public class ExampleRegistry(IServiceProvider serviceProvider)
197199
];
198200
}
199201
};
200-
}
202+
}

Releases/0.9.0.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 0.9.0 release
2+
3+
- Add tool calling to local models

src/MaIN.Core/.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>MaIN.NET</id>
5-
<version>0.8.1</version>
5+
<version>0.9.0</version>
66
<authors>Wisedev</authors>
77
<owners>Wisedev</owners>
88
<icon>favicon.png</icon>
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
namespace MaIN.Domain.Entities.Tools;
1+
using System.Text.Json.Serialization;
22

3-
public class FunctionCall
3+
namespace MaIN.Domain.Entities.Tools;
4+
5+
public sealed record FunctionCall
46
{
5-
public string Name { get; set; } = null!;
6-
public string Arguments { get; set; } = null!;
7-
}
7+
[JsonPropertyName("name")]
8+
public string Name { get; init; } = string.Empty;
9+
10+
[JsonPropertyName("arguments")]
11+
public string Arguments { get; init; } = "{}";
12+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace MaIN.Domain.Entities.Tools;
4+
5+
public sealed record ToolCall
6+
{
7+
[JsonPropertyName("id")]
8+
public string Id { get; init; } = string.Empty;
9+
10+
[JsonPropertyName("type")]
11+
public string Type { get; init; } = "function";
12+
13+
[JsonPropertyName("function")]
14+
public FunctionCall Function { get; init; } = new();
15+
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
namespace MaIN.Domain.Entities.Tools;
1+
using System.Text.Json.Serialization;
2+
3+
namespace MaIN.Domain.Entities.Tools;
24

35
public class ToolDefinition
46
{
57
public string Type { get; set; } = "function";
68
public FunctionDefinition? Function { get; set; }
9+
10+
[JsonIgnore]
711
public Func<string, Task<string>>? Execute { get; set; }
812
}

0 commit comments

Comments
 (0)