Noel-Alex/Oracle

0

stars

1

commits

Python

primary language

Jun 2, 2026

updated

README

ORACLE

Omnidirectional Research Agent with Corpus Logic and Epistemological Engine

ORACLE is a distributed research system with a Docker-based core stack, an optional GPU inference layer, a FastAPI command-center backend, and a Vite frontend.

What It Runs

  • Core infra: PostgreSQL, NATS JetStream, LiteLLM, FalkorDB, Qdrant, worker
  • Optional GPU services: tei-emb, gliner, coref (pronoun resolution), relex (inline relation extraction), vllm (deprecated)
  • Optional monitoring: Prometheus, Grafana, Loki, Promtail, exporters
  • Command Center: FastAPI backend on :8010, Vite frontend on :5173

Development Status (2026-06-03)

PhaseStatusNotes
Phase 0 — KG Schema✅ CompleteTyped multi-label entities, pattern-based relationship inference, profile system
Phase 1 — Entity Resolution⚠️ PartialExact/fuzzy/alias resolution works; context-aware disambiguation not yet implemented
Phase 2 — Tool Wiring✅ Complete12 tools (8 base + 4 domain) wired to FalkorDB, Qdrant, TEI, LiteLLM
Phase 3 — Investigation Pipeline✅ CompleteDynamic loop with 8 LangGraph nodes, MERGE-based graph write-back, report engine
Phase 4 — Agentic AI⚠️ Partial6 specialists with ModelRouter; structured output parsing and debate engine pending
Phase 5 — Scale & Production⚠️ PartialMonitoring stack ready; sequential GPU benchmark added; FalkorDB write bottleneck under investigation

Benchmark status: 30/30 quality checks pass ✅ | 6/6 stress tests pass ✅ | Throughput benchmarks run ✅ | GPU sequential benchmark: parse/chunk/embed functional, extraction recovered, graph writes bottlenecked |

Production readiness: See PRODUCTION_READINESS.md for a detailed assessment. Bottom line: the code is solid but needs ~1 week of integration hardening before 300GB PDF ingestion.

Verified Startup

These are the commands verified against the current repo.

# 1. Clone and configure
git clone <repo-url> oracle
cd oracle
cp .env.example .env
# Edit .env and set at least:
#   POSTGRES_PASSWORD
#   NATS_AUTH_TOKEN
#   LITELLM_MASTER_KEY
#   one provider key such as OPENROUTER_API_KEY

# 2. Start the core Docker stack
docker compose up -d

# 3. Initialize NATS JetStream streams
docker compose --profile manual-start up nats-init

# 4. Optional: start monitoring
docker compose -f monitoring/docker-compose.monitoring.yml up -d

# 5. Optional: start GPU services
docker compose --profile gpu up -d tei-emb gliner coref relex

# Verify GPU services:
curl -fsS http://127.0.0.1:8001/health   # GLiNER entity extraction (joint-encoder, 304M params)
curl -fsS http://127.0.0.1:8003/health   # F-COREF pronoun resolution
curl -fsS http://127.0.0.1:8004/health   # GLiNER-Relex inline relation extraction (317 rel/sec)

# 6. Start the Command Center backend
set -a
source .env
export ORACLE_LEDGER_DSN="postgresql://oracle:${POSTGRES_PASSWORD}@localhost:15432/oracle"
export FALKORDB_HOST=localhost
export FALKORDB_PORT=17379
.venv/bin/python command-center/api/main.py

# 7. In another terminal, start the frontend
cd command-center/frontend
npm run dev -- --host 0.0.0.0

Verified URLs

  • Command Center frontend: http://localhost:5173
  • Command Center backend health: http://localhost:8010/health
  • FalkorDB browser: http://localhost:13500
  • LiteLLM: http://localhost:4000/health/liveliness
  • NATS monitor: http://localhost:8222
  • Qdrant: http://localhost:16333/dashboard
  • Grafana: http://localhost:13000
  • Prometheus: http://localhost:19090
  • TEI (embeddings): http://localhost:7997
  • GLiNER (entity extraction): http://localhost:8001
  • coref: http://localhost:8003
  • Relex (inline relation extraction): http://localhost:8004
  • vLLM (deprecated): http://localhost:8002

Verified Ingestion Smoke Test

This smoke pass exercises file discovery, parsing, chunking, embeddings, Qdrant writes, and entity extraction:

mkdir -p tmp/oracle-smoke-corpus
cat <<'EOF' > tmp/oracle-smoke-corpus/sample_text.txt
ORACLE smoke test input.
This file verifies local file discovery and text parsing.
EOF

cat <<'EOF' > tmp/oracle-smoke-corpus/machine_learning.md
# Machine Learning Smoke Document

Embeddings map text into vectors.
Entity extraction should identify organizations, locations, and dates when present.
EOF

.venv/bin/python tests/test_complete_e2e.py \
  --corpus tmp/oracle-smoke-corpus \
  --output tmp/oracle-smoke-output

Expected result: Overall: PASS

Throughput Validation

The primary kept end-to-end throughput validation is:

ORACLE_E2E_SKIP_LITELLM=1 .venv/bin/python tests/test_e2e_without_litellm.py

This writes a report to reports/e2e-without-litellm-report.md and a machine-readable result to tests/e2e_results_no_litellm.json.

Benchmark Suite

Offline Benchmarks (no external services required)

# Quality checks (7 categories, 30 individual checks)
python -m oracle.benchmarks.quality_checks

# Stress tests (6 scenarios: large corpus, connection pool, deep traversal, etc.)
python -m oracle.benchmarks.stress_test --quick

# Throughput benchmarks (parse, chunk, embed, extract, graph write, full pipeline)
python -m oracle.benchmarks.throughput_benchmarks --iterations 5

# Cross-module import verification
python -c "from oracle.investigation_graph import build_investigation_graph; print('OK')"
python -c "from oracle.tools.executors import wire_all_executors; print('OK')"
python -c "from oracle.tools.new_tools import wire_domain_executors; print('OK')"
python -c "from oracle.knowledge_graph.investigation_writer import write_investigation_graph; print('OK')"

Sequential GPU Benchmark (requires running Docker stack)

Runs each pipeline stage in isolation to measure per-stage GPU throughput without resource contention. Designed for 12 GB VRAM cards where TEI (~2.5 GB), GLiNER (~0.6 GB), and Relex (~3 GB) together exceed VRAM.

# Requires: Docker stack running, corpus selected
# Select corpus first (one-time):
python benchmarks/select_corpus.py --n 250

# Run benchmark:
python benchmarks/benchmark_sequential_gpu.py [--docs N]

# Results written to reports/benchmarks/

Phases:

  1. Parse + Chunk (CPU only, no GPU services)
  2. Embedding → Qdrant (TEI only)
  3. Extraction → Graph writes (GLiNER only, Relex disabled)
  4. FalkorDB verification (node/edge counts, orphan detection)

Historical targets (from prior joint-encoder benchmark):

  • TEI Embedding: 466 chunks/sec (batch 12, GPU 67%)
  • GLiNER Extraction: 803 chunks/sec (batch 256, GPU 63%)

Tool System

ORACLE has 12 typed tools with Pydantic-validated I/O and pluggable backends:

Base tools (8): graph_search, vector_search, entity_lookup, claim_trace, source_fetch, contradiction_check, model_call, report_note

Domain tools (4): temporal_query, relationship_path, passenger_list, financial_flow

All tools have real backend executors (FalkorDB, Qdrant, TEI, LiteLLM) wired via wire_all_executors() and wire_domain_executors(). See oracle/tools/executors.py and oracle/tools/new_tools.py.

Knowledge Graph

Typed Schema

Entities are stored with multi-label nodes (:Entity:Person, :Entity:Organization, :Entity:Location, etc.) enabling type-specific queries. Relationships are typed (KNOWS, PASSENGER_ON, LOCATED_IN, OWNS, etc.) using pattern-based inference — no LLM costs during ingestion.

Key modules:

  • Entity classifier (oracle/ingestion/entity_classifier.py): Maps GLiNER labels to concrete graph node types with sub-classification (org_type, loc_type, event_type)
  • Relationship inference (oracle/ingestion/relationship_inference.py): 27 pattern rules across all entity pair combinations
  • Graph writer (oracle/knowledge_graph/__init__.py): MERGE-based idempotent writes with dynamic Cypher

Graph Visualization

The Command Center renders the full knowledge graph (12K+ nodes, growing) using a pre-computed server-side layout:

# Pre-compute graph layout, PageRank, and Louvain communities
.venv/bin/python scripts/precompute_graph_layout.py [--force] [--iterations 50]

This runs spring_layout on all nodes, computes PageRank and community assignments, and writes coordinates (viz_x, viz_y, viz_pagerank, viz_community) back to FalkorDB. The frontend reads these pre-computed positions and renders via WebGL — no client-side physics, instant load.

Graph page features:

  • Three-tier LOD: dots → circles → labels based on zoom level
  • Chunk nodes never show text (prevents clutter)
  • Community-based coloring
  • Node type filtering and search
  • Scrollable in page flow (doesn't block viewport)

Relevant endpoints:

  • GET /api/graph/export?limit=N — Type-proportional graph data with edges
  • GET /api/graph/summary — Node/edge counts and top entities
  • GET /api/graph/health — Database connectivity status

Investigation Pipeline

The investigation system uses a LangGraph state machine with 8 nodes and conditional routing:

planner → tool_dispatcher → evidence_collector → hypothesis_generator
                                                       ↓
                                                  orchestrator
                                                   ↙  ↓  ↘
                                        [challenger] [loop] [reporter → completer]
  • Dynamic loop: Orchestrator decides whether to challenge, gather more evidence, or report
  • PostgreSQL checkpointing: Investigations survive restarts via AsyncPostgresSaver
  • Graph write-back: Findings, claims, evidence, hypotheses, and contradictions persisted to FalkorDB

Key modules:

  • Investigation graph (oracle/investigation_graph.py): 1,019 lines, 8 nodes with conditional edges
  • Investigation writer (oracle/knowledge_graph/investigation_writer.py): MERGE-based artifact persistence
  • Report engine (oracle/reporting/report_engine.py): Confidence blending with provenance chains, exports to Markdown/HTML/PDF/DOCX

Corpus Profiles

Named profiles configure entity types, chunk sizes, and relationship rules per dataset:

from oracle.profiles import get_profile_for_corpus

profile = get_profile_for_corpus("epstein_files")  # or "bible_kjv", "default"

Profiles defined in oracle/profiles.py.

Relation Extraction (Inline, Encoder-Based)

Relation extraction now runs inline during the extraction phase via ExtractResultHandler — not as a separate post-hoc enrichment task. After GLiNER extracts entities from each chunk, GLiNER-Relex is called immediately to extract typed relationships between those entities. Pattern-based relationships (from relationship_inference.py's 27 rules) and Relex relationships are merged in dispatcher._merge_relationships() before writing to FalkorDB. This means typed edges (WORKS_FOR, FOUNDED, LOCATED_IN, PART_OF, COMPETITOR, etc.) flow end-to-end in a single ingestion pass — no separate enrichment worker needed.

Unlike the old vLLM pipeline (~0.04 pairs/sec autoregressive), Relex performs joint NER+relation extraction in a single encoder forward pass at 317 relations/sec — an ~8,000x speedup.

Key implementation:

  • ExtractResultHandler: Calls Relex API (:8004) inline after entity extraction, sending entity pairs with context text
  • dispatcher._merge_relationships(): Merges Relex typed relationships with pattern-inferred relationships, resolving conflicts by confidence
  • 34 zero-shot Relex relation types mapped to 13 FalkorDB edge types (WORKS_FOR, FOUNDED, LOCATED_IN, PART_OF, COMPETITOR, etc.)
  • Edges written with source:gliner_relex or source:pattern property for provenance tracking

No capability flag needed — relation extraction is part of the standard extraction capability. Ensure relex is running and ORACLE_RELEX_URL is set (defaults to http://localhost:8004).

Deprecated: post-hoc enrichment (STREAM_ENRICHMENT)

The old post-hoc enrichment pipeline (NATS oracle.tasks.enrichment.graph stream, graph_enrichment worker capability, separate GraphResultHandler enrichment pass) is deprecated. It is gated behind ORACLE_ENABLE_DEPRECATED_ENRICHMENT=1. Do not use in new deployments — all relationship extraction now happens inline.

Optional pre-processing: F-COREF pronoun resolution

Add coref to the GPU stack for pronoun resolution before entity extraction (344 chunks/sec, 93ms latency):

docker compose --profile gpu up -d coref

Set ORACLE_ENABLE_COREF=true to enable in the ingestion pipeline.

Benchmarking

Relex integration tests require the Relex service running:

# Relex integration tests — health, load, accuracy, throughput, no-hallucination
python tests/test_relex_enrichment.py

# Legacy vLLM tests (only if vLLM is running and ORACLE_ENABLE_DEPRECATED_ENRICHMENT=1)
python tests/test_vllm_enrichment.py --smoke

Architecture At A Glance

Controller
  Postgres   NATS   LiteLLM   FalkorDB   Qdrant   Worker

Optional GPU
  tei-emb    gliner    coref    relex (inline RE)

Command Center
  FastAPI backend (:8010)
  Vite frontend (:5173)

Current Caveat

The current dockerized worker container reports healthy on :18080, but it also logs recurring NATS fetch_error messages after startup. A local ingestion smoke pass still succeeds, but the README does not currently treat the worker log noise as a clean operational state. See TROUBLESHOOTING.md.

Documentation

DocumentPurpose
INSTALL.mdFull bring-up runbook
WORKER_GUIDE.mdWorker-specific setup
ENV_REFERENCE.mdEnvironment variables
ARCHITECTURE.mdSystem layout, data flow, and graph viz pipeline
DEVELOPMENT.mdLocal development workflow
PRODUCTION_READINESS.mdHonest audit of what's ready and what's not
TROUBLESHOOTING.mdKnown failures and fixes
monitoring/README.mdMonitoring stack
command-center/frontend/README.mdFrontend runbook
docs/COMMAND_CENTER_PRODUCT_SPEC.mdCommand Center vision and design
docs/ENGINEERING_DEFINITION_OF_DONE.mdCompletion criteria
docs/ENRICHMENT_PIPELINE.mdGraph enrichment pipeline (encoder-based, GLiNER-Relex)
PIPELINE_TECHNICAL_REPORT.mdComplete pipeline technical reference (for AI/developer onboarding)

Last updated: 2026-06-03

Contributors

Noel-Alex

1 commits

Noel-Alex/Oracle

0

stars

1

commits

Python

primary language

Jun 2, 2026

updated

README

ORACLE

Omnidirectional Research Agent with Corpus Logic and Epistemological Engine

ORACLE is a distributed research system with a Docker-based core stack, an optional GPU inference layer, a FastAPI command-center backend, and a Vite frontend.

What It Runs

  • Core infra: PostgreSQL, NATS JetStream, LiteLLM, FalkorDB, Qdrant, worker
  • Optional GPU services: tei-emb, gliner, coref (pronoun resolution), relex (inline relation extraction), vllm (deprecated)
  • Optional monitoring: Prometheus, Grafana, Loki, Promtail, exporters
  • Command Center: FastAPI backend on :8010, Vite frontend on :5173

Development Status (2026-06-03)

PhaseStatusNotes
Phase 0 — KG Schema✅ CompleteTyped multi-label entities, pattern-based relationship inference, profile system
Phase 1 — Entity Resolution⚠️ PartialExact/fuzzy/alias resolution works; context-aware disambiguation not yet implemented
Phase 2 — Tool Wiring✅ Complete12 tools (8 base + 4 domain) wired to FalkorDB, Qdrant, TEI, LiteLLM
Phase 3 — Investigation Pipeline✅ CompleteDynamic loop with 8 LangGraph nodes, MERGE-based graph write-back, report engine
Phase 4 — Agentic AI⚠️ Partial6 specialists with ModelRouter; structured output parsing and debate engine pending
Phase 5 — Scale & Production⚠️ PartialMonitoring stack ready; sequential GPU benchmark added; FalkorDB write bottleneck under investigation

Benchmark status: 30/30 quality checks pass ✅ | 6/6 stress tests pass ✅ | Throughput benchmarks run ✅ | GPU sequential benchmark: parse/chunk/embed functional, extraction recovered, graph writes bottlenecked |

Production readiness: See PRODUCTION_READINESS.md for a detailed assessment. Bottom line: the code is solid but needs ~1 week of integration hardening before 300GB PDF ingestion.

Verified Startup

These are the commands verified against the current repo.

# 1. Clone and configure
git clone <repo-url> oracle
cd oracle
cp .env.example .env
# Edit .env and set at least:
#   POSTGRES_PASSWORD
#   NATS_AUTH_TOKEN
#   LITELLM_MASTER_KEY
#   one provider key such as OPENROUTER_API_KEY

# 2. Start the core Docker stack
docker compose up -d

# 3. Initialize NATS JetStream streams
docker compose --profile manual-start up nats-init

# 4. Optional: start monitoring
docker compose -f monitoring/docker-compose.monitoring.yml up -d

# 5. Optional: start GPU services
docker compose --profile gpu up -d tei-emb gliner coref relex

# Verify GPU services:
curl -fsS http://127.0.0.1:8001/health   # GLiNER entity extraction (joint-encoder, 304M params)
curl -fsS http://127.0.0.1:8003/health   # F-COREF pronoun resolution
curl -fsS http://127.0.0.1:8004/health   # GLiNER-Relex inline relation extraction (317 rel/sec)

# 6. Start the Command Center backend
set -a
source .env
export ORACLE_LEDGER_DSN="postgresql://oracle:${POSTGRES_PASSWORD}@localhost:15432/oracle"
export FALKORDB_HOST=localhost
export FALKORDB_PORT=17379
.venv/bin/python command-center/api/main.py

# 7. In another terminal, start the frontend
cd command-center/frontend
npm run dev -- --host 0.0.0.0

Verified URLs

  • Command Center frontend: http://localhost:5173
  • Command Center backend health: http://localhost:8010/health
  • FalkorDB browser: http://localhost:13500
  • LiteLLM: http://localhost:4000/health/liveliness
  • NATS monitor: http://localhost:8222
  • Qdrant: http://localhost:16333/dashboard
  • Grafana: http://localhost:13000
  • Prometheus: http://localhost:19090
  • TEI (embeddings): http://localhost:7997
  • GLiNER (entity extraction): http://localhost:8001
  • coref: http://localhost:8003
  • Relex (inline relation extraction): http://localhost:8004
  • vLLM (deprecated): http://localhost:8002

Verified Ingestion Smoke Test

This smoke pass exercises file discovery, parsing, chunking, embeddings, Qdrant writes, and entity extraction:

mkdir -p tmp/oracle-smoke-corpus
cat <<'EOF' > tmp/oracle-smoke-corpus/sample_text.txt
ORACLE smoke test input.
This file verifies local file discovery and text parsing.
EOF

cat <<'EOF' > tmp/oracle-smoke-corpus/machine_learning.md
# Machine Learning Smoke Document

Embeddings map text into vectors.
Entity extraction should identify organizations, locations, and dates when present.
EOF

.venv/bin/python tests/test_complete_e2e.py \
  --corpus tmp/oracle-smoke-corpus \
  --output tmp/oracle-smoke-output

Expected result: Overall: PASS

Throughput Validation

The primary kept end-to-end throughput validation is:

ORACLE_E2E_SKIP_LITELLM=1 .venv/bin/python tests/test_e2e_without_litellm.py

This writes a report to reports/e2e-without-litellm-report.md and a machine-readable result to tests/e2e_results_no_litellm.json.

Benchmark Suite

Offline Benchmarks (no external services required)

# Quality checks (7 categories, 30 individual checks)
python -m oracle.benchmarks.quality_checks

# Stress tests (6 scenarios: large corpus, connection pool, deep traversal, etc.)
python -m oracle.benchmarks.stress_test --quick

# Throughput benchmarks (parse, chunk, embed, extract, graph write, full pipeline)
python -m oracle.benchmarks.throughput_benchmarks --iterations 5

# Cross-module import verification
python -c "from oracle.investigation_graph import build_investigation_graph; print('OK')"
python -c "from oracle.tools.executors import wire_all_executors; print('OK')"
python -c "from oracle.tools.new_tools import wire_domain_executors; print('OK')"
python -c "from oracle.knowledge_graph.investigation_writer import write_investigation_graph; print('OK')"

Sequential GPU Benchmark (requires running Docker stack)

Runs each pipeline stage in isolation to measure per-stage GPU throughput without resource contention. Designed for 12 GB VRAM cards where TEI (~2.5 GB), GLiNER (~0.6 GB), and Relex (~3 GB) together exceed VRAM.

# Requires: Docker stack running, corpus selected
# Select corpus first (one-time):
python benchmarks/select_corpus.py --n 250

# Run benchmark:
python benchmarks/benchmark_sequential_gpu.py [--docs N]

# Results written to reports/benchmarks/

Phases:

  1. Parse + Chunk (CPU only, no GPU services)
  2. Embedding → Qdrant (TEI only)
  3. Extraction → Graph writes (GLiNER only, Relex disabled)
  4. FalkorDB verification (node/edge counts, orphan detection)

Historical targets (from prior joint-encoder benchmark):

  • TEI Embedding: 466 chunks/sec (batch 12, GPU 67%)
  • GLiNER Extraction: 803 chunks/sec (batch 256, GPU 63%)

Tool System

ORACLE has 12 typed tools with Pydantic-validated I/O and pluggable backends:

Base tools (8): graph_search, vector_search, entity_lookup, claim_trace, source_fetch, contradiction_check, model_call, report_note

Domain tools (4): temporal_query, relationship_path, passenger_list, financial_flow

All tools have real backend executors (FalkorDB, Qdrant, TEI, LiteLLM) wired via wire_all_executors() and wire_domain_executors(). See oracle/tools/executors.py and oracle/tools/new_tools.py.

Knowledge Graph

Typed Schema

Entities are stored with multi-label nodes (:Entity:Person, :Entity:Organization, :Entity:Location, etc.) enabling type-specific queries. Relationships are typed (KNOWS, PASSENGER_ON, LOCATED_IN, OWNS, etc.) using pattern-based inference — no LLM costs during ingestion.

Key modules:

  • Entity classifier (oracle/ingestion/entity_classifier.py): Maps GLiNER labels to concrete graph node types with sub-classification (org_type, loc_type, event_type)
  • Relationship inference (oracle/ingestion/relationship_inference.py): 27 pattern rules across all entity pair combinations
  • Graph writer (oracle/knowledge_graph/__init__.py): MERGE-based idempotent writes with dynamic Cypher

Graph Visualization

The Command Center renders the full knowledge graph (12K+ nodes, growing) using a pre-computed server-side layout:

# Pre-compute graph layout, PageRank, and Louvain communities
.venv/bin/python scripts/precompute_graph_layout.py [--force] [--iterations 50]

This runs spring_layout on all nodes, computes PageRank and community assignments, and writes coordinates (viz_x, viz_y, viz_pagerank, viz_community) back to FalkorDB. The frontend reads these pre-computed positions and renders via WebGL — no client-side physics, instant load.

Graph page features:

  • Three-tier LOD: dots → circles → labels based on zoom level
  • Chunk nodes never show text (prevents clutter)
  • Community-based coloring
  • Node type filtering and search
  • Scrollable in page flow (doesn't block viewport)

Relevant endpoints:

  • GET /api/graph/export?limit=N — Type-proportional graph data with edges
  • GET /api/graph/summary — Node/edge counts and top entities
  • GET /api/graph/health — Database connectivity status

Investigation Pipeline

The investigation system uses a LangGraph state machine with 8 nodes and conditional routing:

planner → tool_dispatcher → evidence_collector → hypothesis_generator
                                                       ↓
                                                  orchestrator
                                                   ↙  ↓  ↘
                                        [challenger] [loop] [reporter → completer]
  • Dynamic loop: Orchestrator decides whether to challenge, gather more evidence, or report
  • PostgreSQL checkpointing: Investigations survive restarts via AsyncPostgresSaver
  • Graph write-back: Findings, claims, evidence, hypotheses, and contradictions persisted to FalkorDB

Key modules:

  • Investigation graph (oracle/investigation_graph.py): 1,019 lines, 8 nodes with conditional edges
  • Investigation writer (oracle/knowledge_graph/investigation_writer.py): MERGE-based artifact persistence
  • Report engine (oracle/reporting/report_engine.py): Confidence blending with provenance chains, exports to Markdown/HTML/PDF/DOCX

Corpus Profiles

Named profiles configure entity types, chunk sizes, and relationship rules per dataset:

from oracle.profiles import get_profile_for_corpus

profile = get_profile_for_corpus("epstein_files")  # or "bible_kjv", "default"

Profiles defined in oracle/profiles.py.

Relation Extraction (Inline, Encoder-Based)

Relation extraction now runs inline during the extraction phase via ExtractResultHandler — not as a separate post-hoc enrichment task. After GLiNER extracts entities from each chunk, GLiNER-Relex is called immediately to extract typed relationships between those entities. Pattern-based relationships (from relationship_inference.py's 27 rules) and Relex relationships are merged in dispatcher._merge_relationships() before writing to FalkorDB. This means typed edges (WORKS_FOR, FOUNDED, LOCATED_IN, PART_OF, COMPETITOR, etc.) flow end-to-end in a single ingestion pass — no separate enrichment worker needed.

Unlike the old vLLM pipeline (~0.04 pairs/sec autoregressive), Relex performs joint NER+relation extraction in a single encoder forward pass at 317 relations/sec — an ~8,000x speedup.

Key implementation:

  • ExtractResultHandler: Calls Relex API (:8004) inline after entity extraction, sending entity pairs with context text
  • dispatcher._merge_relationships(): Merges Relex typed relationships with pattern-inferred relationships, resolving conflicts by confidence
  • 34 zero-shot Relex relation types mapped to 13 FalkorDB edge types (WORKS_FOR, FOUNDED, LOCATED_IN, PART_OF, COMPETITOR, etc.)
  • Edges written with source:gliner_relex or source:pattern property for provenance tracking

No capability flag needed — relation extraction is part of the standard extraction capability. Ensure relex is running and ORACLE_RELEX_URL is set (defaults to http://localhost:8004).

Deprecated: post-hoc enrichment (STREAM_ENRICHMENT)

The old post-hoc enrichment pipeline (NATS oracle.tasks.enrichment.graph stream, graph_enrichment worker capability, separate GraphResultHandler enrichment pass) is deprecated. It is gated behind ORACLE_ENABLE_DEPRECATED_ENRICHMENT=1. Do not use in new deployments — all relationship extraction now happens inline.

Optional pre-processing: F-COREF pronoun resolution

Add coref to the GPU stack for pronoun resolution before entity extraction (344 chunks/sec, 93ms latency):

docker compose --profile gpu up -d coref

Set ORACLE_ENABLE_COREF=true to enable in the ingestion pipeline.

Benchmarking

Relex integration tests require the Relex service running:

# Relex integration tests — health, load, accuracy, throughput, no-hallucination
python tests/test_relex_enrichment.py

# Legacy vLLM tests (only if vLLM is running and ORACLE_ENABLE_DEPRECATED_ENRICHMENT=1)
python tests/test_vllm_enrichment.py --smoke

Architecture At A Glance

Controller
  Postgres   NATS   LiteLLM   FalkorDB   Qdrant   Worker

Optional GPU
  tei-emb    gliner    coref    relex (inline RE)

Command Center
  FastAPI backend (:8010)
  Vite frontend (:5173)

Current Caveat

The current dockerized worker container reports healthy on :18080, but it also logs recurring NATS fetch_error messages after startup. A local ingestion smoke pass still succeeds, but the README does not currently treat the worker log noise as a clean operational state. See TROUBLESHOOTING.md.

Documentation

DocumentPurpose
INSTALL.mdFull bring-up runbook
WORKER_GUIDE.mdWorker-specific setup
ENV_REFERENCE.mdEnvironment variables
ARCHITECTURE.mdSystem layout, data flow, and graph viz pipeline
DEVELOPMENT.mdLocal development workflow
PRODUCTION_READINESS.mdHonest audit of what's ready and what's not
TROUBLESHOOTING.mdKnown failures and fixes
monitoring/README.mdMonitoring stack
command-center/frontend/README.mdFrontend runbook
docs/COMMAND_CENTER_PRODUCT_SPEC.mdCommand Center vision and design
docs/ENGINEERING_DEFINITION_OF_DONE.mdCompletion criteria
docs/ENRICHMENT_PIPELINE.mdGraph enrichment pipeline (encoder-based, GLiNER-Relex)
PIPELINE_TECHNICAL_REPORT.mdComplete pipeline technical reference (for AI/developer onboarding)

Last updated: 2026-06-03

Contributors

Noel-Alex

1 commits

Languages

Python

83.9%

TypeScript

8.8%

CSS

5.5%

Shell

1.1%