A flexible Graph RAG package with advanced ingestion and augmentation strategies
Everything you need for advanced knowledge graph retrieval and augmentation
Local, Global, Naive, Self, and Hybrid query modes for flexible knowledge retrieval tailored to your specific use case.
Decorator-based DI framework with @service, @singleton_service, and @inject_config for clean, configurable architecture.
Override base classes and configure via JSON to customize LLMs, storage, chunking, extraction, and more.
Runs with lightweight local implementations (Ollama, NetworkX, JSON storage) out of the box. Perfect for experiments.
Comprehensive test suite covering all components and strategies ensuring reliability and stability.
Beautiful terminal, HTML, and Markdown renderers for all models using Rich and custom formatters.
Vector-based similarity search for nodes, edges, and chunks with multiple storage backend options.
Easily swap LLM implementations (Ollama, OpenAI, Anthropic, etc.) via simple configuration changes.
GraphML export for visualization with Gephi, yEd, or Cytoscape. Open to graph databases and advanced visualization tools.
Choose the right retrieval strategy for your query pattern
Entity-centric retrieval that extracts low-level keywords from queries and matches against nodes. Retrieves relationship neighborhoods around primary nodes.
Relationship-centric retrieval that extracts high-level keywords and matches against edges. Retrieves node endpoints of matching edges.
Traditional RAG approach with direct semantic similarity search on text chunks. No graph structure utilized.
Combines Local and Global strategies in parallel, merging and deduplicating the combined context for comprehensive coverage.
LLM generates context on its own without retrieval. Useful for baseline comparisons and scenarios where no relevant context exists.
Hierarchical configuration with service variants for runtime component swapping
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())