Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions MapperAI.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpClient_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc439425da351c75ac7d966a1cc8324b51a9c471865af79d2f2f3fcb65e392_003FHttpClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=5ca51f47_002De3fa_002D40db_002D8e16_002D940aee47c197/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="Test_Should_Create_4_Files_With_CSharp_Extension" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=5ca51f47_002De3fa_002D40db_002D8e16_002D940aee47c197/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="Test_Should_Create_4_Files_With_CSharp_Extension" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.FileMapperTests.Test_Should_Create_4_Files_With_CSharp_Extension&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.ClassMapperTests.Test1&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.PdfMapperTests.Test1&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.FileMapperTests.Test_Should_Create_4_Files_With_Go_Extension&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=ee3fe810_002Dfb62_002D402b_002Db9c5_002D8dab803c815e/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="Test1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=ee3fe810_002Dfb62_002D402b_002Db9c5_002D8dab803c815e/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="Test1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.ClassMapperTests.Test1&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.FileMapperTests.Test1&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.FileMapperTests.Test_Should_Create_1_File_With_CSharp_Extension&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.PdfMapperTests.Test1&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.FileMapperTests.Test_Should_Create_4_Files_With_Go_Extension&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.FileMapperTests.Test_Should_Create_4_Files_With_CSharp_Extension&lt;/TestId&gt;&#xD;
&lt;TestId&gt;xUnit::8B3E109D-96CA-4B6D-B379-6AF70646DC25::net8.0::MapperAI.Test.DI.DependencyInjectionTests.AddMapperAI_ShouldRegisterServices&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>
4 changes: 2 additions & 2 deletions src/MapperAI.Core/Clients/GeminiMapperClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class GeminiMapperClient : MapperClientBase, IMapperClient
{
private const string EndpointBase = "https://generativelanguage.googleapis.com/v1beta";

public GeminiMapperClient(MapperClientConfiguration mapperClientConfiguration, IMapperSerializer serializer) : base(
mapperClientConfiguration, serializer)

public GeminiMapperClient(MapperClientConfiguration mapperClientConfiguration, IMapperSerializer serializer, HttpClient httpClient) : base(mapperClientConfiguration, serializer, httpClient)
{
}

Expand Down
6 changes: 3 additions & 3 deletions src/MapperAI.Core/Clients/MapperClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ public abstract class MapperClientBase
private readonly HttpClient _httpClient;
private readonly IMapperSerializer _serializer;

protected MapperClientBase(MapperClientConfiguration mapperClientConfiguration, IMapperSerializer serializer)
protected MapperClientBase(MapperClientConfiguration mapperClientConfiguration, IMapperSerializer serializer, HttpClient httpClient)
{
MapperClientConfiguration = mapperClientConfiguration;
_httpClient = new HttpClient();
_serializer = serializer;
_httpClient = httpClient;
}

protected async Task<JsonDocument> GetAsync(string endpoint, object body, CancellationToken cancellationToken = default)
Expand All @@ -31,7 +31,7 @@ protected async Task<JsonDocument> GetAsync(string endpoint, object body, Cancel
throw new MapperRequestStatusException($"Request failed with status: {response.StatusCode}");
}

string result = await response.Content.ReadAsStringAsync();
string result = await response.Content.ReadAsStringAsync(cancellationToken);
return JsonDocument.Parse(result);
}
catch (Exception ex)
Expand Down
13 changes: 3 additions & 10 deletions src/MapperAI.Core/Clients/MapperClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,17 @@

namespace MapperAI.Core.Clients;

public class MapperClientFactory : IMapperClientFactory
public class MapperClientFactory(IMapperSerializer serializer, HttpClient httpClient) : IMapperClientFactory
{
private readonly IMapperSerializer _serializer;

public MapperClientFactory(IMapperSerializer serializer)
{
_serializer = serializer;
}

public IMapperClient CreateClient(MapperClientConfiguration configuration)
{
switch (configuration.Type)
{
case ModelType.Ollama:
return new OllamaMapperClient(configuration, _serializer);
return new OllamaMapperClient(configuration, serializer, httpClient);

default:
return new GeminiMapperClient(configuration, _serializer);
return new GeminiMapperClient(configuration, serializer, httpClient);
}
}
}
13 changes: 4 additions & 9 deletions src/MapperAI.Core/Clients/Models/MapperClientConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
using MapperAI.Core.Enums;
using MapperAI.Core.Extensions.Enums;

namespace MapperAI.Core.Clients.Models;

public class MapperClientConfiguration
{
public string Model { get; set; }
public string? ApiKey { get; set; }
public ModelType Type { get; set; }

public MapperClientConfiguration(string model, string? apiKey, ModelType type)
public string Model => Type.GetEnumDescriptionValue();

public MapperClientConfiguration( string? apiKey, ModelType type)
{
Model = model;
ApiKey = apiKey;
Type = type;
}

public MapperClientConfiguration(string model, ModelType type)
{
Model = model;
Type = type;
}
}
4 changes: 2 additions & 2 deletions src/MapperAI.Core/Clients/OllamaMapperClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public class OllamaMapperClient : MapperClientBase ,IMapperClient
{
private const string Endpoint = "http://localhost:11434/api/generate";

public OllamaMapperClient(MapperClientConfiguration mapperClientConfiguration, IMapperSerializer serializer) : base(mapperClientConfiguration, serializer)

public OllamaMapperClient(MapperClientConfiguration mapperClientConfiguration, IMapperSerializer serializer, HttpClient httpClient) : base(mapperClientConfiguration, serializer, httpClient)
{
}


public async Task<MapperClientResponse> SendAsync(string prompt, CancellationToken cancellationToken)
{
dynamic payload = CreatePayload(prompt);
Expand Down
36 changes: 36 additions & 0 deletions src/MapperAI.Core/DI/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using MapperAI.Core.Clients;
using MapperAI.Core.Clients.Interfaces;
using MapperAI.Core.Clients.Models;
using MapperAI.Core.Enums;
using MapperAI.Core.Mappers;
using MapperAI.Core.Mappers.Interfaces;
using MapperAI.Core.Serializers;
using MapperAI.Core.Serializers.Interfaces;
using Microsoft.Extensions.DependencyInjection;

namespace MapperAI.Core.DI;

public static class DependencyInjection
{
public static IServiceCollection AddMapperAI(this IServiceCollection services, string apiKey, ModelType modelType)
{
services.AddMapperClientConfiguration(apiKey, modelType);
services.AddHttpClient();
services.AddSingleton<IMapperSerializer, MapperSerializer>();
services.AddSingleton<IMapperClientFactory, MapperClientFactory>();
services.AddScoped<IClassMapper, ClassMapper>();

services.AddScoped<IClassMapper, ClassMapper>();
services.AddScoped<IFileMapper, FileMapper>();
services.AddScoped<IPDFMapper, PdfMapper>();

return services;
}

private static void AddMapperClientConfiguration(this IServiceCollection services, string apiKey, ModelType modelType)
{
MapperClientConfiguration configuration = new(apiKey, modelType);
services.AddSingleton<MapperClientConfiguration>(s => configuration);

}
}
8 changes: 5 additions & 3 deletions src/MapperAI.Core/Enums/ModelType.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
namespace MapperAI.Core.Enums;
using System.ComponentModel;

namespace MapperAI.Core.Enums;

public enum ModelType
{

Gemini,
[Description("gemini-2.0-flash")]
GeminiFlash2_0,
ChatGpt,
Ollama
}
14 changes: 14 additions & 0 deletions src/MapperAI.Core/Extensions/Enums/EnumExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.ComponentModel;
using System.Reflection;

namespace MapperAI.Core.Extensions.Enums;

public static class EnumExtension
{
public static string GetEnumDescriptionValue(this Enum data)
{
FieldInfo? field = data.GetType().GetField(data.ToString());
var attribute = field?.GetCustomAttribute<DescriptionAttribute>();
return attribute?.Description ?? throw new InvalidEnumArgumentException();
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System.Reflection;
using System.Reflection;

namespace MapperAI.Core.Initializers;
namespace MapperAI.Core.Extensions.Initializers;

public class DependencyInitializer
public static class InitializerExtension
{

public static void Initialize(object obj)
public static void Initialize(this object obj)
{
var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
var genericProperties = properties.Where(x => x.PropertyType.IsGenericType);
Expand All @@ -17,6 +16,7 @@ public static void Initialize(object obj)
}
}
}

private static void InitializeDependencyProperties(Type? itemType, PropertyInfo property, object obj)
{
if (itemType == null)
Expand Down Expand Up @@ -47,5 +47,4 @@ private static void InitializeDependencyProperties(Type? itemType, PropertyInfo

property.SetValue(obj, listInstance);
}

}
1 change: 1 addition & 0 deletions src/MapperAI.Core/MapperAI.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

<ItemGroup>
<PackageReference Include="itext7" Version="9.1.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ public class FileMapperConfiguration
public string InputFolder { get; set; }
public string? NameSpace { get; set; }
public string Extension { get; set; } = "C#";

public string? LanguageVersion { get; set; }
public string? FileName { get; set; }
public bool IsUniqueClass => FileName != null;
Expand Down
4 changes: 2 additions & 2 deletions src/MapperAI.Core/Mappers/PdfMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using iText.Kernel.Pdf.Canvas.Parser;
using MapperAI.Core.Clients.Interfaces;
using MapperAI.Core.Clients.Models;
using MapperAI.Core.Initializers;
using MapperAI.Core.Extensions.Initializers;
using MapperAI.Core.Mappers.Interfaces;
using MapperAI.Core.Serializers.Interfaces;

Expand All @@ -27,7 +27,7 @@ public PdfMapper(IMapperSerializer serializer, IMapperClientFactory mapperClient
IMapperClient iai = _mapperClientFactory.CreateClient(_clientConfiguration);
string pdfContent = ExtractPdfContent(pdfPath);
T destinyObject = new T();
DependencyInitializer.Initialize(destinyObject);
destinyObject.Initialize();
string prompt = CreatePrompt(pdfContent, _serializer.Serialize(destinyObject));
MapperClientResponse result = await iai.SendAsync(prompt, cancellationToken);
return _serializer.Deserialize<T>(result.Value);
Expand Down
2 changes: 1 addition & 1 deletion test/MapperAI.Test/BaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public abstract class BaseTests
public BaseTests()
{
Serializer = new MapperSerializer();
Factory = new MapperClientFactory(Serializer);
Factory = new MapperClientFactory(Serializer, new HttpClient());
}
}
6 changes: 3 additions & 3 deletions test/MapperAI.Test/ClassMapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ namespace MapperAI.Test;
public class ClassMapperTests : BaseTests
{
private readonly IClassMapper _classMapper;
private readonly MapperClientConfiguration _clientConfiguration;

public ClassMapperTests()
{
_clientConfiguration = new MapperClientConfiguration("gemini-2.0-flash", Environment.GetEnvironmentVariable("GEMINI_KEY"),ModelType.Gemini);
_classMapper = new ClassMapper(Serializer, Factory, _clientConfiguration);
var clientConfiguration = new MapperClientConfiguration(Environment.GetEnvironmentVariable("GEMINI_KEY"),ModelType.GeminiFlash2_0);
_classMapper = new ClassMapper(Serializer, Factory, clientConfiguration);

}


Expand Down
28 changes: 28 additions & 0 deletions test/MapperAI.Test/DI/DependencyInjectionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using MapperAI.Core.Clients.Interfaces;
using MapperAI.Core.DI;
using MapperAI.Core.Enums;
using MapperAI.Core.Mappers.Interfaces;
using MapperAI.Core.Serializers.Interfaces;
using Microsoft.Extensions.DependencyInjection;

namespace MapperAI.Test.DI;

public class DependencyInjectionTests
{
[Fact]
public void AddMapperAI_ShouldRegisterServices()
{
var services = new ServiceCollection();

// Act
services.AddMapperAI("fake-key", ModelType.GeminiFlash2_0);
var provider = services.BuildServiceProvider();

// Assert
Assert.NotNull(provider.GetService<IMapperSerializer>());
Assert.NotNull(provider.GetService<IMapperClientFactory>());
Assert.NotNull(provider.GetService<IClassMapper>());
Assert.NotNull(provider.GetService<IFileMapper>());
Assert.NotNull(provider.GetService<IPDFMapper>());
}
}
10 changes: 4 additions & 6 deletions test/MapperAI.Test/FileMapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ namespace MapperAI.Test;

public class FileMapperTests : BaseTests
{

private readonly MapperClientConfiguration _clientConfiguration;
private readonly IFileMapper _mapper;

private string InputFolder => Path.Combine(FoldersHelpers.GetProjectDefaultPath(), "Class");
private string OutputFolder => Path.Combine(FoldersHelpers.GetProjectDefaultPath(), "MappedClasses");

public FileMapperTests()
{
_clientConfiguration = new MapperClientConfiguration("gemini-2.0-flash", Environment.GetEnvironmentVariable("GEMINI_KEY"),ModelType.Gemini);
_mapper = new FileMapper(Factory, Serializer, _clientConfiguration);
var clientConfiguration = new MapperClientConfiguration( Environment.GetEnvironmentVariable("GEMINI_KEY"),ModelType.GeminiFlash2_0);
_mapper = new FileMapper(Factory, Serializer, clientConfiguration);

}

Expand All @@ -45,11 +43,11 @@ public async Task Test_Should_Create_4_Files_With_Go_Extension()
public async Task Test_Should_Create_4_Files_With_CSharp_Extension()
{

string extesionToMap = "js";
string extesionToMap = "php";
FileMapperConfiguration configuration = new FileMapperConfiguration(InputFolder, OutputFolder)
{
NameSpace = "MapperAI.Test.MappedClasses",
Extension = extesionToMap
Extension = extesionToMap,
};
await _mapper.MapAsync(configuration);
var files = Directory.GetFiles(OutputFolder);
Expand Down
5 changes: 2 additions & 3 deletions test/MapperAI.Test/PdfMapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ namespace MapperAI.Test;
public class PdfMapperTests : BaseTests
{
private readonly IPDFMapper _pdfMapper;
private readonly MapperClientConfiguration _clientConfiguration;

public PdfMapperTests()
{
_clientConfiguration = new MapperClientConfiguration("gemini-2.0-flash", Environment.GetEnvironmentVariable("GEMINI_KEY"),ModelType.Gemini);
_pdfMapper = new PdfMapper(Serializer, Factory, _clientConfiguration);
var clientConfiguration = new MapperClientConfiguration( Environment.GetEnvironmentVariable("GEMINI_KEY"),ModelType.GeminiFlash2_0);
_pdfMapper = new PdfMapper(Serializer, Factory, clientConfiguration);
}

[Fact]
Expand Down