Lodestar.Abstractions 0.1.1

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Lodestar.Abstractions --version 0.1.1
                    
NuGet\Install-Package Lodestar.Abstractions -Version 0.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Lodestar.Abstractions" Version="0.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Lodestar.Abstractions" Version="0.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Lodestar.Abstractions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Lodestar.Abstractions --version 0.1.1
                    
#r "nuget: Lodestar.Abstractions, 0.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Lodestar.Abstractions@0.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Lodestar.Abstractions&version=0.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Lodestar.Abstractions&version=0.1.1
                    
Install as a Cake Tool

Lodestar

Quality Gate Status

A data-science toolkit for C#/.NET, built on an honest premise:

Don't rewrite Python. Use the .NET ecosystem where it's strong, and write native code only where .NET has a real gap: text (similarity, vectorization, semantic search). All of it with no Python at runtime.

Why

Python dominates data analysis through its ecosystem and its exploratory notebook workflow, not through the language itself. Its performance comes from C/Fortran kernels.

C# brings static typing, real parallelism without a global interpreter lock, safe refactoring, and simple deployment. The only objective reason to stay on Python for this domain was the lack of an equivalent .NET library. Lodestar removes that reason.

What has no .NET equivalent

The claim this project is judged on, strongest first.

  1. Sparse text vectorization. CountVectorizer, TfidfVectorizer and HashingVectorizer at scikit-learn semantics, over a CsrMatrix written here. ML.NET's FeaturizeText produces a dense vector coupled to IDataView; for the same thousand documents it materializes 81 million floats where the sparse matrix stores 39 974 values. There is no third option in .NET.
  2. Framework-free classification metrics. 54 metric classes against ML.NET's six result types — and no IDataView, no schema, no pipeline object between the caller and a double. ML.NET has no call that returns one metric: asking it for accuracy costs the whole evaluation bundle.
  3. Loading the tokenizer files people actually have. tokenizer.json — normalizer, pre-tokenizer, model, decoder, added tokens — is what Llama-2 and Mistral v0.1 ship, and Microsoft.ML.Tokenizers has no entry point that reads one. Every one of its factories takes a vocabulary, a merges file or a spiece.model.
  4. Split conformal prediction. An interval instead of a point, a set instead of a class, with a finite-sample coverage guarantee — MAPIE's job, and the survey behind #441 found no C# implementation at all, maintained or otherwise. The guarantee assumes exchangeable calibration and test data, which docs/guides/conformal.md leads with rather than footnotes.
  5. Distances, embeddings and fuzzy matching, bundled for pipeline coherence rather than because .NET is empty here — it is not, and the table below says by how much.

All of it with no Python at runtime, on .NET 10 and .NET Standard 2.0 from a single package (also .NET Framework 4.6.1+, Mono, Xamarin, Unity — see docs/decisions/0001).

The second deliverable is the migration guides for people arriving from Python: docs/migration/ points each need (NumPy, pandas, scikit-learn, statsmodels, PyTorch, matplotlib, seaborn) at the right .NET building block and its pitfalls, marks the libraries that are no longer maintained with the dates that prove it, and says when calling Python is still the right answer. Its four-column inventory is the project map — use, build, decide.

Measured against the .NET incumbents

A claim nobody checked is a claim nobody believes, so every package is benchmarked against the .NET library a reader would otherwise reach for — not only against Python. Both sides are checked to return the same answers before either is timed; bench/README.md's section 15 has the harness and the agreement checks.

package incumbent how it reads
Lodestar.Text ML.NET FeaturizeText Not like-for-like. Per feature produced the two are within ~11 % — the advantage is the sparse representation, not a faster kernel
Lodestar.Fuzzy Fastenshtein, Quickenshtein, F23.StringSimilarity, Raffinert.FuzzySharp Ahead on Levenshtein at every length, and on all four fuzz ratios
Lodestar.Embeddings Microsoft.ML.Tokenizers, TensorPrimitives Behind on encoding, and the gap that justifies the package is the loader above — decision 0068
Lodestar.Metrics ML.NET metrics Coverage, not speed: the advantage narrows with size and the shape does not
Lodestar.Conformal — No incumbent exists, which is the finding rather than a gap in the harness — bench/README.md section 15 says what would change that

Numbers with the machine that produced them are in docs/guides/performance.md; a shared runner's absolutes are not comparable and are deliberately not published there.

Why not just call Python?

CSnakes and Python.NET both work, both are maintained, and for a model that only exists as a Python package they are the right answer — docs/migration/ says so. What they cost is a Python runtime to deploy and version alongside the application, no ahead-of-time compilation to a single artifact, and the GIL between your threads and theirs. Where a .NET library will do, that is a poor trade, and this project exists to make it an avoidable one.

What is delivered

The five lots of the original brief are complete, and the repository has since grown past that framing — docs/reference/ documents considerably more than this table lists.

Lot Contents Status
1 String distances & similarity ✅ complete — Levenshtein (+ Myers), OSA, Damerau-Levenshtein, Hamming, Jaro, Jaro-Winkler, Indel, LCS, Ratcliff-Obershelp, Jaccard, Dice, Overlap, Tversky, Cosine, Soundex, Metaphone, NYSIIS
2 Tokenization & sparse vectorization ✅ complete — CSR, tokenizers (word/char/char_wb), CountVectorizer, TfidfVectorizer, HashingVectorizer, Porter, Snowball EN/FR/DE/ES/IT/PT, stop words in six languages
3 Embeddings & semantic search ✅ complete — WordPiece, SentencePiece, BPE and byte-level BPE (GPT-2, Llama-3, Qwen2), pooling, SIMD kNN, ONNX inference
4 Applied fuzzy matching ✅ complete — fuzz.* (ratio/partial/token_sort/token_set/WRatio), process.extract/extractOne, blocking deduplication
5 Classification metrics ✅ complete — confusion matrix, accuracy, precision/recall/F1/F-beta in all four averaging modes, classification_report character for character, ROC-AUC binary and multiclass (ovr/ovo)

Every building block is oracle-validated against rapidfuzz / jellyfish / textdistance / difflib / scikit-learn / nltk / HuggingFace tokenizers / sentencepiece / numpy / ONNX Runtime (see docs/equivalence.md).

Getting started

dotnet add package Lodestar.Text
using Lodestar.Text.Distances;

Levenshtein.Distance("kitten", "sitting");             // 3
Levenshtein.NormalizedSimilarity("kitten", "sitting"); // 0.5714…

A runnable version of the above, consuming the packages exactly as you would:

for p in src/Lodestar.Text src/Lodestar.Embeddings src/Lodestar.Fuzzy src/Lodestar.Metrics; do
  dotnet pack "$p" -c Release -o ./artifacts
done
dotnet run --project samples/Lodestar.Sample -c Release

Full guide: docs/guides/quickstart.md. See also the vectorization, embeddings, fuzzy-matching and metrics guides — the last one answers which metric to reach for, which the per-member reference pages deliberately cannot.

Function by function, the reference pages under docs/reference/ say what each member is for, when to prefer it to its neighbour and what the trap is — start with the distances. The same pages are published to the wiki, where each package's channel follows main and every release is archived under its own version.

Developing

dotnet build                                   # build the solution
dotnet test                                    # replay oracles + property tests
dotnet run -c Release --project bench/Lodestar.Text.Benchmarks -- --filter '*Levenshtein*'

The project follows GitHub flow: main is always releasable, and every change arrives through a short-lived branch and a pull request. Branch conventions, the definition of done, the oracle-validation procedure and the analyzer-suppression policy are in CONTRIBUTING.md; release history is in CHANGELOG.md.

Oracle validation

Conformance to Python behavior is proven, not assumed (§4 of the brief). tools/generate_oracles.py freezes a few thousand reference cases from rapidfuzz/jellyfish/etc. into tests/oracles/*.json (versioned). The C# suite replays them with a 1e-9 tolerance. Python is a development-only dependency. See tools/README.md.

Structure

Lodestar.slnx
├── src/Lodestar.Text/            distances, similarity, tokenizers, vectorizers, stemmers (no dependencies)
├── src/Lodestar.Embeddings/      sub-word tokenizers, pooling, SIMD kNN, ONNX inference (ONNX Runtime isolated here)
├── src/Lodestar.Fuzzy/           fuzz.*, process.extract, deduplication
├── src/Lodestar.Metrics/         confusion matrix, precision/recall/F1, report, ROC-AUC
├── tests/                       xUnit: oracles + properties (one project per module)
├── tests/oracles/               frozen JSON corpora (generated from Python) + a synthetic ONNX model
├── bench/Lodestar.Text.Benchmarks/  BenchmarkDotNet
├── tools/generate_oracles.py    reference generation
├── Directory.Build.props        (root); src|tests/Directory.Packages.props (central package management)
├── src/*/Version.props          one version per publishable package (decision 0012)
├── docs/                        guides, equivalence table, decision log
├── docs/reference/<package>/    one reference entry per exported type and public method
└── docs/wiki-map.json           which page ships with which package, and which namespaces the reference gate enforces

Where a fact belongs

Each document below has one subject; content whose subject is another document's belongs there instead, with a link left behind. The source column is what tells you whether to correct the document itself or something upstream of it.

document its source its subject
bench/README.md the bench/ harness projects and scripts, hand-maintained how to measure — the harness, the corpus, the commands
docs/guides/performance.md a benchmark run on a named machine what was measured — every number, with its machine and its window
tools/README.md the scripts under tools/, hand-maintained what each tool does and how to run it
CONTRIBUTING.md the project's own process, hand-maintained the process a contributor follows
CLAUDE.md what a session has found, hand-maintained what a session needs to be productive, and the traps that cost time
docs/equivalence.md the oracle corpora in tests/oracles/*.json, replayed against the C# they compare the Python call to C# counterpart mapping, with each divergence
docs/migration/ the .NET package chosen for each need what is delegated to another .NET library, and why
docs/reference/ the exported types and public methods of the namespaces docs/wiki-map.json declares covered, replayed against both target frameworks' assemblies what each function is for, entry by entry — declaration, parameters, returns, example, remarks
docs/wiki-map.json the packages and the pages that ship with each, hand-maintained which page belongs to which package, and which namespaces the reference gate enforces
CHANGELOG.md the merged pull requests, per release what changed, per release
docs/decisions/ the ADRs' own **Status:** lines, indexed in docs/decisions/README.md a decision, with its options and its loser
root README.md the project as it stands, hand-maintained what the project is, and where to go next

Publishing

Four NuGet packages are produced: Lodestar.Text, Lodestar.Embeddings, Lodestar.Fuzzy, Lodestar.Metrics. Each versions and releases on its own: shared metadata (license, README, repository) lives in Directory.Build.props, while the version is declared per project in src/<Package>/Version.props. Lodestar.Fuzzy depends on Lodestar.Text as a published package, not as a project reference — see docs/decisions/0012.

GitHub Packages (no nuget.org account needed — uses GitHub's automatic token). Bump the version, then tag it with the package name. The release workflow packs and publishes that package alone:

# 1. edit src/Lodestar.Fuzzy/Version.props, commit, merge to main
# 2. tag the released version — <PackageId>/v<Version>
git tag Lodestar.Fuzzy/v0.3.0
git push origin Lodestar.Fuzzy/v0.3.0

The tag does not set the version; it names which declared version to release. The workflow refuses the job if the tag and Version.props disagree. Repository-wide v* tags are retired — there is no single version left for one to designate.

Step 1 is not optional. Because the tag only confirms the declared version, tagging without bumping first is a tag that agrees with Version.props and names a version the feed already has. The push is then rejected rather than absorbed. The workflows do not pass --skip-duplicate, which used to report that case as a successful release that shipped nothing. Keeping a declared version off the feed is also checked directly in CI by tools/check_version_floor.py.

To consume them, add a source pointing at the owner's feed (with a GitHub token that has read:packages):

dotnet nuget add source "https://nuget.pkg.github.com/CyrilB1531/index.json" \
  --name github --username CyrilB1531 --password <GITHUB_TOKEN>
dotnet add package Lodestar.Text

nuget.org uses Trusted Publishing (OIDC, no stored key): run the Publish to nuget.org workflow from the Actions tab, choosing the package and confirming its version. By hand, with an API key, one package at a time:

dotnet pack src/Lodestar.Text -c Release -o artifacts
dotnet nuget push "artifacts/Lodestar.Text.*.nupkg" \
  --source https://api.nuget.org/v3/index.json --api-key <KEY>

License

Apache-2.0. See NOTICE and THIRD-PARTY-NOTICES.md for attributions. The license choice and the code-provenance rule are documented in docs/decisions/0003-provenance-and-licensing.md.

This repository is not legal advice.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (14)

Showing the top 5 NuGet packages that depend on Lodestar.Abstractions:

Package Downloads
Lodestar.Text

String distances, similarity metrics, tokenizers and text vectorizers for .NET — native, allocation-lean, no Python at runtime.

Lodestar.Embeddings

Sub-word tokenizers (WordPiece, SentencePiece, BPE and byte-level BPE), batch encoding, pooling and SIMD kNN search for .NET. No external dependency: ONNX inference lives in Lodestar.Onnx, so a caller who only tokenizes never restores a native runtime.

Lodestar.Stats

Classical hypothesis tests for .NET at scipy.stats parity: Student and Welch t, Mann-Whitney U, Wilcoxon signed-rank, chi-square, Fisher exact, Kolmogorov-Smirnov, one-way ANOVA, Kruskal-Wallis, Shapiro-Wilk, and Bonferroni / Benjamini-Hochberg / Benjamini-Yekutieli corrections. Arrays in, statistic and p-value out. No model, no training loop, and no dependency beyond Lodestar.Abstractions, which holds its options and results.

Lodestar.Decomposition

Truncated SVD and non-negative matrix factorization for .NET at scikit-learn parity, over a sparse matrix and without centring it: latent semantic analysis on a term-document matrix, with explained variance, and NMF for a parts-based decomposition. Randomized SVD with all three power-iteration normalizers; the dense kernels are written here, so the only dependency is Lodestar.Abstractions.

Lodestar.Cluster

Clustering for .NET at scikit-learn parity: k-means by Lloyd's algorithm over a row-major span, with the initial centres accepted as an input so a run is reproducible entry by entry. Scores with Lodestar.Metrics, which already ships silhouette, adjusted Rand, AMI and V-measure. No dependencies.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 1,714 9/24/2026
0.1.1 5,535 9/1/2026
0.1.0 110 9/1/2026