Skip to main content

Infona

Messy CSV, JSON, or text → one LLM schema pass → deterministic rows into Neo4j → ask in English (Cypher).

Luna (or your configured model) sees the file once and names types, attributes, relationships. Every cell maps through that schema via insert_facts. Then ask compiles English to Cypher on the populated graph.

infona.ai (waitlist / demo) · what's free · API

docs Apache-2.0 Python 3.12+ Neo4j npm @infona-ai/mcp tests

English question compiled to Cypher on Neo4j: AstraZeneca runs FLAURA2, indication NSCLC.

Ask in English, get Cypher, get the row. ingestask is the payoff. The graph is the trials.csv sample.


10-minute quickstart

Need: Docker + Node 20+ (for the infona CLI). A stranger gets a real answer with no API key.

Zero-key (cached-plan replay)

The prebuilt path replays a cached Cypher plan. It is not live inference. /ask stays always-LLM Cypher whenever a real model key (or INFONA_LLM_BASE_URL) is configured.

git clone https://github.com/infona-ai/infona-oss.git && cd infona-oss
cp .env.example .env          # leave OPENROUTER_API_KEY empty / as the placeholder
npm i -g @infona-ai/cli       # or use npx @infona-ai/cli in place of infona
./scripts/oss_up.sh           # Neo4j + API + loads the prebuilt trials graph
infona ask "Which Phase 3 NSCLC trials is AstraZeneca running?" --kg trials

That question should return FLAURA2, labelled as a cached-plan replay (not live inference). ./scripts/oss_up.sh compose-ups, waits until /health reports Neo4j up, writes ~/.infona/config.json, and runs ./scripts/load_prebuilt_trials.sh.

Reload the snapshot later (still no key):

./scripts/load_prebuilt_trials.sh
infona ask "Which Phase 3 NSCLC trials is AstraZeneca running?" --kg trials

Advertised bound stays 10 minutes. Measured 1 min 42 s cold on macOS 26.5.1 + Colima (Ubuntu 24.04 VM, 4 CPU, 6 GB; warm daemon, empty project, docker compose build --no-cache) from git clone to that zero-key ask. Native Linux was not measured. First-time neo4j:5-community pull is extra; 10 minutes still covers it.

Placeholder keys from .env.example (sk-or-...) count as no key. INFONA_ASK_CACHED_PLAN=1 forces replay even with a key (tests). =0 disables it.

1. Messy suppliers — URI merge

examples/suppliers-messy.csv is synthetic (Acme / Globex / Initech, fake tax IDs). No real customer data.

Schema inference needs a key (paste OPENROUTER_API_KEY=sk-or-... into .env):

infona ingest examples/suppliers-messy.csv --kg suppliers
infona er rebuild --kg suppliers

Ingest writes every row as its own Supplier fragment. er rebuild re-blocks the already-ingested graph and collapses fragment URIs (6→3). The headquarters and credit_rating lines below are an explanatory report: field winners are not written as the sole current graph value. Both HQ literals stay live; validity intervals are not on Neo4j yet.

Rebuilding entity resolution for suppliers…
  Supplier         6 → 3  (−3 fragments across 2 clusters)

  merge  https://graph.infona.ai/entities/Supplier/ERP-1001
         losers:     https://graph.infona.ai/entities/Supplier/CRM-4402, https://graph.infona.ai/entities/Supplier/DIR-8891
         reason:     signal-richest
         score:      1.00
         provenance: erp @ 2026-03-01T12:00:00+00:00 (source_of_truth)

  merge  https://graph.infona.ai/entities/Supplier/ERP-2001
         losers:     https://graph.infona.ai/entities/Supplier/CRM-5503
         reason:     signal-richest
         score:      1.00
         provenance: erp @ 2026-03-01T12:00:00+00:00 (source_of_truth)

  conflict  headquarters
         entity:     https://graph.infona.ai/entities/Supplier/ERP-1001
         winner:     Austin  (erp, source_of_truth, 2026-03-01T12:00:00+00:00)
         loser:      San Francisco  (directory, supplementary, 2024-06-01T00:00:00+00:00)
         reason:     authority

  unresolved  credit_rating
         entity:     https://graph.infona.ai/entities/Supplier/ERP-1001
         crm: BBB @ 2026-03-01T12:00:00+00:00 (source_of_truth)
         erp: A @ 2026-03-01T12:00:00+00:00 (source_of_truth)
         flagged: equal-trust sources — not silently guessed

Done. 3 fragments absorbed.
  • merge — three Acme name variants (and two Globex) became one entity each. The surviving URI is the signal-richest fragment; its provenance is the source row that won (erp, timestamp, authority). That URI collapse is applied to the graph.
  • conflict / headquarters — the report names Austin as the authority-axis winner (ERP source_of_truth over a stale directory scrape). That line is the explanation, not a rewrite of current facts.
  • unresolved / credit_rating — ERP says A, CRM says BBB. Same authority, same timestamp. The report flags the pair instead of silently picking.

Fixture notes: examples/suppliers-messy.md. Hermetic proof: tests/test_suppliers_messy_fixture.py.

2. ingest → ask — the payoff

With a key, live /ask is always-LLM Cypher. The cached plan is not consulted when a real key is present.

infona ingest examples/trials.csv --kg my-data
infona ask "Which Phase 3 NSCLC trials is AstraZeneca running?" --kg my-data

That question should return FLAURA2. examples/trials.csv is a 16-row oncology sample (8 sponsors, 11 drugs, 7 indications) — public program names, synthetic TRIAL-* IDs, no patient data.

infona ingest inferring a schema from trials.csv, then writing Trial, Sponsor, Drug, Indication nodes into the graph

infona ask compiling English to Cypher and lighting three sponsor paths — FLAURA2, MARIPOSA, CROWN — into NSCLC

The looping SVGs are generated from scripts/render_readme_demos.py. Local Neo4j notes: docs/neo4j-local.md. infona init --local connects without starting Docker. If something fails, the CLI should name the next command.

Python package (library, not the infona CLI — that is @infona-ai/cli). Same version as the npm packages:

pip install infona-client

Import path is infona_client. Graph IRIs live under https://graph.infona.ai/.


Optional: 3rd-party REST / SQL extract (dlt)

pip install infona-client does not pull dlt. Install the extra on the backend only (pip install 'infona-client[dlt]'). Infona is the destination — there is no dlt warehouse sink. The CLI reads env:VAR locally and sends an inline token; the API never reads the server process environment.

# frozen body for POST /graphs/{tenant}/ingest/dlt
cat > spec.json <<'EOF'
{
  "source": {
    "kind": "rest_api",
    "base_url": "https://api.example.com",
    "auth": {"type": "bearer", "secret_ref": "env:EXAMPLE_TOKEN"},
    "resources": ["v1/contacts"]
  },
  "map": {"v1/contacts": {"type": "Contact", "id_field": "id"}},
  "kg": "crm"
}
EOF
infona ingest --dlt spec.json --kg crm

SQL is the same shape with "kind": "sql" and "dsn": "env:EXAMPLE_DSN". Hosted Explorer Connect / Run is premium (ONTA-554) and hits this same route.


Eval — 6 / 8 (75%), misses stay visible

Published pin: 6 / 8 (75%) on examples/trials.csv (16 synthetic oncology rows). Query model openai/gpt-oss-120b, judge deepseek/deepseek-v4-pro-0813 (reasoning, effort high). /ask is always-LLM Cypher — these scores are not golden-string shortcuts. Same eight questions as the prior 2/8 pin. Two misses stay visible.

Eval is Python-only. There is no infona eval CLI.

infona ingest examples/trials.csv --kg eval-public-trials -y
python scripts/run_public_eval.py --dataset examples/trials.csv --kg eval-public-trials --questions 8
Tier Skill Passed Asked Accuracy Visible misses
1 Count/Lookup 2 2 100%
2 Filter 1 2 50% Start-year ≥ 2019 returned rows, not a count
3 Join 2 2 100%
4 Multi-hop 1 2 50% NSCLC Phase-3 average used a missing average_enrollment column
All 6 8 75%

Full write-up: docs/EVAL.md. Backing JSON: docs/eval/public_results.json.


What leaves your machine

Infona does not phone home unless you turn it on. Default off.

export INFONA_TELEMETRY=1          # opt in
export INFONA_TELEMETRY=0          # force off (wins over a previous yes)

The first-run CLI prompt (infona / infona init on a TTY) asks the same question and writes ~/.infona/telemetry.json. There is no opt-out default.

Only when enabled, one anonymous JSON object per job:

  • job type (ingest / ask / er rebuild / export)
  • a row-count bucket (not the exact count)
  • source type (csv / json / jsonl / text / http — never a filename)
  • error class (exception type or HTTP family — never the message)

A random install_id (UUID) identifies the install, not you.

Never leaves: your data, column names, file names, graph content, workspace / tenant ids, prompts, answers, Cypher, emails, API keys.

When enabled, the default collector is the public Infona-oss PostHog project (write-only project token). Override with INFONA_TELEMETRY_URL, set it to off, or use INFONA_TELEMETRY_SINK=stderr / file locally.

Full contract: docs/TELEMETRY.md.


What this is not

Infona is not a memory or context layer that stuffs retrieved chunks into a prompt window. This repo registers no default open-web page fetcher; you bring retrieval or you skip web fetch (docs/BOUNDARY.md). It is not RAG over a vector index, and it is not "chat with your CSV."


What you get

Entity resolution infona er rebuild collapses fragment URIs (6→3 on the suppliers fixture). Winner URI, reason, score, provenance timestamp. Field-conflict lines in the report are explanatory; they do not rewrite current graph values.
Provenance Source + timestamp + authority on the winning fact in the report. Answers carry per-fact citations (tests/test_answer_citations.py).
Schema from one pass Luna (or your configured model) sees the file once. Types, attributes, relationships. No per-row LLM.
Deterministic rows Every cell maps through that schema via insert_facts.
A real graph Neo4j. Sponsors, trials, drugs, indications are nodes.
Ask Always-LLM Cypher when a key is present. Cached-plan replay when it is not. Fail-closed when the plan is a silent wrong total.
CLI + MCP + HTTP Same canonical routes. infona, @infona-ai/mcp, POST /graphs/{tenant}/ask.
Export JSON or CSV back out. The graph is yours.
CSV / JSON / text
  → schema inference (1 LLM call; skipped for the prebuilt snapshot)
  → deterministic row mapping
  → Neo4j knowledge graph (GraphStore / Cypher)
  → er rebuild (URI collapse; field-conflict report)
  → ask (cached-plan replay with no key; always-LLM Cypher with a key)

Writes go through insert_facts / refresh_after_write. Instance relationships use https://graph.infona.ai/onto/<leaf>. Ask is always-LLM Cypher when a model is configured. Grounding, probes, and few-shots inform the model; they do not replace it.

export OPENROUTER_API_KEY=sk-or-...
export INFONA_QUERY_PROVIDER=openrouter
export INFONA_QUERY_MODEL=openai/gpt-oss-120b

MCP (agents)

Same ask, same graph, same exact rows — as a tool result:

{
  "mcpServers": {
    "infona": {
      "command": "npx",
      "args": ["-y", "-p", "@infona-ai/mcp", "infona-mcp"],
      "env": {
        "INFONA_API_URL": "http://localhost:8000",
        "INFONA_TENANT": "default"
      }
    }
  }
}

ask, search, agent, ingest_csv, ingest_dlt, export_kg, ontology, jobs — same backend the CLI hits. packages/mcp/README.md.

What's free

  • OSS (this repo): ingest, ontology, ask, MCP / CLI / HTTP, export, free sources, BYOK registry, plugin seams.
  • Bring your own retrieval: OSS registers no open-web page fetcher. Enrichment that needs a URL fetch declines unless you register one — or you use hosted Infona.
  • Hosted-only: managed keys Infona bills, paid search/scrape ladders, curated Enhanced ontology, Explorer, billing.

Full table: docs/BOUNDARY.md.

Product path: FastAPI + Neo4j GraphStore (Cypher). SPARQL / Neptune are not product backends.


License and contributing

Apache 2.0 — LICENSE, NOTICE.

Shipped packages share one lockstep version: infona-client on PyPI and @infona-ai/cli / @infona-ai/mcp on npm. Release notes: CHANGELOG.md.

docs/API.md · docs/BOUNDARY.md · ROADMAP.md · SECURITY.md · CODE_OF_CONDUCT.md · CHANGELOG.md · CONTRIBUTING.md · CLA.md · AGENTS.md

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infona_client-0.1.44.tar.gz (3.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infona_client-0.1.44-py3-none-any.whl (3.8 MB view details)

Uploaded Python 3

File details

Details for the file infona_client-0.1.44.tar.gz.

File metadata

  • Download URL: infona_client-0.1.44.tar.gz
  • Upload date:
  • Size: 3.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for infona_client-0.1.44.tar.gz
Algorithm Hash digest
SHA256 fd1be8ed52c9ad4d67232465408479f1a8860eb7a19d3b1a97ff6016bead998a
MD5 eab71a06b282da77fc255d06c25fe720
BLAKE2b-256 a4d19a837e792a74446cf4084a03e7da4d6d37791c719bfb68e548b8b274df40

See more details on using hashes here.

File details

Details for the file infona_client-0.1.44-py3-none-any.whl.

File metadata

  • Download URL: infona_client-0.1.44-py3-none-any.whl
  • Upload date:
  • Size: 3.8 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for infona_client-0.1.44-py3-none-any.whl
Algorithm Hash digest
SHA256 c06b115469d9e9e593073db709446388d4e345ea8fec2b3d748feb09e1adff30
MD5 88587c3e5269baa2313883c56cb578e5
BLAKE2b-256 b21603b2fce1e58b044e6ccd148c64329ee3459f8332f9c8fa0e0227adfa1439

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.53

2 files

0.1.52

2 files

0.1.51

2 files

0.1.50

2 files

0.1.49

2 files

0.1.48

2 files

0.1.47

2 files

0.1.46

2 files

0.1.45

2 files

This release

0.1.44 This release

2 files

0.1.43

2 files

0.1.42

2 files

0.1.41

2 files

0.1.40

2 files

0.1.39

2 files

0.1.38

2 files

0.1.37

2 files

0.1.36

2 files

0.1.35

2 files

0.1.34

2 files

0.1.33

2 files

0.1.32

2 files

0.1.31

2 files

0.1.30

2 files

0.1.29

2 files

0.1.28

2 files

0.1.27

2 files

0.1.26

2 files

0.1.25

2 files

0.1.24

2 files

0.1.23

2 files

0.1.22

2 files

0.1.21

2 files

0.1.20

2 files

0.1.19

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page