A modular system for extracting knowledge graphs from text using multiple LLM backends. Supports Gemini API, Ollama, and LM Studio with a unified client abstraction layer.
- Multi-Backend LLM Support — Gemini API (cloud), Ollama (local), LM Studio (local)
- Knowledge Graph Extraction — Structured triples (head-relation-tail) with source grounding via langextract
- Graph Augmentation — Iterative strategies to bridge disconnected components
- Origin Tracking — Every triple tagged as
explicit(extracted) orcontextual(augmented) - Interactive Visualizations — Cytoscape.js interactive network graphs with node dragging, search/filter, and context menus; entity text highlighting
- Domain System — Customizable prompts, examples, and schema constraints per knowledge domain
- Pipeline Orchestration — YAML-driven or flag-based multi-step pipelines
- Multiple I/O Formats — JSONL, JSON, CSV input; GraphML output
# Using Makefile (recommended)
make install
# Or manually
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"Requires Python 3.11+.
make install auto-detects the first available interpreter that is already
Python 3.11+ among common commands such as python3.13, python3.12,
python3.11, python3, and python.
If your supported interpreter lives under a different name or path, use
make install PYTHON=/path/to/python3.11.
| Backend | Requirement |
|---|---|
| Gemini | API key from Google AI Studio — set GOOGLE_API_KEY in .env |
| Ollama | Ollama running locally (ollama serve) |
| LM Studio | LM Studio with server enabled and model loaded |
# Interactive mode (REPL)
kgb
# One-shot extraction
kgb extract --input data.jsonl --domain legal --client gemini
# Full pipeline via script
bash scripts/test_single_extraction_gemini.shThe typical workflow follows four steps:
Text → Extract → Augment → Convert → Visualize
↓ ↓ ↓ ↓
JSON JSON+ GraphML HTML
(explicit) (contextual)
Extracts source-grounded triples using langextract. Each triple has character positions in the original text.
kgb extract \
--input data/legal/legal_background.jsonl \
--domain legal \
--client gemini \
--output-dir outputs/runGenerates bridging triples (tagged contextual) to connect disconnected graph components.
kgb augment connectivity \
--input data/legal/legal_background.jsonl \
--domain legal \
--client gemini \
--output-dir outputs/run \
--max-disconnected 1 \
--max-iterations 5kgb convert --input outputs/run/extracted_json --output outputs/run/graphml# Network topology (nodes colored by origin: Extracted/Augmented/Both)
kgb visualize network --input outputs/run/graphml --output outputs/run/network_viz
# Entity highlighting in source text
kgb visualize extraction \
--input data/legal/legal_background.jsonl \
--triples outputs/run/extracted_json \
--output outputs/run/extraction_vizkgb run-pipeline --config kgb/pipeline/configs/legal_ollama.yamlOr with flags:
kgb run-pipeline --input data.jsonl --domain legal --client ollama \
--extract --augment --convert --visualize| Command | Description |
|---|---|
kgb extract |
Extract knowledge graph triples from text |
kgb augment connectivity |
Bridge disconnected graph components |
kgb convert |
Convert JSON triples to GraphML |
kgb visualize network |
Interactive network graph (Cytoscape.js) |
kgb visualize extraction |
Entity highlights in source text (langextract) |
kgb run-pipeline |
Run multi-step pipeline (YAML or flags) |
kgb list domains |
List available knowledge domains |
kgb list clients |
List registered LLM clients |
kgb list pipelines |
List built-in YAML pipeline configs |
Common options (most commands):
| Option | Description |
|---|---|
--input, -i |
Input file (JSONL, JSON, or CSV) |
--output-dir, -o |
Output directory |
--domain, -d |
Knowledge domain (default, legal) |
--client, -c |
LLM backend (gemini, ollama, lmstudio) |
--model |
Model identifier (uses provider default if omitted) |
--mode, -m |
Extraction mode (open, constrained) |
--record-ids |
Filter specific record IDs |
--temp |
LLM temperature (default: 0.0) |
--workers |
Max parallel workers |
--timeout |
Request timeout in seconds |
Each run produces a timestamped directory:
test_outputs/single_extraction_20260318_101048/
├── metadata.json # Run configuration and timestamp
├── extracted_json/ # JSON triples (explicit + contextual)
│ └── UKSC-2009-0143.json
├── graphml/ # NetworkX-compatible GraphML
│ └── UKSC-2009-0143.graphml
├── network_viz/ # Interactive Cytoscape.js HTML
│ └── UKSC-2009-0143.html
└── extraction_viz/ # Entity highlighting HTML
└── UKSC-2009-0143.html
[
{
"head": "Sigma Finance Corporation",
"relation": "is a type of",
"tail": "structured investment vehicle (SIV)",
"inference": "explicit",
"justification": null
},
{
"head": "financial markets",
"relation": "impacted",
"tail": "Sigma Finance Corporation",
"inference": "contextual",
"justification": "The text states the impact on financial markets..."
}
]inference: "explicit"— Directly extracted from text with source groundinginference: "contextual"— Inferred during augmentation to bridge components
kgb/
├── __main__.py # Typer CLI + interactive REPL
├── builder/ # Graph construction logic
│ ├── extraction.py # Triple extraction (uses langextract)
│ ├── augmentation.py # Strategy registry + connectivity strategy
│ └── validation.py # Schema validation + prompt rendering
├── clients/ # LLM client abstraction
│ ├── base.py # BaseLLMClient (extract + augment interface)
│ ├── config.py # ClientConfig dataclass
│ ├── factory.py # ClientFactory + @client() decorator
│ ├── defaults.py # Provider defaults loader
│ ├── configs/ # Provider default JSON files
│ └── providers/ # Implementations
│ ├── gemini.py # Google Gemini (native SDK)
│ ├── ollama.py # Ollama (OpenAI-compatible)
│ └── lmstudio.py # LM Studio (OpenAI-compatible)
├── domains/ # Knowledge domain resources
│ ├── base.py # KnowledgeDomain + DomainComponent
│ ├── registry.py # @domain() decorator + registry
│ ├── models.py # Triple, InferenceType, DomainSchema
│ ├── default/ # Generic domain
│ └── legal/ # Legal domain (prompts, examples, schema)
├── io/ # Input/output handling
│ ├── readers/ # JSONL, JSON, CSV loaders
│ └── writers/ # GraphML converter
├── visualization/ # HTML visualization engines
│ ├── graph_viz.py # Cytoscape.js network graphs (origin coloring)
│ └── text_viz.py # langextract entity highlighting
└── pipeline/ # Pipeline orchestration
├── runner.py # PipelineRunner
├── context.py # PipelineContext
├── config.py # YAML config loader
├── steps/ # Pipeline step implementations
└── configs/ # Built-in YAML pipeline configs
The system is orchestrated by the Pipeline, driven by the CLI. I/O Readers load input data, the Client communicates with LLM backends, the Builder manages extraction/augmentation logic, and the Domain provides prompts, examples, and schema constraints. I/O Writers produce GraphML output and the Visualization module generates interactive HTML views.
The Builder module coordinates extraction and augmentation. Extract uses langextract for source-grounded triples; Augment generates bridging triples via direct LLM inference. Both rely on the Client abstraction (BaseLLMClient / ClientFactory) and the Domain system (KnowledgeDomain / DomainRegistry) for prompts, few-shot examples, and entity/relation type constraints. The Validation subsystem normalizes and validates triples against schema constraints.
┌─────────────────────────────────────────────────────────────────────┐
│ KGB Extension Points │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────────────┐ │
│ │ I/O Readers │ │ I/O Writers │ │ Visualization │ │
│ │ add-dataset- │ │ add-converter │ │ add-visualization │ │
│ │ format │ │ │ │ │ │
│ └───────┬───────┘ └───────┬───────┘ └────────────┬────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Pipeline Runner │ │
│ │ load → build → convert → visualize │ │
│ └─────────────────────┬────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Builder │ │
│ │ extract_triples() → augment_triples() │ │
│ └───────┬────────────────┬───────────────────────┬─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ LLM Clients │ │ Domains │ │ Augmentation Strategies │ │
│ │add-llm-client│ │ add-domain │ │ add-augmentation- │ │
│ │ │ │ │ │ strategy │ │
│ └──────────────┘ └─────────────┘ └──────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
| Pattern | Where | Mechanism |
|---|---|---|
| Factory + Registry | Clients | @client("name") decorator → ClientFactory.create(config) |
| Registry | Domains | @domain("name") decorator → get_domain("name") |
| Strategy + Registry | Augmentation | @register_strategy("name") → augment_triples(strategy="name") |
| Component | Domains | DomainComponent lazy-loads prompt + examples per activity |
All LLM backends implement two core methods:
| Method | Purpose | Source grounding | Used by |
|---|---|---|---|
extract() |
Extract triples from text | Yes (char positions) | builder/extraction.py |
augment() |
Generate bridging triples | No | builder/augmentation.py |
from kgb.clients import ClientFactory, ClientConfig
config = ClientConfig(client_type="ollama", model_id="gemma3:1b")
client = ClientFactory.create(config)
# Source-grounded extraction
triples = client.extract(text="...", prompt_description="...")
# Inference-based augmentation (no char positions)
bridges = client.augment(text="...", prompt_description="...", format_type=Triple)Domains bundle prompts, examples, and schema constraints per knowledge area:
kgb/domains/legal/
├── __init__.py # @domain("legal") class LegalDomain
├── extraction/
│ ├── prompt_open.md # Open extraction prompt
│ ├── prompt_constrained.md # Constrained extraction prompt
│ └── examples.json # Few-shot extraction examples
├── augmentation/
│ └── connectivity/ # Strategy-specific resources
│ ├── prompt.md
│ └── examples.json
└── schema.json # Entity/relation type constraints
from kgb.domains import get_domain, list_available_domains
print(list_available_domains()) # ['default', 'legal']
domain = get_domain("legal", extraction_mode="open")
prompt = domain.extraction.prompt
examples = domain.extraction.examples
schema = domain.schema # DomainSchema with entity_types, relation_types| Client | Type | Default Model | Setup |
|---|---|---|---|
gemini |
Cloud API | gemini-2.0-flash | Set GOOGLE_API_KEY in .env |
ollama |
Local | llama3.1 | ollama serve + ollama pull <model> |
lmstudio |
Local | (loaded model) | Start LM Studio server on port 1234 |
# .env file (auto-loaded)
GOOGLE_API_KEY=your-gemini-api-key
# Or export directly
export GOOGLE_API_KEY="your-key"- Nodes colored by origin: blue (Extracted), amber (Augmented), violet (Both)
- Augmented edges rendered with dashed lines
- Layouts: cose (force-directed), circle, dagre (hierarchical) — switchable in-browser
- Node dragging, search/filter bar, right-click context menus
- Path finder, export (PNG/SVG/JSON)
- Dark mode support
- Hover tooltips with node degree, origin, and edge attributes
- Source text with color-coded entity spans
- Animated highlight transitions
- Grouping by entity type or relation
- Augmented entities visually distinguished
The main extension points are in the codebase itself:
- Add providers under
kgb/clients/providers/with defaults inkgb/clients/configs/ - Add domains under
kgb/domains/<name>/ - Add augmentation strategies in
kgb/builder/augmentation.py - Add readers under
kgb/io/readers/ - Add writers under
kgb/io/writers/ - Add visualizations under
kgb/visualization/
# Gemini (requires API key)
bash scripts/test_single_extraction_gemini.sh
# Ollama (requires local server)
bash scripts/test_single_extraction_ollama.sh
# LM Studio (requires local server)
bash scripts/test_single_extraction_lmstudio.shConfigure hyperparameters at the top of each script (model, temperature, record IDs, etc.).
kgb list domains
kgb list clients
kgb extract --input data/legal/legal_background.jsonl --domain legal --client ollama --model gemma3:1b --record-ids UKSC-2009-0143# Build
make docker-build
# Smoke test the installed CLI in the image
docker run --rm kg-constructor list clients
# Interactive session
make docker-start
# Background dev container
make docker-dev
make docker-stopThe image installs the packaged CLI. Repository helper scripts and local datasets are
meant to be run from a mounted checkout, for example via make docker-start.
See LICENSE file for details.