44
55** Intelligent Markdown document chunking for RAG systems with structural awareness**
66
7- [ ![ Version] ( https://img.shields.io/badge/version-2.0.0--a3 -orange.svg )] ( CHANGELOG.md )
7+ [ ![ Version] ( https://img.shields.io/badge/version-2.1.0 -orange.svg )] ( CHANGELOG.md )
88[ ![ License: MIT] ( https://img.shields.io/badge/License-MIT-yellow.svg )] ( https://opensource.org/licenses/MIT )
99[ ![ Python 3.12+] ( https://img.shields.io/badge/python-3.12+-blue.svg )] ( https://www.python.org/downloads/ )
1010[ ![ Dify Plugin] ( https://img.shields.io/badge/dify-1.9.0+-green.svg )] ( https://dify.ai/ )
@@ -51,17 +51,19 @@ This plugin is designed primarily for **RAG (Retrieval-Augmented Generation)** w
5151| Breaks code blocks mid-function | Preserves code blocks as atomic units |
5252| Loses header context | Maintains hierarchical section structure |
5353| Splits tables and lists | Keeps tables and lists intact |
54- | One-size-fits-all approach | 6 adaptive strategies based on content |
54+ | One-size-fits-all approach | 4 adaptive strategies based on content |
5555| No overlap support | Smart overlap for better retrieval |
56+ | ** Destroys list hierarchies** | ** Smart list grouping with context binding** |
5657
5758---
5859
5960## ✨ Features
6061
6162### 🎯 Adaptive Chunking
62- - ** 3 intelligent strategies** — automatic selection based on content analysis
63+ - ** 4 intelligent strategies** — automatic selection based on content analysis
64+ - ** List-Aware Strategy** — preserves nested list hierarchies and context (unique competitive advantage)
6365- ** Structure preservation** — headers, lists, tables, and code stay intact
64- - ** Smart overlap** — configurable context overlap between chunks
66+ - ** Adaptive overlap** — context window scales with chunk size (up to 35%)
6567
6668### 🔍 Deep Content Analysis
6769- ** AST parsing** — full Markdown syntax analysis
@@ -160,8 +162,8 @@ Add the chunker to your Dify workflow:
160162|-----------|------|---------|-------------|
161163| ` input_text` | string | required | Markdown text to chunk |
162164| `max_chunk_size` | number | 4096 | Maximum chunk size in characters |
163- | `chunk_overlap` | number | 200 | Overlap between consecutive chunks (see below ) |
164- | `strategy` | select | auto | Chunking strategy (auto/code_aware/structural/fallback) |
165+ | `chunk_overlap` | number | 200 | Base overlap size (adaptive : actual max = min(overlap_size, chunk_size * 0.35) ) |
166+ | `strategy` | select | auto | Chunking strategy (auto/code_aware/list_aware/ structural/fallback) |
165167| `include_metadata` | boolean | true | Embed metadata in chunk text (see below) |
166168
167169# ## Understanding `chunk_overlap`
@@ -306,10 +308,47 @@ chunker = MarkdownChunker()
306308chunks = chunker.chunk(text)
307309
308310# Force specific strategy
309- chunks = chunker.chunk(text, strategy="code")
311+ chunks = chunker.chunk(text, strategy="code_aware")
312+ chunks = chunker.chunk(text, strategy="list_aware") # For list-heavy docs
310313chunks = chunker.chunk(text, strategy="structural")
311314```
312315
316+ ### List-Aware Strategy Example
317+
318+ ``` python
319+ from markdown_chunker import MarkdownChunker, ChunkConfig
320+
321+ # Changelog processing with list-aware strategy
322+ changelog = """
323+ # Changelog
324+
325+ ## Version 2.0
326+
327+ New features:
328+ - **Authentication**
329+ - OAuth 2.0 support
330+ - SAML integration
331+ - MFA with SMS and authenticator apps
332+ - **Performance**
333+ - 50% f aster processing
334+ - Reduced memory usage
335+ """
336+
337+ config = ChunkConfig(
338+ max_chunk_size = 2000 ,
339+ list_ratio_threshold = 0.35 , # Lower threshold for changelogs
340+ list_count_threshold = 3 # Activate with fewer lists
341+ )
342+
343+ chunker = MarkdownChunker(config)
344+ chunks = chunker.chunk(changelog)
345+
346+ # Result: Nested items stay together, context preserved
347+ for chunk in chunks:
348+ print (f " Chunk type: { chunk.metadata[' content_type' ]} " )
349+ print (f " List depth: { chunk.metadata.get(' max_list_depth' , 0 )} " )
350+ ```
351+
313352### Configuration Profiles
314353
315354``` python
@@ -365,8 +404,57 @@ The system automatically selects the optimal strategy based on content analysis:
365404| Strategy | Priority | Activation Conditions | Best For |
366405| ----------| ----------| ----------------------| ----------|
367406| ** Code-Aware** | 1 (highest) | code_ratio ≥ 30% OR has code blocks/tables | Technical docs, API docs |
368- | ** Structural** | 2 | ≥3 headers | Documentation, guides |
369- | ** Fallback** | 3 (default) | Always applicable | Simple text, mixed content |
407+ | ** List-Aware** | 2 | list_ratio > 40% OR list_count ≥ 5 (AND logic for structured docs) | Changelogs, feature lists, task lists, outlines |
408+ | ** Structural** | 3 | ≥3 headers with hierarchy | Documentation, guides |
409+ | ** Fallback** | 4 (default) | Always applicable | Simple text, mixed content |
410+
411+ ### List-Aware Strategy: Competitive Advantage
412+
413+ ** Unique capability not found in competing solutions** (LangChain, LlamaIndex, Unstructured, Chonkie):
414+
415+ ** Intelligent List Processing:**
416+ - ** Hierarchy Preservation** — nested lists never split across depth levels
417+ - ** Context Binding** — introduction paragraphs automatically attached to their lists
418+ - ** Smart Grouping** — related list items kept together based on structure
419+ - ** Type Detection** — handles bullet lists, numbered lists, and checkboxes
420+
421+ ** Activation Logic:**
422+ ``` python
423+ # For documents with strong hierarchical structure (many headers):
424+ activate_if: list_ratio > 0.40 AND list_count >= 5
425+
426+ # For documents without strong structure:
427+ activate_if: list_ratio > 0.40 OR list_count >= 5
428+ ```
429+
430+ ** Perfect for:**
431+ - ** Changelogs** — version releases with nested changes
432+ - ** Feature lists** — product capabilities with descriptions
433+ - ** Task lists** — todos with sub-tasks and checkboxes
434+ - ** Outlines** — structured notes and cheatsheets
435+
436+ ** Example Input:**
437+ ``` markdown
438+ Our product includes:
439+
440+ - ** Authentication**
441+ - OAuth 2.0 support
442+ - SAML integration
443+ - MFA options
444+ - SMS
445+ - Authenticator app
446+ - Hardware keys
447+
448+ - ** Authorization**
449+ - Role-based access
450+ - Permission groups
451+ ```
452+
453+ ** Result:** Two coherent chunks preserving full hierarchies:
454+ - Chunk 1: Introduction + Authentication with all nested items
455+ - Chunk 2: Authorization with all nested items
456+
457+ ** Competitor Behavior:** Would split nested items, losing context and relationships.
370458
371459---
372460
@@ -382,19 +470,22 @@ config = ChunkConfig(
382470 max_chunk_size = 4096 , # Maximum chunk size (chars)
383471 min_chunk_size = 512 , # Minimum chunk size
384472
385- # Overlap
386- overlap_size = 200 , # Overlap size (0 = disabled)
473+ # Overlap (adaptive sizing)
474+ overlap_size = 200 , # Base overlap size (0 = disabled)
475+ # Actual max = min(overlap_size, chunk_size * 0.35)
387476
388477 # Behavior
389478 preserve_atomic_blocks = True , # Keep code blocks and tables intact
390479 extract_preamble = True , # Extract content before first header
391480
392481 # Strategy selection thresholds
393- code_threshold = 0.3 , # Code ratio for CodeAwareStrategy
394- structure_threshold = 3 , # Min headers for StructuralStrategy
482+ code_threshold = 0.3 , # Code ratio for CodeAwareStrategy
483+ structure_threshold = 3 , # Min headers for StructuralStrategy
484+ list_ratio_threshold = 0.40 , # List ratio for ListAwareStrategy
485+ list_count_threshold = 5 , # Min list blocks for ListAwareStrategy
395486
396487 # Override
397- strategy_override = None , # Force specific strategy (code_aware/structural/fallback)
488+ strategy_override = None , # Force specific strategy (code_aware/list_aware/ structural/fallback)
398489)
399490```
400491
@@ -519,10 +610,10 @@ class ChunkingResult:
519610
520611| Module | Description |
521612| --------| -------------|
522- | ` markdown_chunker_v2/parser.py ` | Markdown parsing and content analysis |
523- | ` markdown_chunker_v2/chunker.py ` | Main chunking orchestration |
524- | ` markdown_chunker_v2/strategies/ ` | 3 chunking strategies (code_aware, structural, fallback) |
525- | ` markdown_chunker_v2/config.py ` | Configuration (8 parameters) |
613+ | ` markdown_chunker_v2/parser.py ` | Markdown parsing and content analysis (with list detection) |
614+ | ` markdown_chunker_v2/chunker.py ` | Main chunking orchestration (with adaptive overlap) |
615+ | ` markdown_chunker_v2/strategies/ ` | 4 chunking strategies (code_aware, list_aware , structural, fallback) |
616+ | ` markdown_chunker_v2/config.py ` | Configuration (10 parameters) |
526617| ` markdown_chunker_v2/types.py ` | Core data types |
527618| ` provider/ ` | Dify plugin provider |
528619| ` tools/ ` | Dify plugin tools |
@@ -532,11 +623,15 @@ class ChunkingResult:
532623```
533624dify-markdown-chunker/
534625├── markdown_chunker_v2/ # Core library (v2.0 redesign)
535- │ ├── parser.py # Markdown parsing
536- │ ├── chunker.py # Main chunking logic
537- │ ├── config.py # Configuration (8 params)
626+ │ ├── parser.py # Markdown parsing (with list detection)
627+ │ ├── chunker.py # Main chunking logic (adaptive overlap)
628+ │ ├── config.py # Configuration (10 params)
538629│ ├── types.py # Data types
539- │ └── strategies/ # 3 chunking strategies
630+ │ └── strategies/ # 4 chunking strategies
631+ │ ├── code_aware.py # Code-heavy documents
632+ │ ├── list_aware.py # List-heavy documents
633+ │ ├── structural.py # Header-based structure
634+ │ └── fallback.py # Universal fallback
540635├── provider/ # Dify plugin provider
541636├── tools/ # Dify plugin tools
542637├── tests/ # Test suite (498 tests)
@@ -688,13 +783,26 @@ MIT License — see [LICENSE](LICENSE)
688783
689784## 📝 Changelog
690785
691- ** Current Version:** 2.0.2-a0 (December 2024)
786+ ** Current Version:** 2.0.2-a3 (December 2025)
787+
788+ ### v2.0.2-a3 - List-Aware Strategy & Adaptive Overlap
789+ - ** NEW: List-Aware Strategy** - intelligent processing for list-heavy documents
790+ - Preserves nested list hierarchies (parent-child relationships)
791+ - Automatic context binding (introduction paragraphs + lists)
792+ - Smart activation (AND logic for structured docs, OR for plain lists)
793+ - Handles bullet lists, numbered lists, and checkboxes
794+ - ** Adaptive overlap sizing** - context window scales with chunk size (up to 35%)
795+ - Small chunks: respects configured overlap_size
796+ - Large chunks: allows larger overlap (max 35% of chunk size)
797+ - Formula: ` min(overlap_size, chunk_size * 0.35) `
798+ - ** Enhanced list detection in parser** - full list analysis with hierarchy depth
799+ - ** Comprehensive test coverage** - 24 new tests for list strategy and overlap behavior
692800
693801### v2.0.2-a0 - Major Redesign
694- - ** Simplified architecture** : 3 strategies instead of 6
695- - ** Simplified configuration** : 8 parameters instead of 32
802+ - ** Simplified architecture** : 3 base strategies (code_aware, structural, fallback)
803+ - ** Simplified configuration** : 8 core parameters (expanded to 10 in a3)
696804- ** Consolidated types** : Single types.py module
697- - ** Improved test suite** : 445 focused property-based tests
805+ - ** Improved test suite** : 498 focused property-based tests
698806- ** Metadata-based overlap** : Context stored in metadata, not merged into content
699807
700808Full changelog: [ CHANGELOG.md] ( CHANGELOG.md )
0 commit comments