Added tool calling support (#731)

Co-authored-by: krut_ni <nils.kruthoff@dlr.de>
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-09-04 15:48:07 +02:00
1 parent b00c3f9ab3
commit 4d8d30e15e
266 files changed
+11186 -740

No files matched your search

@@ -0,0 +1,3 @@
namespace AIStudio.Provider.SelfHosted;
public readonly record struct Model(string Id, string? Object, string? OwnedBy, ModelArchitecture? Architecture);
@@ -0,0 +1,3 @@
namespace AIStudio.Provider.SelfHosted;
public readonly record struct ModelArchitecture(string[]? InputModalities, string[]? OutputModalities);
@@ -1,7 +1,3 @@
namespace AIStudio.Provider.SelfHosted;
public readonly record struct ModelsResponse(string? Object, Model[]? Data);
public readonly record struct Model(string Id, string? Object, string? OwnedBy, ModelArchitecture? Architecture);
public readonly record struct ModelArchitecture(string[]? InputModalities, string[]? OutputModalities);
public readonly record struct ModelsResponse(string? Object, Model[]? Data);
@@ -35,7 +35,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
effectiveChatModel,
chatThread,
settingsManager,
async (systemPrompt, apiParameters) =>
async (systemPrompt, apiParameters, tools) =>
{
// Build the list of messages. The image format depends on the host:
// - Ollama uses the direct image URL format: { "type": "image_url", "image_url": "data:..." }
@@ -57,6 +57,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
// Right now, we only support streaming completions:
Stream = true,
Tools = tools,
AdditionalApiParameters = apiParameters
};
},
@@ -95,12 +96,12 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
switch (host)
{
case Host.LLAMA_CPP:
return await this.LoadLlamaCppTextModels(["embed"], [], token, apiKeyProvisional);
return await this.LoadLlamaCppTextModels(["embed"], [], apiKeyProvisional, token);
case Host.LM_STUDIO:
case Host.OLLAMA:
case Host.VLLM:
return await this.LoadModels( SecretStoreType.LLM_PROVIDER, ["embed"], [], token, apiKeyProvisional);
return await this.LoadModels( SecretStoreType.LLM_PROVIDER, ["embed"], [], apiKeyProvisional, token);
}
return ModelLoadResult.FromModels([]);
@@ -127,7 +128,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
case Host.LM_STUDIO:
case Host.OLLAMA:
case Host.VLLM:
return await this.LoadModels( SecretStoreType.EMBEDDING_PROVIDER, [], ["embed"], token, apiKeyProvisional);
return await this.LoadModels( SecretStoreType.EMBEDDING_PROVIDER, [], ["embed"], apiKeyProvisional, token);
}
return ModelLoadResult.FromModels([]);
@@ -154,7 +155,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
case Host.OLLAMA:
case Host.VLLM:
return await this.LoadModels(SecretStoreType.TRANSCRIPTION_PROVIDER, [], [], token, apiKeyProvisional);
return await this.LoadModels(SecretStoreType.TRANSCRIPTION_PROVIDER, [], [], apiKeyProvisional, token);
default:
return ModelLoadResult.FromModels([]);
@@ -169,7 +170,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
#endregion
private async Task<ModelLoadResult> LoadModels(SecretStoreType storeType, string[] ignorePhrases, string[] filterPhrases, CancellationToken token, string? apiKeyProvisional = null)
private async Task<ModelLoadResult> LoadModels(SecretStoreType storeType, string[] ignorePhrases, string[] filterPhrases, string? apiKeyProvisional, CancellationToken token)
{
var secretKey = await this.GetModelLoadingSecretKey(storeType, apiKeyProvisional, true);
@@ -202,13 +203,12 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
return FailedModelLoadResult(ModelLoadFailureReason.PROVIDER_UNAVAILABLE, e.Message);
}
}
private async Task<Provider.Model> ResolveChatModelForRequest(Provider.Model chatModel, CancellationToken token)
{
if (host is not Host.LLAMA_CPP || !chatModel.IsSystemModel)
return chatModel;
var modelLoadResult = await this.LoadLlamaCppTextModels(["embed"], [], token);
var modelLoadResult = await this.LoadLlamaCppTextModels(["embed"], [], null, token);
if (!modelLoadResult.Success)
return chatModel;
@@ -245,7 +245,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
return chatModel;
}
private async Task<ModelLoadResult> LoadLlamaCppTextModels(string[] ignorePhrases, string[] filterPhrases, CancellationToken token, string? apiKeyProvisional = null)
private async Task<ModelLoadResult> LoadLlamaCppTextModels(string[] ignorePhrases, string[] filterPhrases, string? apiKeyProvisional, CancellationToken token)
{
var secretKey = await this.GetModelLoadingSecretKey(SecretStoreType.LLM_PROVIDER, apiKeyProvisional, true);
@@ -325,4 +325,4 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
{
return ModelLoadResult.FromModels([ AIStudio.Provider.Model.SYSTEM_MODEL ]);
}
}
}