From 36e98dd14c06f8fdfa9f06f3bdca24f5d74682a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:55:33 +0000 Subject: [PATCH 1/2] Initial plan From f3b6af6849f078a08ae587d435dd1cc7aed7782d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 17:13:34 +0000 Subject: [PATCH 2/2] Remove AutoMapper dependency, replace with manual property mapping Co-authored-by: corpo-iwillspeak <265613520+corpo-iwillspeak@users.noreply.github.com> Agent-Logs-Url: https://github.com/crispthinking/FastText.NetWrapper/sessions/4f8a1d14-bc20-46dc-974c-386441953c2d --- .../FastText.NetWrapper.csproj | 1 - FastText.NetWrapper/FastTextArgs.cs | 55 ++++++++----- FastText.NetWrapper/FastTextWrapper.cs | 82 ++++++++++++------- 3 files changed, 90 insertions(+), 48 deletions(-) diff --git a/FastText.NetWrapper/FastText.NetWrapper.csproj b/FastText.NetWrapper/FastText.NetWrapper.csproj index 5fadc90..2432584 100644 --- a/FastText.NetWrapper/FastText.NetWrapper.csproj +++ b/FastText.NetWrapper/FastText.NetWrapper.csproj @@ -13,7 +13,6 @@ - diff --git a/FastText.NetWrapper/FastTextArgs.cs b/FastText.NetWrapper/FastTextArgs.cs index 5bf9c3e..2301bd0 100644 --- a/FastText.NetWrapper/FastTextArgs.cs +++ b/FastText.NetWrapper/FastTextArgs.cs @@ -1,5 +1,4 @@ using System.Runtime.InteropServices; -using AutoMapper; namespace FastText.NetWrapper; @@ -40,8 +39,8 @@ public unsafe QuantizedSupervisedArgs() FastTextWrapper.FastTextArgsStruct* argsPtr; GetDefaultSupervisedArgs(new IntPtr(&argsPtr)); - - Mapper.Map(*argsPtr, this); + + MapFromStruct(*argsPtr); DestroyArgs(new IntPtr(argsPtr)); } @@ -87,7 +86,7 @@ public unsafe SupervisedArgs() GetDefaultSupervisedArgs(new IntPtr(&argsPtr)); - Mapper.Map(*argsPtr, this); + MapFromStruct(*argsPtr); DestroyArgs(new IntPtr(argsPtr)); } @@ -120,20 +119,6 @@ public abstract class FastTextArgs #endregion - protected static readonly IMapper Mapper; - - static FastTextArgs() - { - Mapper = new MapperConfiguration(config => - { - config.ShouldMapProperty = prop => prop.GetMethod.IsPublic || prop.GetMethod.IsAssembly; - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); - }).CreateMapper(); - } - /// /// This constructor gets values from /// https://github.com/olegtarasov/fastText/blob/b0a32d744f4d16d8f9834649f6f178ff79b5a4ce/src/fasttext_api.cc#L12 @@ -146,11 +131,43 @@ protected unsafe FastTextArgs() GetDefaultArgs(new IntPtr(&argsPtr)); - Mapper.Map(*argsPtr, this); + MapFromStruct(*argsPtr); DestroyArgs(new IntPtr(argsPtr)); } + protected void MapFromStruct(FastTextWrapper.FastTextArgsStruct argsStruct) + { + lr = argsStruct.lr; + lrUpdateRate = argsStruct.lrUpdateRate; + dim = argsStruct.dim; + ws = argsStruct.ws; + epoch = argsStruct.epoch; + minCount = argsStruct.minCount; + minCountLabel = argsStruct.minCountLabel; + neg = argsStruct.neg; + wordNgrams = argsStruct.wordNgrams; + loss = (LossName)argsStruct.loss; + model = (ModelName)argsStruct.model; + bucket = argsStruct.bucket; + minn = argsStruct.minn; + maxn = argsStruct.maxn; + thread = argsStruct.thread; + t = argsStruct.t; + verbose = argsStruct.verbose; + saveOutput = argsStruct.saveOutput; + seed = argsStruct.seed; + + if (this is QuantizedSupervisedArgs quantized) + { + quantized.qout = argsStruct.qout; + quantized.retrain = argsStruct.retrain; + quantized.qnorm = argsStruct.qnorm; + quantized.cutoff = argsStruct.cutoff; + quantized.dsub = argsStruct.dsub; + } + } + /// /// learning rate [0.1] /// diff --git a/FastText.NetWrapper/FastTextWrapper.cs b/FastText.NetWrapper/FastTextWrapper.cs index 7067a1e..5992a14 100644 --- a/FastText.NetWrapper/FastTextWrapper.cs +++ b/FastText.NetWrapper/FastTextWrapper.cs @@ -1,6 +1,5 @@ using System.Runtime.InteropServices; using System.Text; -using AutoMapper; using Microsoft.Extensions.Logging; namespace FastText.NetWrapper; @@ -12,7 +11,6 @@ public partial class FastTextWrapper : IDisposable { private static readonly Encoding _utf8 = Encoding.UTF8; - private readonly IMapper _mapper; private readonly ILogger _logger; private IntPtr _fastText; @@ -25,17 +23,6 @@ public partial class FastTextWrapper : IDisposable public FastTextWrapper(ILoggerFactory loggerFactory = null) { _logger = loggerFactory?.CreateLogger(); - - _mapper = new MapperConfiguration(config => - { - config.ShouldMapProperty = prop => prop.GetMethod.IsPublic || prop.GetMethod.IsAssembly; - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); - }) - .CreateMapper(); - _fastText = CreateFastText(); } @@ -54,17 +41,6 @@ public FastTextWrapper(ILoggerFactory loggerFactory = null) public FastTextWrapper(bool useBundledLibrary, ILoggerFactory loggerFactory = null) { _logger = loggerFactory?.CreateLogger(); - - _mapper = new MapperConfiguration(config => - { - config.ShouldMapProperty = prop => prop.GetMethod.IsPublic || prop.GetMethod.IsAssembly; - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); - }) - .CreateMapper(); - _fastText = CreateFastText(); } @@ -220,10 +196,10 @@ internal void Supervised(string inputPath, string outputPath, SupervisedArgs arg bool quantizeWithNoQuantTune = quantizedArgs != null && string.IsNullOrEmpty(autotuneArgs.ModelSize); - var argsStruct = _mapper.Map(args); + var argsStruct = ToArgsStruct(args); argsStruct.model = model_name.sup; - var autotuneStruct = _mapper.Map(autotuneArgs); + var autotuneStruct = ToAutotuneArgsStruct(autotuneArgs); CheckForErrors(Train( _fastText, inputPath, @@ -273,7 +249,7 @@ public void Unsupervised(UnsupervisedModel model, string inputPath, string outpu args.model = (ModelName)model; - var argsStruct = _mapper.Map(args); + var argsStruct = ToArgsStruct(args); CheckForErrors(Train( _fastText, inputPath, @@ -305,7 +281,7 @@ public void Quantize(QuantizedSupervisedArgs args, string output = null) if (string.IsNullOrEmpty(ModelPath) && string.IsNullOrEmpty(output)) throw new InvalidOperationException("Model was loaded from memory. You need to specify output path."); - var argsStruct = _mapper.Map(args); + var argsStruct = ToArgsStruct(args); string outPath = AdjustPath(string.IsNullOrEmpty(output) ? ModelPath : output, true); if ((Path.IsPathRooted(output) && !Directory.Exists(Path.GetDirectoryName(outPath)))) @@ -502,6 +478,56 @@ public void Dispose() _fastText = IntPtr.Zero; } + private static FastTextArgsStruct ToArgsStruct(FastTextArgs args) + { + var result = new FastTextArgsStruct + { + lr = args.lr, + lrUpdateRate = args.lrUpdateRate, + dim = args.dim, + ws = args.ws, + epoch = args.epoch, + minCount = args.minCount, + minCountLabel = args.minCountLabel, + neg = args.neg, + wordNgrams = args.wordNgrams, + loss = (loss_name)args.loss, + model = (model_name)args.model, + bucket = args.bucket, + minn = args.minn, + maxn = args.maxn, + thread = args.thread, + t = args.t, + verbose = args.verbose, + saveOutput = args.saveOutput, + seed = args.seed + }; + + if (args is QuantizedSupervisedArgs quantized) + { + result.qout = quantized.qout; + result.retrain = quantized.retrain; + result.qnorm = quantized.qnorm; + result.cutoff = quantized.cutoff; + result.dsub = quantized.dsub; + } + + return result; + } + + private static AutotuneArgsStruct ToAutotuneArgsStruct(AutotuneArgs args) + { + return new AutotuneArgsStruct + { + ValidationFile = args.ValidationFile, + Metric = args.Metric, + Predictions = args.Predictions, + Duration = args.Duration, + ModelSize = args.ModelSize, + Verbose = args.Verbose + }; + } + private string AdjustPath(string path, bool isQuantized) { string result = Path.HasExtension(path) ? Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path)) : path;