diff --git a/LlmTornado.Contrib/LlmTornado.Contrib.csproj b/LlmTornado.Contrib/LlmTornado.Contrib.csproj
index 3da2d66..f8259d1 100644
--- a/LlmTornado.Contrib/LlmTornado.Contrib.csproj
+++ b/LlmTornado.Contrib/LlmTornado.Contrib.csproj
@@ -4,10 +4,33 @@
net8.0
enable
enable
+ true
+
Contribution addon for LlmTornado
+ Matěj "lofcz" Štágl, LlmTornado Contributors
+ MIT
+ https://github.com/lofcz/LlmTornado
+ https://github.com/lofcz/LlmTornado
+ git
+ llmtornado
+ nuget_logo.jpg
+ preview
+ 1.0.1
+ Provides extra functionality to LlmTornado.
+
+
+
+
+
+
+ true
+ \
+
+
+
diff --git a/LlmTornado.Contrib/LlmTornadoExtensions.cs b/LlmTornado.Contrib/LlmTornadoExtensions.cs
new file mode 100644
index 0000000..2490e70
--- /dev/null
+++ b/LlmTornado.Contrib/LlmTornadoExtensions.cs
@@ -0,0 +1,146 @@
+using System.Collections;
+using System.Diagnostics.CodeAnalysis;
+using EnumsNET;
+using LlmTornado.ChatFunctions;
+using Newtonsoft.Json.Linq;
+
+namespace LlmTornado.Contrib;
+
+public static class LlmTornadoExtensions
+{
+ ///
+ /// Attempts to get value of a given argument. If the argument is of incompatible type, is returned.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool TryGetArgument(this FunctionCall call, string arg, [NotNullWhen(returnValue: true)] out T? data, out Exception? exception)
+ {
+ return Get(call.ArgGetter.Value.Source, arg, out data, out exception);
+ }
+
+ ///
+ /// Attempts to get value of a given argument. If the argument is not found or is of incompatible type, null is returned.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool TryGetArgument(this FunctionCall call, string arg, [NotNullWhen(returnValue: true)] out T? data)
+ {
+ return Get(call.ArgGetter.Value.Source, arg, out data, out _);
+ }
+
+ internal static bool Get(this Dictionary? args, string param, out T? data, out Exception? exception)
+ {
+ exception = null;
+
+ if (args is null)
+ {
+ data = default;
+ return false;
+ }
+
+ if (!args.TryGetValue(param, out object? rawData))
+ {
+ data = default;
+ return false;
+ }
+
+ if (rawData is T obj)
+ {
+ data = obj;
+ }
+
+ if (rawData is JArray jArr)
+ {
+ data = jArr.ToObject();
+ return true;
+ }
+
+ try
+ {
+ data = (T?)rawData.ChangeType(typeof(T));
+ return true;
+ }
+ catch (Exception e)
+ {
+ data = default;
+ exception = e;
+ return false;
+ }
+ }
+
+ public static object? ChangeType(this object? value, Type conversion)
+ {
+ Type? t = conversion;
+
+ if (t.IsEnum && value != null)
+ {
+ if (Enums.TryParse(t, value.ToString(), true, out object? x))
+ {
+ return x;
+ }
+ }
+
+ Type? nullableUnderlyingType = Nullable.GetUnderlyingType(t);
+
+ if (nullableUnderlyingType is not null && value is not null)
+ {
+ if (nullableUnderlyingType.IsEnum)
+ {
+ if (Enums.TryParse(nullableUnderlyingType, value.ToString(), true, out object? x))
+ {
+ return x;
+ }
+ }
+ }
+
+ if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ if (value == null)
+ {
+ return null;
+ }
+
+ t = Nullable.GetUnderlyingType(t);
+ }
+
+ if (t == typeof(int) && value?.ToString() == string.Empty)
+ {
+ return 0;
+ }
+
+ if (t == typeof(int) && ((value?.ToString()?.Contains('.') ?? false) || (value?.ToString()?.Contains(',') ?? false)))
+ {
+ if (double.TryParse(value.ToString()?.Replace(",", "."), out double x))
+ {
+ return (int)x;
+ }
+ }
+
+ if (value is not null && t is { IsGenericType: true } && value.GetType().IsGenericType)
+ {
+ Type destT = t.GetGenericArguments()[0];
+ Type sourceT = value.GetType().GetGenericArguments()[0];
+
+ if (destT.IsEnum && sourceT == typeof(int))
+ {
+ IList? instance = (IList?)Activator.CreateInstance(t);
+
+ foreach (object? x in (IList)value)
+ {
+ instance?.Add(x);
+ }
+
+ return instance;
+ }
+ }
+
+ return t is not null ? Convert.ChangeType(value, t) : null;
+ }
+}
\ No newline at end of file
diff --git a/LlmTornado.Contrib/nuget_logo.jpg b/LlmTornado.Contrib/nuget_logo.jpg
new file mode 100644
index 0000000..3f55109
Binary files /dev/null and b/LlmTornado.Contrib/nuget_logo.jpg differ
diff --git a/LlmTornado.Demo/ChatDemo.cs b/LlmTornado.Demo/ChatDemo.cs
index 1d0360c..a8e4a9d 100644
--- a/LlmTornado.Demo/ChatDemo.cs
+++ b/LlmTornado.Demo/ChatDemo.cs
@@ -8,6 +8,7 @@
using LlmTornado.Code;
using LlmTornado.Code.Models;
using LlmTornado.Common;
+using LlmTornado.Contrib;
namespace LlmTornado.Demo;
diff --git a/LlmTornado.Demo/LlmTornado.Demo.csproj b/LlmTornado.Demo/LlmTornado.Demo.csproj
index c6453ab..415a655 100644
--- a/LlmTornado.Demo/LlmTornado.Demo.csproj
+++ b/LlmTornado.Demo/LlmTornado.Demo.csproj
@@ -8,6 +8,7 @@
+
diff --git a/LlmTornado/Chat/FunctionCall.cs b/LlmTornado/Chat/FunctionCall.cs
index c8d7d1d..cb75fe0 100644
--- a/LlmTornado/Chat/FunctionCall.cs
+++ b/LlmTornado/Chat/FunctionCall.cs
@@ -12,16 +12,25 @@ namespace LlmTornado.ChatFunctions;
///
public class FunctionCall
{
+ ///
+ /// Arguments.
+ ///
[JsonIgnore]
- private readonly Lazy argGetter;
+ internal readonly Lazy ArgGetter;
+ ///
+ /// Decoded arguments.
+ ///
[JsonIgnore]
- private readonly Lazy?> decodedArguments;
+ internal readonly Lazy?> DecodedArguments;
+ ///
+ /// Creates an empty function call.
+ ///
public FunctionCall()
{
- argGetter = new Lazy(() => new ChatFunctionParamsGetter(decodedArguments?.Value));
- decodedArguments = new Lazy?>(() => Arguments.IsNullOrWhiteSpace() ? [] : JsonConvert.DeserializeObject>(Arguments));
+ ArgGetter = new Lazy(() => new ChatFunctionParamsGetter(DecodedArguments?.Value));
+ DecodedArguments = new Lazy?>(() => Arguments.IsNullOrWhiteSpace() ? [] : JsonConvert.DeserializeObject>(Arguments));
}
[JsonIgnore]
@@ -57,32 +66,7 @@ public FunctionCall()
///
public Dictionary GetArguments()
{
- return argGetter.Value.Source ?? [];
- }
-
- ///
- /// Attempts to get value of a given argument. If the argument is of incompatible type, is returned.
- ///
- ///
- ///
- ///
- ///
- ///
- public bool TryGetArgument(string param, [NotNullWhen(returnValue: true)] out T? data, out Exception? exception)
- {
- return argGetter.Value.Get(param, out data, out exception);
- }
-
- ///
- /// Attempts to get value of a given argument. If the argument is not found or is of incompatible type, null is returned.
- ///
- ///
- ///
- ///
- ///
- public bool TryGetArgument(string param, [NotNullWhen(returnValue: true)] out T? data)
- {
- return argGetter.Value.Get(param, out data, out _);
+ return ArgGetter.Value.Source ?? [];
}
///
diff --git a/LlmTornado/Chat/Plugins/ChatPluginFunctionInputParams.cs b/LlmTornado/Chat/Plugins/ChatPluginFunctionInputParams.cs
index bd6ae3f..b4f21c4 100644
--- a/LlmTornado/Chat/Plugins/ChatPluginFunctionInputParams.cs
+++ b/LlmTornado/Chat/Plugins/ChatPluginFunctionInputParams.cs
@@ -5,52 +5,22 @@
namespace LlmTornado.Chat.Plugins;
+///
+/// Input params of a function call.
+///
public class ChatPluginFunctionInputParams
{
- private readonly Dictionary? source;
-
+ ///
+ /// Source dictionary.
+ ///
+ public Dictionary? Source { get; set; }
+
+ ///
+ /// Creates an input params from a dictionary.
+ ///
+ ///
public ChatPluginFunctionInputParams(Dictionary? pars)
{
- source = pars;
- }
-
- public bool Get(string param, out T? data, out Exception? exception)
- {
- exception = null;
-
- if (source == null)
- {
- data = default;
- return false;
- }
-
- if (!source.TryGetValue(param, out object? rawData))
- {
- data = default;
- return false;
- }
-
- if (rawData is T obj)
- {
- data = obj;
- }
-
- if (rawData is JArray jArr)
- {
- data = jArr.ToObject();
- return true;
- }
-
- try
- {
- data = (T?)rawData.ChangeType(typeof(T));
- return true;
- }
- catch (Exception e)
- {
- data = default;
- exception = e;
- return false;
- }
+ Source = pars;
}
}
\ No newline at end of file
diff --git a/LlmTornado/Code/Extensions.cs b/LlmTornado/Code/Extensions.cs
index 7a627f3..9568fff 100644
--- a/LlmTornado/Code/Extensions.cs
+++ b/LlmTornado/Code/Extensions.cs
@@ -1,12 +1,8 @@
-using System;
-using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
-using System.Linq;
using System.Reflection;
-using EnumsNET;
using Newtonsoft.Json;
namespace LlmTornado.Code;
@@ -59,75 +55,6 @@ public static void AddOrUpdate(this ConcurrentDictionary diction
return dictionary;
}
- public static object? ChangeType(this object? value, Type conversion)
- {
- Type? t = conversion;
-
- if (t.IsEnum && value != null)
- {
- if (Enums.TryParse(t, value.ToString(), true, out object? x))
- {
- return x;
- }
- }
-
- Type? nullableUnderlyingType = Nullable.GetUnderlyingType(t);
-
- if (nullableUnderlyingType is not null && value is not null)
- {
- if (nullableUnderlyingType.IsEnum && value != null)
- {
- if (Enums.TryParse(nullableUnderlyingType, value.ToString(), true, out object? x))
- {
- return x;
- }
- }
- }
-
- if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
- {
- if (value == null)
- {
- return null;
- }
-
- t = Nullable.GetUnderlyingType(t);
- }
-
- if (t == typeof(int) && value?.ToString() == "")
- {
- return 0;
- }
-
- if (t == typeof(int) && ((value?.ToString()?.Contains('.') ?? false) || (value?.ToString()?.Contains(',') ?? false)))
- {
- if (double.TryParse(value.ToString()?.Replace(",", "."), out double x))
- {
- return (int)x;
- }
- }
-
- if (value != null && t is { IsGenericType: true } && value.GetType().IsGenericType)
- {
- Type destT = t.GetGenericArguments()[0];
- Type sourceT = value.GetType().GetGenericArguments()[0];
-
- if (destT.IsEnum && sourceT == typeof(int))
- {
- IList? instance = (IList?)Activator.CreateInstance(t);
-
- foreach (object? x in (IList)value)
- {
- instance?.Add(x);
- }
-
- return instance;
- }
- }
-
- return t != null ? System.Convert.ChangeType(value, t) : null;
- }
-
private static readonly JsonSerializerSettings JsonSettingsIgnoreNulls = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
public static string ToJson(this object? obj, bool prettify = false)
diff --git a/LlmTornado/Code/PartialModels.cs b/LlmTornado/Code/PartialModels.cs
index a96a964..fc71304 100644
--- a/LlmTornado/Code/PartialModels.cs
+++ b/LlmTornado/Code/PartialModels.cs
@@ -123,46 +123,6 @@ public ChatFunctionParamsGetter(Dictionary? pars)
{
Source = pars;
}
-
- public bool Get(string param, [NotNullWhen(returnValue: true)] out T? data, out Exception? exception)
- {
- exception = null;
-
- if (Source is null)
- {
- data = default;
- return false;
- }
-
- if (!Source.TryGetValue(param, out object? rawData))
- {
- data = default;
- return false;
- }
-
- if (rawData is T obj)
- {
- data = obj;
- }
-
- if (rawData is JArray jArr)
- {
- data = jArr.ToObject();
- return true;
- }
-
- try
- {
- data = (T?)rawData.ChangeType(typeof(T));
- return true;
- }
- catch (Exception e)
- {
- data = default;
- exception = e;
- return false;
- }
- }
}
internal class ToolCallInboundAccumulator
diff --git a/LlmTornado/LlmTornado.csproj b/LlmTornado/LlmTornado.csproj
index f5b1228..811096d 100644
--- a/LlmTornado/LlmTornado.csproj
+++ b/LlmTornado/LlmTornado.csproj
@@ -1,6 +1,6 @@
- latestmajor
+ preview
true
Matěj Štágl, LlmTornado contributors
LlmTornado
@@ -13,7 +13,7 @@
OpenAI NextGeneration
safe apis: include content of the request
LlmTornado
- 3.1.25
+ 3.1.26
3.0.5
3.0.5
True
@@ -41,12 +41,15 @@
-
-
-
+
+
+
+ <_Parameter1>LlmTornado.Contrib
+
+