FluxCurator.Core
0.16.0
See the version list below for details.
dotnet add package FluxCurator.Core --version 0.16.0
NuGet\Install-Package FluxCurator.Core -Version 0.16.0
<PackageReference Include="FluxCurator.Core" Version="0.16.0" />
<PackageVersion Include="FluxCurator.Core" Version="0.16.0" />
<PackageReference Include="FluxCurator.Core" />
paket add FluxCurator.Core --version 0.16.0
#r "nuget: FluxCurator.Core, 0.16.0"
#:package FluxCurator.Core@0.16.0
#addin nuget:?package=FluxCurator.Core&version=0.16.0
#tool nuget:?package=FluxCurator.Core&version=0.16.0
FluxCurator
Clean, protect, and chunk your text for RAG pipelines — no tokenizer, model, or service required.
Overview
FluxCurator is a text preprocessing library for RAG (Retrieval-Augmented Generation) pipelines. It provides multilingual PII masking, content filtering, and intelligent text chunking with support for 13 languages and 13 countries' national IDs.
Minimal Dependencies Philosophy: Core functionality (FluxCurator.Core) works standalone; its only dependency is the shared contract package Flux.Abstractions. The main package (FluxCurator) adds the Curator entry point, DI support and semantic chunking via an external IEmbedder you inject.
Packages
| Package | Purpose |
|---|---|
FluxCurator |
Curator entry point, AddFluxCurator DI registration, BatchProcessor, and semantic chunking over your IEmbedder |
FluxCurator.Core |
Interfaces, options and the built-in implementations: rule-based/hierarchical/table-aware chunkers, PII detectors and PIIMasker, RuleBasedFilter, TextRefiner, language profiles |
Features
| Feature | Entry point | How to turn it on |
|---|---|---|
| Text refinement — remove blank/duplicate lines, empty list markers, custom patterns | Curator.WithTextRefinement(...), Curator.RefineText, TextRefiner |
Opt-in: call WithTextRefinement (presets on TextRefineOptions) |
| Multilingual PII masking — emails, phones, national IDs (13 countries), credit cards, IP addresses, bank accounts, passports, URL credentials, MAC addresses | Curator.WithPIIMasking(...) then MaskPII / DetectPII / ContainsPII; PIIMasker |
Opt-in: call WithPIIMasking (MaskPII throws until you do); DI: FluxCuratorOptions.EnablePIIMasking. The default TypesToMask is PIIType.Common (email, phone, national ID, credit card); IP, bank account, passport, URL credential and MAC address need TypesToMask set to include them (or PIIMaskingOptions.Strict, which uses PIIType.All) |
| National ID checksum validation — SSN (US), RRN (Korea), Aadhaar (India), SIN (Canada), … | NationalIdRegistry, NationalIdDetectorBase |
On whenever PII masking is on; all 13 detectors are registered by default |
| Custom PII detectors | Curator.RegisterPIIDetector, PIIMasker.RegisterDetector, PIIDetectorBase |
Opt-in: register your detector |
| Content filtering — rule and blocklist based | Curator.WithContentFiltering(...) then FilterContent; RuleBasedFilter, ContentFilterManager |
Opt-in: call WithContentFiltering. No word lists are built in — supply ContentFilterOptions.CustomBlocklist / CustomPatterns (or RuleBasedFilter.AddRule), otherwise nothing is filtered |
Rule-based chunking — Auto, Sentence, Paragraph, Token |
Curator.ChunkAsync, IChunkerFactory.CreateChunker |
Default: ChunkOptions.Strategy = Auto |
Hierarchical chunking — Markdown heading structure with parent/child metadata (HierarchyLevel, ParentId) |
ChunkingStrategy.Hierarchical |
Opt-in: set the strategy (or use ChunkOptions.ForLargeDocument) |
| Semantic chunking — split at embedding-similarity boundaries | ChunkingStrategy.Semantic, Curator.UseEmbedder |
Opt-in: requires an IEmbedder (UseEmbedder, or registered in DI before AddFluxCurator) — or a Microsoft.Extensions.AI embedding generator (UseEmbeddingGenerator(generator), or services.AddEmbeddingGeneratorEmbedder() before AddFluxCurator); without one, chunking with this strategy throws |
Table-aware chunking — Markdown tables stay whole (or split between rows with the header repeated) in every built-in strategy; each table chunk also repeats the line(s) that name it — a caption such as <표 5> … / Table 5: … within 8 lines above, then the title/unit line(s) directly above (footnotes skipped), else the nearest heading (metadata table_context) |
ChunkOptions.PreserveTables, ChunkOptions.TableContextLines, TableAwareChunker for your own IChunker |
Default on (PreserveTables = true, TableContextLines = 2) |
| Chunk balancing — merge undersized and split oversized chunks | ChunkOptions.EnableChunkBalancing |
Default on |
| Multi-language support — 13 language profiles for sentence detection and token estimation | ChunkOptions.LanguageCode, Curator.DetectLanguage |
Default: auto-detect (LanguageCode = null) |
| Streaming chunks | Curator.ChunkStreamAsync |
Call it instead of ChunkAsync |
| Pipeline processing — Refine → Filter → Mask → Chunk in one call | Curator.PreprocessAsync → PreprocessingResult |
Runs the steps you enabled with the With… calls |
| Batch processing | Curator.CreateBatchProcessor() → BatchProcessor (AddTexts, WithMaxConcurrency, ProcessAsync, PreprocessAsync) |
Opt-in |
| Dependency injection | services.AddFluxCurator(...) registers IChunkerFactory (singleton) and IFluxCurator (transient, a configured Curator) |
Call AddFluxCurator; inject IFluxCurator (namespace FluxCurator.Core) |
| FileFlux integration | FileFlux delegates its chunking to FluxCurator through IChunkerFactory |
The adapter lives in the FileFlux package — see FileFlux Integration |
Installation
# Main package (DI support and semantic chunking)
dotnet add package FluxCurator
# Core package only (no Curator/DI; depends only on Flux.Abstractions)
dotnet add package FluxCurator.Core
Quick Start
The entry point is Curator (namespace FluxCurator). Options, chunks and results live in FluxCurator.Core.Domain,
and the extension interfaces (IEmbedder, IChunkerFactory, IPIIMasker, …) in FluxCurator.Core.Core. The examples
below assume these three using lines:
Basic Chunking
using FluxCurator; // Curator, AddFluxCurator
using FluxCurator.Core.Core; // IEmbedder, IChunkerFactory, IPIIDetector, ...
using FluxCurator.Core.Domain; // ChunkOptions, DocumentChunk, PIIMaskingOptions, ...
var text = "FluxCurator splits text into chunks. Each chunk keeps whole sentences. It works without a tokenizer.";
// Create a curator with default options
var curator = new Curator();
// Chunk the text (the default strategy is Auto)
var chunks = await curator.ChunkAsync(text);
foreach (var chunk in chunks)
{
Console.WriteLine($"Chunk {chunk.ChunkIndex + 1}/{chunk.TotalChunks}:");
Console.WriteLine(chunk.Content);
Console.WriteLine($"Tokens: ~{chunk.Metadata.EstimatedTokenCount}");
}
Streaming Chunks
// Memory-efficient streaming for large texts
var curator = new Curator();
await foreach (var chunk in curator.ChunkStreamAsync(largeText))
{
// Handle each chunk as soon as it is produced
Console.WriteLine($"Chunk {chunk.ChunkIndex}: {chunk.Content.Length} chars");
}
Dependency Injection
// Program.cs
services.AddFluxCurator(options =>
{
options.DefaultChunkOptions = ChunkOptions.ForMediumContext; // ForRAG is Semantic: it needs an IEmbedder (below)
options.EnablePIIMasking = true;
options.EnableContentFiltering = true;
});
// With an external IEmbedder for semantic chunking
services.AddSingleton<IEmbedder>(myEmbedder); // Register your embedder first
services.AddFluxCurator(options =>
{
options.DefaultChunkOptions = new ChunkOptions
{
Strategy = ChunkingStrategy.Semantic,
TargetChunkSize = 512
};
});
Using IChunkerFactory
// Inject IChunkerFactory (registered by AddFluxCurator) for flexible chunker creation
public class MyService(IChunkerFactory chunkerFactory)
{
public Task<IReadOnlyList<DocumentChunk>> ProcessAsync(string text)
{
// Create a specific chunker
var chunker = chunkerFactory.CreateChunker(ChunkingStrategy.Hierarchical);
return chunker.ChunkAsync(text, ChunkOptions.Default);
}
}
Text Refinement
// Clean noisy text before processing
var curator = new Curator()
.WithTextRefinement(TextRefineOptions.Standard);
var result = await curator.PreprocessAsync(rawText);
// Pipeline: Refine → Filter → Mask → Chunk
// Custom patterns
var options = new TextRefineOptions
{
RemoveBlankLines = true,
RemoveDuplicateLines = true,
RemoveEmptyListItems = true, // Supports Korean markers: ㅇ, ○, ●, □, ■
TrimLines = true,
RemovePatterns = [@"^#\s*댓글\s*$", @"^\[광고\].*$"]
};
Presets for specific content types:
| Preset | Use |
|---|---|
TextRefineOptions.Light |
Minimal: empty list markers, trim, collapse blanks |
TextRefineOptions.Standard |
Default: Light + remove duplicate lines |
TextRefineOptions.ForWebContent |
Web pages: aggressive cleaning |
TextRefineOptions.ForKorean |
Korean: removes 댓글 sections, copyright lines |
TextRefineOptions.ForPdfContent |
PDF text: removes page numbers |
TextRefineOptions.ForTokenOptimization / ForAggressiveTokenOptimization |
Reduce tokens before embedding |
PII Masking
// Enable PII masking
var curator = new Curator()
.WithPIIMasking();
// Mask PII in text
var result = curator.MaskPII("Contact: 010-1234-5678, Email: test@example.com");
Console.WriteLine(result.MaskedText);
// Output: "Contact: [PHONE], Email: [EMAIL]"
Multilingual National ID Detection
// Auto-detect PII for all supported languages
var curator = new Curator()
.WithPIIMasking(PIIMaskingOptions.Default);
var result = curator.MaskPII("SSN: 536-22-1234, RRN: 901231-1234567");
// Output: "SSN: [NATIONAL_ID], RRN: [NATIONAL_ID]"
// Detect for specific language
var koreanCurator = new Curator()
.WithPIIMasking(PIIMaskingOptions.ForLanguage("ko"));
var krResult = koreanCurator.MaskPII("주민등록번호: 901231-1234567");
// Output: "주민등록번호: [NATIONAL_ID]"
// Validates using Modulo-11 checksum algorithm
// Detect for multiple languages
var multiCurator = new Curator()
.WithPIIMasking(PIIMaskingOptions.ForLanguages("en-US", "ko", "pt-BR"));
Hierarchical Chunking
var curator = new Curator()
.WithChunkingOptions(opt =>
{
opt.Strategy = ChunkingStrategy.Hierarchical;
opt.MaxChunkSize = 1024;
});
var chunks = await curator.ChunkAsync(markdownText);
foreach (var chunk in chunks)
{
// Access hierarchy information
var level = chunk.Metadata.Custom?["HierarchyLevel"];
var parentId = chunk.Metadata.Custom?["ParentId"];
var sectionPath = chunk.Location.SectionPath;
Console.WriteLine($"[Level {level}] {sectionPath}");
Console.WriteLine(chunk.Content);
}
Full Pipeline Processing
// Complete preprocessing pipeline
var curator = new Curator()
.WithTextRefinement(TextRefineOptions.Standard)
.WithContentFiltering()
.WithPIIMasking(PIIMaskingOptions.ForLanguages("en", "ko", "ja"))
.WithChunkingOptions(ChunkOptions.ForMediumContext); // ForRAG needs UseEmbedder(...) first
// Process: Refine → Filter → Mask PII → Chunk
var result = await curator.PreprocessAsync(text);
Console.WriteLine(result.GetSummary());
// e.g. "Produced 5 chunk(s). Text refined. Filtered 2 content item(s). Masked 3 PII item(s)."
Semantic Chunking
// Requires an IEmbedder implementation (e.g., OpenAI, LMSupply, etc.)
var curator = new Curator()
.UseEmbedder(myEmbedder) // Inject your IEmbedder implementation
.WithChunkingOptions(opt =>
{
opt.Strategy = ChunkingStrategy.Semantic;
opt.SemanticSimilarityThreshold = 0.5f;
});
var chunks = await curator.ChunkAsync(text);
// Chunks at natural semantic boundaries
Chunking Strategies
| Strategy | Description | Embedder Required | Best For |
|---|---|---|---|
Auto |
Automatically select best strategy | No | General use |
Sentence |
Split by sentence boundaries | No | Conversational text |
Paragraph |
Split by paragraph boundaries | No | Structured documents |
Token |
Split by token count | No | Consistent chunk sizes |
Semantic |
Split by semantic similarity | Yes | RAG applications |
Hierarchical |
Preserve document structure with parent-child relationships | No | Technical docs, Markdown |
Large Document Processing
For documents with 50K+ tokens, use hierarchical chunking with the ForLargeDocument preset:
// Use the preset for large documents
var curator = new Curator()
.WithChunkingOptions(ChunkOptions.ForLargeDocument);
var chunks = await curator.ChunkAsync(largeDocument);
// Access hierarchy metadata
foreach (var chunk in chunks)
{
var level = chunk.Metadata.Custom?["HierarchyLevel"];
var sectionPath = chunk.Location.SectionPath;
Console.WriteLine($"[Level {level}] {sectionPath}: {chunk.Content.Length} chars");
}
See Large Document Chunking Guide for detailed configuration options.
Supported Languages
FluxCurator includes language profiles for accurate sentence detection and token estimation. A tag with a region
(zh-TW, pt-BR, en-US) uses the profile of its language:
| Language | Code | Features |
|---|---|---|
| Korean | ko |
습니다체/해요체 endings, Korean sentence markers |
| English | en |
Standard sentence boundaries |
| Japanese | ja |
Japanese sentence endings (。、!?) |
| Chinese (Simplified and Traditional) | zh |
Chinese punctuation |
| Spanish | es |
Spanish punctuation |
| French | fr |
French punctuation |
| German | de |
German punctuation |
| Portuguese | pt |
Portuguese punctuation |
| Russian | ru |
Cyrillic support |
| Arabic | ar |
RTL and Arabic punctuation |
| Hindi | hi |
Devanagari script support |
| Vietnamese | vi |
Latin with Vietnamese diacritics |
| Thai | th |
Thai script (no word spaces) |
PII Types Supported
Global PII Types
PIIMaskingOptions.TypesToMask selects which built-in detectors run. Its default, PIIType.Common, covers Email,
Phone, CreditCard and NationalId; the other types below are detected only when you include them (for example
TypesToMask = PIIType.All, or the PIIMaskingOptions.Strict preset).
| Type | Description | Validation |
|---|---|---|
Email |
Email addresses, including non-ASCII local parts and domains (홍길동@회사.kr) |
Local-part and TLD validation |
Phone |
Korean mobile, landline (incl. (02) 555-1234) and service numbers; US (234) 567-8900 / 234-567-8900; + international |
Prefix and length validation |
CreditCard |
Credit card numbers | Luhn algorithm |
IPAddress |
IPv4 and IPv6 addresses | Format validation |
BankAccount |
An IBAN; a 10-16 digit account number (plain or 110-234-567890) after an account word (account, acct, 계좌, 이체, …) on the same line |
IBAN mod-97; context word for domestic numbers |
Passport |
M12345678, the Korean 2021 form M123A4567, or nine digits, after a passport word (passport, 여권, 旅券, …) |
Context word |
UrlCredential |
The secret inside a URL: the value of token, access_token, api_key, key, sig, password, secret, code, … parameters and the password of scheme://user:password@host. Only the secret is masked: …/users?token=[CREDENTIAL]&page=2 |
Credential-named parameter |
HardwareAddress |
MAC addresses 00:1A:2B:3C:4D:5E, 00-1A-…, 001a.2b3c.4d5e |
One separator throughout; all-zero and broadcast skipped |
DriversLicense, PersonName, Address, TaxId and SocialSecurityNumber are categories for detectors you
register: no built-in detector reports them (US SSN, UK NINO and the other national numbers report NationalId).
PIIMasker.CoveredTypes returns the types a masker can actually find with its options and registered detectors —
assert on it when a masking policy requires a type.
Every built-in detector matches whole values only: a run of digits or ASCII letters is never reported in part, so
timestamps, order numbers, hashes and UUIDs are not masked as phone numbers or IDs. A value written directly
next to text in a script without spaces (연락처010-1234-5678로) is still detected. A bare run of ten digits
is not treated as a US phone number, nor a bare 15xxxxxx as a service number; write them with separators.
A value the text marks as a machine identifier is not reported, whatever its shape: the value of a key in
PIIMaskingOptions.NonPiiKeys (uid=, auid=, pid=, port=, "ts": …, journald fields - see DefaultNonPiiKeys;
add your own keys or clear the set), and a segment of a compound identifier such as a journald cursor
(s=4bf9…;i=43b37;m=0161431588;t=65c9…). The same number under another key (phone=, "user":) is still masked.
Other values are read by shape: a run that happens to have a valid date and checksum (a timestamp, an order number)
can still be reported as an ID or a card number; raise MinConfidence, add its key to NonPiiKeys, or filter such
fields before masking. A custom detector deriving from
PIIDetectorBase gets the same behaviour by placing TokenStart/TokenEnd (or, for numeric IDs,
NumberStart/NumberEnd) around its Pattern.
National ID Types by Country
| Country | Language Code | ID Type | Validation |
|---|---|---|---|
| Korea | ko |
Resident Registration Number (RRN) | Modulo-11 checksum |
| USA | en-US |
Social Security Number (SSN) | Area/Group validation |
| UK | en-GB |
National Insurance Number (NINO) | Prefix/Suffix validation |
| Japan | ja |
My Number | Check digit validation |
| China | zh-CN |
ID Card Number | ISO 7064 MOD 11-2 |
| Germany | de |
Personalausweis / Steuer-ID | Check digit validation |
| France | fr |
INSEE Number | Modulo-97 validation |
| Spain | es |
DNI / NIE | Check letter validation |
| Brazil | pt-BR |
CPF | Dual Modulo-11 |
| Italy | it |
Codice Fiscale | Check character validation |
| India | hi |
Aadhaar | Verhoeff checksum |
| Canada | en-CA |
Social Insurance Number (SIN) | Luhn algorithm |
| Australia | en-AU |
Tax File Number (TFN) | Weighted sum mod 11 |
Configuration Options
ChunkOptions
var options = new ChunkOptions
{
Strategy = ChunkingStrategy.Sentence,
TargetChunkSize = 512,
MinChunkSize = 100,
MaxChunkSize = 1024,
OverlapSize = 50,
LanguageCode = "ko", // null = auto-detect
PreserveSentences = true,
PreserveParagraphs = true,
SemanticSimilarityThreshold = 0.5f
};
// Or start from a preset (compared below)
var fixedSize = ChunkOptions.FixedSize(256, 32); // Fixed token size with overlap
Preset Comparison by Embedding Model
Choose the right preset based on your embedding model's context window:
| Preset | Target | Max | Overlap | Strategy | Best For |
|---|---|---|---|---|---|
Default |
512 | 1024 | 50 | Auto | General purpose |
ForRAG |
512 | 1024 | 64 | Semantic | RAG with semantic chunking (requires an IEmbedder) |
ForShortContext |
200 | 256 | 25 | Sentence | MiniLM, BGE-small (256 tokens) |
ForMediumContext |
400 | 512 | 50 | Sentence | e5, BGE-base, GTE (512 tokens) |
ForLongContext |
1024 | 2048 | 128 | Paragraph | OpenAI, Cohere (8K+ tokens) |
ForKorean |
400 | 800 | 40 | Sentence | Korean text processing |
ForLargeDocument |
768 | 1536 | 128 | Hierarchical | 50K+ token documents |
Note: All sizes are in estimated tokens, not characters. See FAQ for character-to-token conversion ratios.
Masking Strategies
| Strategy | Example Output |
|---|---|
Token |
[EMAIL], [PHONE] |
Asterisk |
every character replaced by * (****************) |
Character |
every character replaced by X |
Redact |
[REDACTED] |
Partial |
jo**@ex****.com |
Hash |
[HASH:a1b2c3d4] |
Remove |
(empty) |
Extensibility
FluxCurator is designed for extensibility. You can add custom PII detectors for your specific needs.
Custom PII Detector
Implement IPIIDetector or extend PIIDetectorBase for pattern-based detection:
using FluxCurator;
using FluxCurator.Core.Domain;
using FluxCurator.Core.Infrastructure.PII;
// Register and use via PIIMasker
var masker = new PIIMasker(PIIMaskingOptions.Default);
masker.RegisterDetector(new EmployeeIdDetector());
var result = masker.Mask("Contact employee EMP-123456 for details.");
// Output: "Contact employee [PII] for details."
// Or register directly on the curator
var curator = new Curator()
.WithPIIMasking()
.RegisterPIIDetector(new EmployeeIdDetector());
var curatorResult = curator.MaskPII("Contact employee EMP-123456 for details.");
// Output: "Contact employee [PII] for details."
public class EmployeeIdDetector : PIIDetectorBase
{
public override PIIType PIIType => PIIType.Custom;
public override string Name => "Employee ID Detector";
// Pattern: EMP-123456
protected override string Pattern => @"EMP-\d{6}";
protected override bool ValidateMatch(string value, out float confidence)
{
confidence = 0.95f;
return true;
}
}
Custom National ID Detector
Extend NationalIdDetectorBase to add a country the library does not cover (the 13 in the table above are built in
and registered by default):
using FluxCurator.Core.Domain;
using FluxCurator.Core.Infrastructure.PII;
using FluxCurator.Core.Infrastructure.PII.NationalId;
// Register with the national ID registry
var registry = new NationalIdRegistry();
registry.Register(new SingaporeNricDetector());
var masker = new PIIMasker(PIIMaskingOptions.ForLanguage("en-SG"), registry);
public class SingaporeNricDetector : NationalIdDetectorBase
{
public override string LanguageCode => "en-SG";
public override string NationalIdType => "NRIC";
public override string FormatDescription => "Letter, 7 digits, check letter";
public override string CountryName => "Singapore";
public override string Name => "Singapore NRIC Detector";
// Pattern: S1234567D
protected override string Pattern => @"[STFGM]\d{7}[A-Z]";
protected override bool ValidateMatch(string value, out float confidence)
{
var normalized = NormalizeValue(value);
if (normalized.Length != 9)
{
confidence = 0.0f;
return false;
}
// A real detector verifies the check letter here
confidence = 0.9f;
return true;
}
}
Dependency Injection with Custom Detectors
using FluxCurator.Core.Infrastructure.PII;
using FluxCurator.Core.Infrastructure.PII.NationalId;
// Register a registry that also knows your own detectors
services.AddSingleton<INationalIdRegistry>(sp =>
{
var registry = new NationalIdRegistry(); // the built-in detectors are already registered
registry.Register(new SingaporeNricDetector());
return registry;
});
// Register PIIMasker with custom registry
services.AddScoped<IPIIMasker>(sp =>
{
var registry = sp.GetRequiredService<INationalIdRegistry>();
var options = PIIMaskingOptions.ForLanguages("en", "hi");
return new PIIMasker(options, registry);
});
Extension Points Summary
| Interface | Base Class | Purpose |
|---|---|---|
IPIIDetector |
PIIDetectorBase |
General PII detection (email, phone, custom) |
INationalIdDetector |
NationalIdDetectorBase |
Country-specific national ID detection |
INationalIdRegistry |
NationalIdRegistry |
Manage and lookup national ID detectors |
IPIIMasker |
PIIMasker |
Coordinate detection and masking |
Integration with Iyulab Ecosystem
FluxCurator is part of the Iyulab open-source RAG ecosystem:
┌─────────────────────────────────────────────────────────────┐
│ Foundation Layer │
├─────────────────────────────────────────────────────────────┤
│ LMSupply LMSupply FluxCurator FluxImprover│
│ (Embeddings) (Reranking) (Chunking) (LLM-based) │
└───────────┬───────────────────────────┬─────────────────────┘
│ │
▼ ▼
┌───────────────────────────────────────────────────────────────┐
│ Processing Layer │
├───────────────────────────────────────────────────────────────┤
│ FileFlux (Document Processing) WebFlux (Web) │
└───────────────────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Storage Layer │
├───────────────────────────────────────────────────────────────┤
│ FluxIndex (Vector DB) │
└───────────────────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Application Layer │
├───────────────────────────────────────────────────────────────┤
│ Your application │
└───────────────────────────────────────────────────────────────┘
FileFlux Integration
FileFlux delegates its chunking to FluxCurator through IChunkerFactory; the adapter types live in the FileFlux
package. See FileFlux Integration.
Project Structure
FluxCurator/
├── src/
│ ├── FluxCurator.Core/ # Core (depends only on Flux.Abstractions): interfaces (Core/), models (Domain/), chunkers, PII, filters, languages
│ └── FluxCurator/ # Main package: Curator, DI registration, semantic chunking (requires IEmbedder)
└── docs/ # Guides
Documentation
- Getting Started - Installation and basic usage
- Chunking Strategies - Detailed guide for each strategy
- Large Document Chunking - Processing 50K+ token documents
- Dependency Injection - DI configuration and patterns
- FileFlux Integration - Integration with FileFlux
FAQ
Q: How do I process large documents (100K+ tokens)?
Use ChunkingStrategy.Hierarchical with the ForLargeDocument preset. It recognizes document structure (#, ##, ###) and chunks at section boundaries while preserving context.
var curator = new Curator()
.WithChunkingOptions(ChunkOptions.ForLargeDocument);
Q: My chunks are too small/too large. How do I fix this?
Chunk balancing is on by default (EnableChunkBalancing); adjust the size limits:
var options = new ChunkOptions
{
MinChunkSize = 200, // Merge chunks smaller than this
MaxChunkSize = 1024, // Split chunks larger than this
EnableChunkBalancing = true
};
Q: I set MaxChunkSize=512 but my chunks are 1,500+ characters. Is this a bug?
No, this is expected behavior. MaxChunkSize specifies estimated tokens, not characters. FluxCurator estimates tokens using language-specific heuristics without an actual tokenizer:
| Language | Chars/Token | 512 tokens ≈ |
|---|---|---|
| English | ~4 | ~2,048 chars |
| Korean | ~1.5-2 | ~750-1,024 chars |
| Chinese/Japanese | ~1.5-2 | ~750-1,024 chars |
| Mixed content | weighted avg | varies |
For mixed-language content (e.g., Korean with English terms), chunk sizes fall between the language-specific ranges. If you need precise token counts, verify with your actual tokenizer after chunking.
Q: How do I preserve context across chunk boundaries?
Increase the overlap size. For technical documents, 15-20% overlap is recommended:
var options = new ChunkOptions
{
TargetChunkSize = 512,
OverlapSize = 100 // ~20% overlap
};
Q: Does FluxCurator support document structure from FileFlux?
Yes, through the text itself: FileFlux emits Markdown with headings, and ChunkingStrategy.Hierarchical chunks at those heading boundaries. There is no separate structure-hint API in FluxCurator.
Q: How do I process Korean documents (DOCX, PPTX, HWP)?
FluxCurator processes text, not document files directly. Use FileFlux to extract text first, then chunk with FluxCurator:
// 1. Extract the text with FileFlux (see the FileFlux README); here it is already in `extractedText`
// 2. Chunk the extracted Korean text
var curator = new Curator()
.WithTextRefinement(TextRefineOptions.ForKorean)
.WithChunkingOptions(opt =>
{
opt.Strategy = ChunkingStrategy.Hierarchical;
opt.LanguageCode = "ko"; // Use Korean language profile
opt.EnableChunkBalancing = true;
});
var chunks = await curator.ChunkAsync(extractedText);
See Large Document Chunking Guide for detailed Korean document processing examples.
Contributing
Contributions are welcome — open an issue or a pull request. Release notes are in CHANGELOG.md.
License
MIT License - see LICENSE for details.
Part of the Iyulab Open Source Ecosystem
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- Flux.Abstractions (>= 0.27.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on FluxCurator.Core:
| Package | Downloads |
|---|---|
|
FluxCurator
Text preprocessing library for RAG pipelines: PII masking, content filtering, and intelligent chunking including semantic chunking with Korean language support. |
|
|
WebFlux
A .NET SDK for preprocessing web content for RAG (Retrieval-Augmented Generation) systems |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.17.0 | 0 | 10/16/2026 |
| 0.16.0 | 55 | 10/15/2026 |
| 0.15.0 | 57 | 10/15/2026 |
| 0.14.0 | 2,237 | 10/7/2026 |
| 0.13.0 | 829 | 10/7/2026 |
| 0.12.0 | 417 | 10/6/2026 |
| 0.11.0 | 563 | 10/6/2026 |
| 0.10.4 | 3,841 | 10/2/2026 |
| 0.10.3 | 472 | 10/1/2026 |
| 0.10.2 | 1,350 | 9/30/2026 |
| 0.10.1 | 253 | 9/30/2026 |
| 0.10.0 | 354 | 9/29/2026 |
| 0.9.1 | 5,051 | 9/23/2026 |
| 0.9.0 | 1,409 | 9/21/2026 |
| 0.8.3 | 1,541 | 9/17/2026 |
| 0.8.2 | 1,122 | 9/14/2026 |
| 0.8.1 | 4,533 | 8/2/2026 |
| 0.8.0 | 1,116 | 7/17/2026 |
| 0.7.6 | 461 | 5/21/2026 |
| 0.7.5 | 2,472 | 4/1/2026 |