Skip to content

Commit

Permalink
refactor core to remove enums.net dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
lofcz committed Nov 22, 2024
1 parent f56e02e commit d6edf5b
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 191 deletions.
23 changes: 23 additions & 0 deletions LlmTornado.Contrib/LlmTornado.Contrib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,33 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>Contribution addon for LlmTornado</Title>
<Authors>Matěj "lofcz" Štágl, LlmTornado Contributors</Authors>
<Copyright>MIT</Copyright>
<PackageProjectUrl>https://github.com/lofcz/LlmTornado</PackageProjectUrl>
<RepositoryUrl>https://github.com/lofcz/LlmTornado</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>llmtornado</PackageTags>
<PackageIcon>nuget_logo.jpg</PackageIcon>
<LangVersion>preview</LangVersion>
<Version>1.0.1</Version>
<Description>Provides extra functionality to LlmTornado.</Description>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\LlmTornado\LlmTornado.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Enums.NET" Version="[5.0.0, )" />
</ItemGroup>

<ItemGroup>
<None Update="nuget_logo.jpg">
<Pack>true</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

</Project>
146 changes: 146 additions & 0 deletions LlmTornado.Contrib/LlmTornadoExtensions.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Attempts to get value of a given argument. If the argument is of incompatible type, <see cref="exception"/> is returned.
/// </summary>
/// <param name="call"></param>
/// <param name="arg"></param>
/// <param name="data"></param>
/// <param name="exception"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static bool TryGetArgument<T>(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);
}

/// <summary>
/// Attempts to get value of a given argument. If the argument is not found or is of incompatible type, null is returned.
/// </summary>
/// <param name="call"></param>
/// <param name="arg"></param>
/// <param name="data"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static bool TryGetArgument<T>(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<T>(this Dictionary<string,object?>? 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<T?>();
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;
}
}
Binary file added LlmTornado.Contrib/nuget_logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions LlmTornado.Demo/ChatDemo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using LlmTornado.Code;
using LlmTornado.Code.Models;
using LlmTornado.Common;
using LlmTornado.Contrib;

namespace LlmTornado.Demo;

Expand Down
1 change: 1 addition & 0 deletions LlmTornado.Demo/LlmTornado.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\LlmTornado.Contrib\LlmTornado.Contrib.csproj" />
<ProjectReference Include="..\LlmTornado\LlmTornado.csproj" />
</ItemGroup>

Expand Down
44 changes: 14 additions & 30 deletions LlmTornado/Chat/FunctionCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,25 @@ namespace LlmTornado.ChatFunctions;
/// </summary>
public class FunctionCall
{
/// <summary>
/// Arguments.
/// </summary>
[JsonIgnore]
private readonly Lazy<ChatFunctionParamsGetter> argGetter;
internal readonly Lazy<ChatFunctionParamsGetter> ArgGetter;

/// <summary>
/// Decoded arguments.
/// </summary>
[JsonIgnore]
private readonly Lazy<Dictionary<string, object?>?> decodedArguments;
internal readonly Lazy<Dictionary<string, object?>?> DecodedArguments;

/// <summary>
/// Creates an empty function call.
/// </summary>
public FunctionCall()
{
argGetter = new Lazy<ChatFunctionParamsGetter>(() => new ChatFunctionParamsGetter(decodedArguments?.Value));
decodedArguments = new Lazy<Dictionary<string, object?>?>(() => Arguments.IsNullOrWhiteSpace() ? [] : JsonConvert.DeserializeObject<Dictionary<string, object?>>(Arguments));
ArgGetter = new Lazy<ChatFunctionParamsGetter>(() => new ChatFunctionParamsGetter(DecodedArguments?.Value));
DecodedArguments = new Lazy<Dictionary<string, object?>?>(() => Arguments.IsNullOrWhiteSpace() ? [] : JsonConvert.DeserializeObject<Dictionary<string, object?>>(Arguments));
}

[JsonIgnore]
Expand Down Expand Up @@ -57,32 +66,7 @@ public FunctionCall()
/// <returns></returns>
public Dictionary<string, object?> GetArguments()
{
return argGetter.Value.Source ?? [];
}

/// <summary>
/// Attempts to get value of a given argument. If the argument is of incompatible type, <see cref="exception"/> is returned.
/// </summary>
/// <param name="param"></param>
/// <param name="data"></param>
/// <param name="exception"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public bool TryGetArgument<T>(string param, [NotNullWhen(returnValue: true)] out T? data, out Exception? exception)
{
return argGetter.Value.Get(param, out data, out exception);
}

/// <summary>
/// Attempts to get value of a given argument. If the argument is not found or is of incompatible type, null is returned.
/// </summary>
/// <param name="param"></param>
/// <param name="data"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public bool TryGetArgument<T>(string param, [NotNullWhen(returnValue: true)] out T? data)
{
return argGetter.Value.Get(param, out data, out _);
return ArgGetter.Value.Source ?? [];
}

/// <summary>
Expand Down
56 changes: 13 additions & 43 deletions LlmTornado/Chat/Plugins/ChatPluginFunctionInputParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,22 @@

namespace LlmTornado.Chat.Plugins;

/// <summary>
/// Input params of a function call.
/// </summary>
public class ChatPluginFunctionInputParams
{
private readonly Dictionary<string, object?>? source;

/// <summary>
/// Source dictionary.
/// </summary>
public Dictionary<string, object?>? Source { get; set; }

/// <summary>
/// Creates an input params from a dictionary.
/// </summary>
/// <param name="pars"></param>
public ChatPluginFunctionInputParams(Dictionary<string, object?>? pars)
{
source = pars;
}

public bool Get<T>(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<T?>();
return true;
}

try
{
data = (T?)rawData.ChangeType(typeof(T));
return true;
}
catch (Exception e)
{
data = default;
exception = e;
return false;
}
Source = pars;
}
}
Loading

0 comments on commit d6edf5b

Please sign in to comment.