Skip to main content

🧩 Semantic Code Chunker

Semantic code chunking library optimized for LLM processing and RAG systems

PyPI version License: MIT Python 3.9+ Code style: black


📖 Table of Contents


🎯 Overview

Semantic Code Chunker is a Python library that intelligently splits source code into meaningful chunks based on Abstract Syntax Tree (AST) analysis. Unlike naive character-based chunking, this library understands the structure of your code and ensures that:

  • ✅ Functions are not split in half
  • ✅ Classes stay together with their methods
  • ✅ Context is preserved for LLM understanding
  • ✅ Configurable per-language policies

Perfect for RAG systems, code analysis tools, and AI-powered development assistants.


✨ Features

Feature Description
🌳 AST-Based Parsing Uses tree-sitter for accurate code structure understanding
🎯 Semantic Chunking Chunks by functions, classes, methods - not arbitrary positions
⚙️ Policy-Driven YAML configuration per language with fine-grained control
🌍 Multi-Language Supports 12+ languages including legacy systems (COBOL, JCL)
🔧 Fallback Mode Regex-based parsing when tree-sitter unavailable
📊 Rich Metadata Each chunk includes type, line numbers, function names
⚡ High Performance Optimized for large codebases

📦 Installation

Using pip

pip install rag-semantic-chunker
uv add rag-semantic-chunker

Development Installation

git clone https://github.com/zthanos/SemanticCodeChunker.git
cd SemanticCodeChunker
uv venv .venv
source .venv/bin/activate  # Linux/macOS
.venv\Scripts\activate     # Windows
uv pip install -e ".[dev]"

🚀 Quick Start

Basic Example

from semantic_chunker import SemanticCodeChunker

# Initialize with policy file
chunker = SemanticCodeChunker("policy.yaml")

# Sample Python code
code = """
def hello_world():
    print("Hello World")

class Calculator:
    def add(self, a, b):
        return a + b
    
    def subtract(self, a, b):
        return a - b
"""

# Chunk the code (max 500 chars per chunk for demo)
chunks = chunker.chunk_code(
    language="python", 
    source_code=code,
    context_size=500
)

print(f"Created {len(chunks)} chunks:")
for i, chunk in enumerate(chunks):
    print(f"\n--- Chunk {i+1} ---")
    print(chunk[:200] + "..." if len(chunk) > 200 else chunk)

Output

Created 2 chunks:

--- Chunk 1 ---
def hello_world():
    print("Hello World")

--- Chunk 2 ---
class Calculator:
    def add(self, a, b):
        return a + b
    
    def subtract(self, a, b):
        return a - b

🌍 Supported Languages

Language Parser Target Nodes Notes
Python python functions, classes, decorators Full support
Java java methods, classes, interfaces Enterprise ready
JavaScript javascript functions, arrow funcs, classes ES6+ supported
TypeScript typescript All JS + types, interfaces Type-aware
C c functions, structs, enums Systems programming
C++ cpp Classes, templates, namespaces OOP features
C# c_sharp Methods, properties, events .NET ecosystem
COBOL cobol Paragraphs, sections Legacy/mainframe ⚠️
JCL jcl Jobs, EXEC, DD statements Mainframe jobs ⚠️
CLIST clist Procedures, functions TSO/E commands ⚠️
Visual Basic vbnet Subs, functions, classes VB.NET support
Elixir elixir def, modules, protocols Functional paradigm

⚠️ Note: Legacy languages (COBOL, JCL, CLIST) use fallback regex parsing when tree-sitter grammars unavailable.


⚙️ Configuration

Policy File Structure

Create a policy.yaml file to configure chunking behavior:

defaults:
  max_context_size: 2048      # Default chars per chunk
  min_chunk_size: 100         # Minimum chunk size
  include_comments: true      # Include comments in chunks
  
languages:
  python:
    parser_name: "python"
    target_nodes:
      - "function_definition"
      - "class_definition"
      - "method_definition"
    
    metadata_fields:
      - "node_type"
      - "line_number"
      - "function_name"
      
  java:
    parser_name: "java"
    target_nodes:
      - "method_declaration"
      - "class_declaration"

Programmatic Configuration

from semantic_chunker.config import PolicyConfig, LanguageConfig

# Create custom configuration
config = PolicyConfig(
    max_context_size=4096,
    languages={
        "python": LanguageConfig(
            parser_name="python",
            target_nodes=["function_definition", "class_definition"]
        )
    }
)

chunker = SemanticCodeChunker(config=config)  # Pass config directly

📚 API Reference

SemanticCodeChunker

Main class for chunking code.

Constructor

def __init__(self, policy_path: str | None = None, config: PolicyConfig | None = None):
    """
    Initialize the chunker.
    
    Args:
        policy_path: Path to YAML policy file (optional)
        config: Direct PolicyConfig object (optional)
        
    Raises:
        FileNotFoundError: If policy_path doesn't exist
        ValueError: If configuration is invalid
    """

chunk_code() Method

def chunk_code(
    self, 
    language: str, 
    source_code: str, 
    context_size: int | None = None
) -> List[str]:
    """
    Chunk source code semantically.
    
    Args:
        language: Language identifier (e.g., 'python', 'java')
        source_code: Source code string to chunk
        context_size: Override default max chunk size
        
    Returns:
        List of chunk strings respecting semantic boundaries
        
    Example:
        >>> chunks = chunker.chunk_code("python", code, context_size=2048)
        >>> len(chunks)  # Number of chunks created
        5
    """

ParsedChunk Data Class

Detailed chunk information with metadata.

@dataclass
class ParsedChunk:
    code: str                    # The actual code content
    metadata: ChunkMetadata      # Metadata about the chunk
    
# Accessing metadata
chunk = chunks[0]
print(chunk.metadata.node_type)     # "function_definition"
print(chunk.metadata.line_number)   # 42
print(chunk.metadata.function_name) # "calculate_sum"

🔬 Advanced Usage

Getting Detailed Chunk Information

from semantic_chunker import SemanticCodeChunker
from semantic_chunker.parser import parse_and_chunk

# Get chunks with full metadata
chunks = parse_and_chunk(
    source_code=code,
    language="python",
    target_nodes=["function_definition", "class_definition"],
    max_context_size=2048
)

for chunk in chunks:
    print(f"Type: {chunk.metadata.node_type}")
    print(f"Lines: {chunk.metadata.line_number}-{chunk.metadata.end_line}")
    print(f"Function: {chunk.metadata.function_name}")
    print(f"Code:\n{chunk.code}\n")

Processing Large Files

def process_large_file(file_path: str, language: str) -> List[str]:
    """Process large files in streaming fashion."""
    
    with open(file_path, 'r', encoding='utf-8') as f:
        source_code = f.read()
        
    chunker = SemanticCodeChunker("policy.yaml")
    
    # Process with larger context for big files
    chunks = chunker.chunk_code(
        language=language,
        source_code=source_code,
        context_size=4096  # Larger chunks for complex codebases
    )
    
    return chunks

# Usage
chunks = process_large_file("src/main.py", "python")

Custom Language Support

from semantic_chunker.parser import ASTParser

class RustParser(ASTParser):
    """Custom parser for Rust (not yet in tree-sitter-languages)."""
    
    def _get_fallback_patterns(self) -> Dict[str, str]:
        return {
            "function": r'\bfn\s+(\w+)\s*\(',
            "struct": r'\bstruct\s+(\w+)',
            "impl_block": r'\bimpl\s+',
        }

# Use custom parser
rust_parser = RustParser("rust")

🏗️ Architecture

System Diagram

┌─────────────────────────────────────────────────────────────────┐
│                      Semantic Code Chunker                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐      │
│  │   Policy     │    │    AST       │    │   Chunk      │      │
│  │   Config     │───▶│    Parser    │───▶│   Extractor  │      │
│  │  (policy.yaml)│    │(tree-sitter) │    │              │      │
│  └──────────────┘    └──────────────┘    └──────────────┘      │
│         │                  │                    │               │
│         ▼                  ▼                    ▼               │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                   SemanticCodeChunker                    │   │
│  │                                                         │   │
│  │  chunk_code(language, source_code, context_size)       │   │
│  │                                                         │   │
│  └─────────────────────────────────────────────────────────┘   │
│                              │                                  │
│                              ▼                                  │
│                    ┌───────────────────┐                       │
│                    │  List[ParsedChunk]│                       │
│                    │                   │                       │
│                    │  - code: str      │                       │
│                    │  - metadata       │                       │
│                    └───────────────────┘                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Data Flow

  1. Load Policy → Read YAML configuration for target language
  2. Parse AST → tree-sitter creates Abstract Syntax Tree
  3. Query Nodes → Extract functions, classes, methods based on policy
  4. Group Chunks → Combine nodes respecting context_size limit
  5. Extract Metadata → Add line numbers, names, types to each chunk

🤝 Contributing

We welcome contributions! Here's how you can help:

Setting Up Development Environment

# Clone repository
git clone https://github.com/zthanos/SemanticCodeChunker.git
cd SemanticCodeChunker

# Create virtual environment
uv venv .venv
source .venv/bin/activate  # Linux/macOS

# Install with dev dependencies
uv pip install -e ".[dev]"

# Run tests
pytest tests/

# Format code
black src/semantic_chunker tests/

# Type checking
mypy src/semantic_chunker

Adding Support for New Language

  1. Add parser name to LANGUAGE_PARSERS in parser.py
  2. Add default config in config.py → get_default_languages()
  3. Add target nodes in example policy.yaml
  4. Write tests in tests/test_<language>.py

Running Tests

# All tests
pytest

# Specific test file
pytest tests/test_python_chunking.py

# With coverage
pytest --cov=src/semantic_chunker --cov-report=html

# Verbose output
pytest -v

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


📞 Support & Contact


Made with ❤️ for the AI and Developer Community

⭐ Star this repo if you find it helpful!

Metadata

Release files for rag-semantic-chunker 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rag-semantic-chunker 0.1.0
File Size Uploaded Provenance
rag_semantic_chunker-0.1.0.tar.gz 108.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for rag-semantic-chunker 0.1.0
File Interpreter ABI Platform
rag_semantic_chunker-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 132.9 kB

Release files / rag_semantic_chunker-0.1.0.tar.gz

Download URL rag_semantic_chunker-0.1.0.tar.gz
Size 108.2 kB
Tags Source
SHA-256 checksum
How to use checksums
85f155b48aa376c0c8dbb2bb8690995f6b9122b301120a43a26f86461190eb2d
BLAKE2b-256 checksum
How to use checksums
2d1c9f68c42b58e77ef9d2de666b5edd4f56b75e3b6692708536506fdff52e2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release files / rag_semantic_chunker-0.1.0-py3-none-any.whl

Download URL rag_semantic_chunker-0.1.0-py3-none-any.whl
Size 24.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ecd589b62bd490e40d314bd098cbeca521767809fdbac833f038ef125002cd8
BLAKE2b-256 checksum
How to use checksums
c5b2ed31332b54e4d4ae06a45043801f48f7e50a889372872b34e8e7be4da839
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Security for rag-semantic-chunker 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page