KNWL

A flexible Graph RAG package with advanced ingestion and augmentation strategies

Python 3.10+ MIT License v1.7.1

Key Features

Everything you need for advanced knowledge graph retrieval and augmentation

๐ŸŽฏ

Five Graph RAG Strategies

Local, Global, Naive, Self, and Hybrid query modes for flexible knowledge retrieval tailored to your specific use case.

๐Ÿ’‰

Dependency Injection

Decorator-based DI framework with @service, @singleton_service, and @inject_config for clean, configurable architecture.

๐Ÿ”Œ

Protocol-Based & Extensible

Override base classes and configure via JSON to customize LLMs, storage, chunking, extraction, and more.

๐Ÿš€

No External Services Required

Runs with lightweight local implementations (Ollama, NetworkX, JSON storage) out of the box. Perfect for experiments.

๐Ÿงช

Extensively Tested

Comprehensive test suite covering all components and strategies ensuring reliability and stability.

๐ŸŽจ

Rich Output Formatting

Beautiful terminal, HTML, and Markdown renderers for all models using Rich and custom formatters.

๐Ÿ”

Semantic Search

Vector-based similarity search for nodes, edges, and chunks with multiple storage backend options.

๐Ÿค–

Any LLM

Easily swap LLM implementations (Ollama, OpenAI, Anthropic, etc.) via simple configuration changes.

๐Ÿ“Š

Graph Visualization

GraphML export for visualization with Gephi, yEd, or Cytoscape. Open to graph databases and advanced visualization tools.

Graph RAG Strategies

Choose the right retrieval strategy for your query pattern

Local Strategy

Entity-centric retrieval that extracts low-level keywords from queries and matches against nodes. Retrieves relationship neighborhoods around primary nodes.

๐Ÿ“Œ Use Case: Questions about specific entities or concepts and their immediate relationships

Global Strategy

Relationship-centric retrieval that extracts high-level keywords and matches against edges. Retrieves node endpoints of matching edges.

๐Ÿ”— Use Case: Questions about relationships, connections, or patterns between entities

Naive Strategy

Traditional RAG approach with direct semantic similarity search on text chunks. No graph structure utilized.

๐Ÿ“„ Use Case: Simple fact-finding or when graph structure isn't beneficial

Hybrid Strategy

Combines Local and Global strategies in parallel, merging and deduplicating the combined context for comprehensive coverage.

๐ŸŒ Use Case: Complex queries benefiting from both entity and relationship context

Self Strategy

LLM generates context on its own without retrieval. Useful for baseline comparisons and scenarios where no relevant context exists.

๐Ÿ’ญ Use Case: Baseline comparisons and fallback when other strategies yield no results

Modular Architecture

Hierarchical configuration with service variants for runtime component swapping

LLM Services

  • Ollama
  • OpenAI
  • Anthropic
  • Configurable via JSON

Storage Backends

  • JSON Storage
  • ChromaDB
  • NetworkX
  • Memgraph

Text Processing

  • Tiktoken Chunking
  • Entity Extraction
  • Graph Extraction
  • Custom Prompts

Core Components

  • Framework Base
  • Dependency Injection
  • Service Registry
  • Config System

Quick Start

Get started with KNWL in minutes

# Install with uv (recommended)
uv add knwl

# Or with pip
pip install knwl
                    
from knwl import Knwl, print_knwl


async def main():
    knwl = Knwl()
    print(knwl)

    # add a fact
    await knwl.add_fact(
        "gravity",
        "Gravity is a universal force that attracts two bodies toward each other.",
        id="fact1",
    )

    assert (await knwl.node_exists("fact1")) is True

    # add another fact
    await knwl.add_fact(
        "photosynthesis",
        "Photosynthesis is the process by which green plants and some other organisms use sunlight to synthesize foods from carbon dioxide and water.",
        id="fact2",
    )
    # at least two nodes should be present now
    assert await knwl.node_count() >= 2

    # you can take the node returned from add_fact as an alternative
    found = await knwl.get_nodes_by_name("gravity")
    assert len(found) >= 1
    gravity_node = found[0]
    found = await knwl.get_nodes_by_name("photosynthesis")
    assert len(found) >= 1
    photosynthesis_node = found[0]
    # connect the two nodes
    await knwl.connect(
        source_name=gravity_node.name,
        target_name=photosynthesis_node.name,
        relation="Both are fundamental natural processes.",
    )

    # one edge
    assert await knwl.edge_count() >= 1

    # Augmentation will fetch the gravity node, despite that it does not directly relate to photosynthesis
    # Obviously, this 1-hop result would not happen with classic RAG since the vector similarity is too low
    augmentation = await knwl.augment("What is photosynthesis?")
    # pretty print the augmentation result
    print_knwl(augmentation)

    # graph RAG question-answer
    a = await knwl.ask("What is photosynthesis?")
    print_knwl(a.answer)


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())
Read Full Documentation