Skip to content

Commit ee37b15

Browse files
Add GitHub Actions workflow and enhance project structure
- Updated `publish.yml` to include a GitHub Actions workflow for building, testing, and publishing to NuGet. - Revamped `README.md` with a new logo, detailed project description, features, installation instructions, and a quick start guide. - Modified `SemanticChunker.NET.sln` to include project references for better organization. - Added binary files for package branding and presentation. - Updated `SemanticChunker.NET.Tests.csproj` with new package references and project reference to the main project. - Created `SemanticChunkerTests.cs` for unit testing the `SemanticChunker` class. - Removed `UnitTest1.cs` for cleanup of the test structure. - Introduced `BreakpointThresholdType.cs` for breakpoint threshold calculation methods. - Added `Chunk.cs` to define the `Chunk` class for chunking functionality. - Updated `SemanticChunker.NET.csproj` to target .NET 8.0 and include necessary package metadata. - Extensively modified `SemanticChunker.cs` to implement core chunking functionality and manage embeddings.
1 parent 0329aff commit ee37b15

16 files changed

Lines changed: 786 additions & 13 deletions

.github/workflows/publish.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Build, Test and Publish to NuGet
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
workflow_dispatch:
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v3
16+
17+
- name: Setup .NET
18+
uses: actions/setup-dotnet@v4
19+
with:
20+
dotnet-version: '8.0.x'
21+
22+
- name: Restore dependencies
23+
run: dotnet restore
24+
25+
- name: Build
26+
run: dotnet build --configuration Release --no-restore
27+
28+
- name: Run tests
29+
run: dotnet test --configuration Release --no-build --no-restore
30+
31+
- name: Pack NuGet package
32+
run: dotnet pack src/SemanticChunker.NET/SemanticChunker.NET.csproj --configuration Release --no-build --output ./nupkg
33+
34+
- name: Publish to NuGet
35+
run: dotnet nuget push ./nupkg/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
36+
env:
37+
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}

README.md

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,112 @@
1-
# SemanticChunker.NET
1+
[![SemanticChunker.NET Logo](https://github.com/GregorBiswanger/SemanticChunker.NET/raw/main/assets/semantic-chunker-net-logo-transparent.png)](https://github.com/GregorBiswanger/SemanticChunker.NET)
2+
3+
# SemanticChunker.NET
4+
5+
**Automatic Semantic Chunking for RAG in .NET
6+
Transforms long texts into coherent, retrieval ready chunks with a single call - powered by embeddings and fully compatible with Semantic Kernel and Microsoft.Extensions.AI.**
7+
8+
[![NuGet](https://img.shields.io/nuget/v/SemanticChunker.NET?style=flat-square)](https://www.nuget.org/packages/SemanticChunker.NET/)
9+
![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)
10+
11+
> Split long documents into semantically coherent chunks that fit your LLM’s context window while maximising retrieval precision.
12+
13+
## Features ✨
14+
15+
- **Plug‑and‑play API** – One call to `CreateChunksAsync` returns ready‑to‑use `Chunk` objects with ID, text, and embedding.
16+
- **Model‑agnostic** – Works with any embedding generator supported by `Microsoft.Extensions.AI`; no framework lock‑in.
17+
- **Four breakpoint strategies**`Percentile`, `StandardDeviation`, `InterQuartile`, and `Gradient` cover most corpus profiles.
18+
- **Context buffer window** – Configurable `bufferSize` preserves cross‑sentence semantics.
19+
- **Target chunk count** – Unique `targetChunkCount` option produces exactly the number of chunks you need.
20+
- **Multilingual sentence splitting** – ICU4N ensures accurate sentence boundaries in 70+ languages.
21+
- **Token‑limit safety** – Automatic 10 % safety margin below your model’s context window.
22+
- **Parallel embedding generation** – Maximises throughput when your embedding provider supports batching.
23+
- **Zero external overhead** – Pure .NET plus ICU4N; lightweight for microservices and serverless functions.
24+
25+
## Installation 📦
26+
27+
```bash
28+
dotnet add package SemanticChunker.NET
29+
````
30+
31+
## Quick Start 🛠️
32+
33+
```csharp
34+
using Microsoft.Extensions.AI;
35+
using Microsoft.SemanticKernel;
36+
using SemanticChunker.NET;
37+
38+
// 1. Wire an embedding generator (example uses LM Studio)
39+
var builder = Kernel.CreateBuilder();
40+
builder.Services.AddLmStudioEmbeddingGenerator("text-embedding-multilingual-e5-base");
41+
using var kernel = builder.Build();
42+
43+
// 2. Create Chunker with your model’s token limit (e.g. 512)
44+
var embeddingGenerator =
45+
kernel.Services.GetRequiredService<IEmbeddingGenerator<string, Embedding<float>>>();
46+
47+
var chunker = new SemanticChunker(embeddingGenerator, tokenLimit: 512);
48+
49+
// 3. Chunk text
50+
string input = File.ReadAllText("whitepaper.md");
51+
IList<Chunk> chunks = await chunker.CreateChunksAsync(input);
52+
53+
// 4. Persist embeddings to your vector store
54+
await myVectorStore.UpsertAsync(chunks);
55+
```
56+
57+
## Step‑by‑Step Calibration Guide
58+
59+
This section walks you through finding the *best* settings for **your** corpus and embedding model.
60+
61+
| Step | Action | Why |
62+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
63+
| **1 Choose an embedding model** | Prefer models whose training data match your language/domain. | Embedding quality dominates chunk quality. |
64+
| **2 Set `tokenLimit`** | Use the embedding model token limit. | Leaves headroom for prompts/RAG metadata. |
65+
| **3 Pick a buffer size** | Start with **1**; raise to 2–3 if individual sentences lose context. | Neighbor sentences improve semantic continuity. |
66+
| **4 Choose a breakpoint strategy** | `Percentile` 95 % is the industry default. Switch to `StandardDeviation` when your corpus shows heavy-tail distance distributions. | Percentile is robust; SD handles outliers. |
67+
| **5 Adjust `thresholdAmount`** | Lower value → more chunks, higher recall; Higher value → fewer, longer chunks, better precision. Tune in 5‑point increments (e.g. 90, 95, 98). | Balances retrieval recall vs. answer accuracy. |
68+
| **6 Optionally set `targetChunkCount`** | If you know how many chunks you need (e.g. for fixed‑budget eval), supply it and skip manual threshold tuning. | Directly controls output size. |
69+
| **7 Evaluate** | Measure Answer F1/EM and retrieval hit rate on a validation set. Iterate Steps 4–6 until metrics plateau. | Empirical tuning beats rules of thumb. |
70+
| **8 Lock parameters in production** | Persist calibrated values in app settings or environment variables. | Guarantees reproducibility across builds. |
71+
72+
## Configuration Reference
73+
74+
| Ctor Parameter | Default | Description |
75+
| ------------------ | ------------ | --------------------------------------------------------------------- |
76+
| `tokenLimit` | ** | Max LLM tokens per chunk (safety margin = 10 %). |
77+
| `bufferSize` | `1` | Sentences added before/after current sentence during embedding. |
78+
| `thresholdType` | `Percentile` | Breakpoint metric (`StandardDeviation`, `InterQuartile`, `Gradient`). |
79+
| `thresholdAmount` | see table | E.g. 95 % for Percentile, 3 σ for Standard Deviation. |
80+
| `targetChunkCount` | `null` | Overrides thresholds to hit an exact chunk count. |
81+
| `minChunkChars` | `0` | Skip chunks shorter than this. |
82+
83+
## 👨‍💻 Author
84+
85+
**[Gregor Biswanger](https://github.com/GregorBiswanger)** - is a leading expert in generative AI, a Microsoft MVP for Azure AI and Web App Development. As an independent consultant, he works closely with the Microsoft product team for GitHub Copilot and supports companies in implementing modern AI solutions.
86+
87+
As a freelance consultant, trainer, and author, he shares his expertise in software architecture and cloud technologies and is a sought-after speaker at international conferences. For several years, he has been live-streaming every Friday evening on [Twitch](https://twitch.tv/GregorBiswanger) with [My Coding Zone](https://www.my-coding-zone.de) in german and is an active [YouTuber](https://youtube.com/GregorBiswanger).
88+
89+
Reach out to Gregor if you need support in the form of consulting, training, or implementing AI solutions using .NET or Node.js. [LinkedIn](https://www.linkedin.com/in/gregor-biswanger-51342011/) or Twitter [@BFreakout](https://www.twitter.com/BFreakout)
90+
91+
See also the list of [contributors](https://github.com/GregorBiswanger/SemanticChunker.NET/graphs/contributors) who participated in this project.
92+
93+
## 🙋‍♀️🙋‍♂ Contributing
94+
95+
Feel free to submit a pull request if you find any bugs (to see a list of active issues, visit the [Issues section](https://github.com/GregorBiswanger/SemanticChunker.NET/issues).
96+
Please make sure all commits are properly documented.
97+
98+
The best thing would be to write about what you plan to do in the issue beforehand. Then there will be no disappointment if we cannot accept your pull request.
99+
100+
## 🙏 Donate
101+
102+
I work on this open-source project in my free time alongside a full-time job and raising three kids. If you`d like to support my work and help me dedicate more time to this project, consider sponsoring me on GitHub:
103+
104+
- [Gregor Biswanger](https://github.com/sponsors/GregorBiswanger)
105+
106+
Your sponsorship allows me to invest more time in improving the project and prioritizing important issues or features. Any support is greatly appreciated - thank you! 🍻
107+
108+
## 📜 License
109+
110+
This project is licensed under the [**Apache License 2.0**](https://raw.githubusercontent.com/GregorBiswanger/SemanticChunker.NET/refs/heads/main/LICENSE.txt) - © Gregor Biswanger 2025
111+
112+
*Happy chunking!* 🧩

SemanticChunker.NET.sln

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 17
4-
VisualStudioVersion = 17.14.36310.24 d17.14
4+
VisualStudioVersion = 17.14.36310.24
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SemanticChunker.NET.Tests", "src\SemanticChunker.NET.Tests\SemanticChunker.NET.Tests.csproj", "{F15C4E11-C06D-4EA9-B550-FC9650EC31FB}"
77
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SemanticChunker.NET", "src\SemanticChunker.NET\SemanticChunker.NET.csproj", "{E3190219-AE70-4367-807E-AF5522CC62F2}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
1517
{F15C4E11-C06D-4EA9-B550-FC9650EC31FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
1618
{F15C4E11-C06D-4EA9-B550-FC9650EC31FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
1719
{F15C4E11-C06D-4EA9-B550-FC9650EC31FB}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{E3190219-AE70-4367-807E-AF5522CC62F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{E3190219-AE70-4367-807E-AF5522CC62F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{E3190219-AE70-4367-807E-AF5522CC62F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{E3190219-AE70-4367-807E-AF5522CC62F2}.Release|Any CPU.Build.0 = Release|Any CPU
1824
EndGlobalSection
1925
GlobalSection(SolutionProperties) = preSolution
2026
HideSolutionNode = FALSE

assets/PackageIcon.png

16.5 KB
Loading

assets/PackageIcon.psd

174 KB
Binary file not shown.

assets/logo-template.psd

542 KB
Binary file not shown.
57.1 KB
Loading
61.6 KB
Loading

src/SemanticChunker.NET.Tests/SemanticChunker.NET.Tests.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1616
</PackageReference>
1717
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
18+
<PackageReference Include="Microsoft.SemanticKernel" Version="1.60.0" />
19+
<PackageReference Include="OllamaApiFacade" Version="1.3.0" />
1820
<PackageReference Include="Shouldly" Version="4.3.0" />
1921
<PackageReference Include="xunit" Version="2.9.3" />
2022
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
@@ -23,6 +25,10 @@
2325
</PackageReference>
2426
</ItemGroup>
2527

28+
<ItemGroup>
29+
<ProjectReference Include="..\SemanticChunker.NET\SemanticChunker.NET.csproj" />
30+
</ItemGroup>
31+
2632
<ItemGroup>
2733
<Using Include="Xunit" />
2834
</ItemGroup>

0 commit comments

Comments
 (0)