factcircuit
FactCircuit는 불변 출처와 단계별 검증, 제한된 검색, 재현 가능한 평가를 제공하는 감사 가능한 주장·증거 검증 루프입니다
CSV -> RDF -> SPARQL/MCP. PROV-O first-class. Self-hostable, sovereignty-first.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Connect your private and open data through shared ontologies — so AI can reach what it couldn't. Every answer grounded, and traceable to its source.
▶ Live demo (no server, no AI — real SPARQL in your browser):. Ask materials questions over a small starrydata subset and get deterministic answers — each carrying its citable IRIs, the exact SPARQL run, and a provenance trace — plus a cross-dataset join of Starrydata measurements with Materials Project crystal structures. Runs entirely client-side (oxigraph-wasm); nothing is sent anywhere.README 전문 보기 ↗Connect your private and open data through shared ontologies — so AI can reach what it couldn't. Every answer grounded, and traceable to its source.
▶ Live demo (no server, no AI — real SPARQL in your browser): https://kumagallium.github.io/asterism/demo/. Ask materials questions over a small starrydata subset and get deterministic answers — each carrying its citable IRIs, the exact SPARQL run, and a provenance trace — plus a cross-dataset join of Starrydata measurements with Materials Project crystal structures. Runs entirely client-side (oxigraph-wasm); nothing is sent anywhere.
Asterism turns scattered structured data into a connected knowledge graph you can query and trust. Data points are the stars; shared ontologies are the lines that connect them into a recognizable figure — one your tools, and your AI, can finally read. It exposes the result as both a SPARQL 1.1 endpoint and an MCP server, with full provenance. CSV is the first input type (starting with the starrydata dataset of thermoelectric/measurement curves); the ingestion substrate is declarative and source-agnostic, extending to JSON/API sources without per-dataset code.
Two properties make the graph trustworthy:
prov:Entity; every ingest / digitization / link is a prov:Activity. A cited number can always be traced back to the figure, paper, and run it came from.docs/architecture/ingestion-execution-safety.md and docs/architecture/phase5-declarative-substrate.md.📖 User manual (Japanese): https://kumagallium.github.io/asterism/manual/. How to onboard a dataset step by step, plus a from-scratch introduction to the ideas underneath — RDF, IRIs, classes, properties, ontologies and SPARQL — and what each file in a dataset actually does. Source: manual/ja/ (the same text the in-app design-consult chat is given).
Live execution state: docs/ROADMAP.md. Design decisions: docs/architecture/ (ADRs).
Shipped today: a CSV → RDF ingester (papers / samples / curves), a watcher + HTTP upload API (drop a CSV → auto-reindex), QUDT unit normalization, WebPlotDigitizer provenance, and a 12M-triple benchmark; a SPARQL endpoint and an MCP server with typed tools (template_curve_fetch, sample_search, property_ranking, provenance_of) for grounded, cited answers; an AI-assisted "Step 0" schema builder for arbitrary CSVs (CLI); and a reproducible demo tagged v0.1.0.
In progress (see ROADMAP): a declarative substrate that generalizes ingestion from "CSV → RDF" to "structured source → RDF" (JSON/API already proven), a shared vetted function library, and a schema-aware query layer so questions can be asked over any onboarded ontology — not just the built-in one. A researcher-facing web UI (schema-design workbench, dataset catalog, and a grounded Ask view) is in active development under ui/ (React, served by the API); today's stable surfaces are the CLI, the HTTP upload API, directory-drop, and MCP.
prov:Entity; every run is a prov:Activity; citations stay queryable by IRI.docker compose up is the supported install. No multi-tenant SaaS surface.What shipped, release by release, is in the manual: the feature roadmap (only the milestones that changed what you can do, linked into the manual) and the release history (every release, generated from CHANGELOG.md). The living execution state is docs/ROADMAP.md. In short: ingestion is generalizing to structured source → RDF (CSV today, JSON/API proven), with a schema-aware query/Ask layer and a source-onboarding UI ahead.
git clone https://github.com/kumagallium/asterism
cd asterism
docker compose up -d --build
# Drop a CSV into the kind-specific directory; the watcher picks it up (no token).
cp /path/to/starrydata_papers.csv data/sources/csv/papers/
# …or upload via HTTP. The write surface is token-gated (fail-closed): set a
# token first (also put it in .env so the container sees it), then send it.
export ASTERISM_API_TOKEN=$(openssl rand -hex 32) # restart compose after setting in .env
curl -F [email protected] -H "X-Asterism-Token: $ASTERISM_API_TOKEN" \
http://localhost:8080/upload/papers
# Inspect ingest history (read-only, open)
curl http://localhost:8080/jobs | jq
# SPARQL directly against the (loopback-only) Oxigraph — for local debugging.
# Oxigraph itself has no auth; never publish 7878 on a shared network.
curl -G http://localhost:7878/query \
--data-urlencode 'query=SELECT (COUNT(*) AS ?c) WHERE { ?s ?p ?o }'
# Call template_curve_fetch (self-built MCP) for the raw x/y of one curve
# (any MCP client works; here we use the python fastmcp Client)
python -c "
import asyncio
from fastmcp import Client
async def main():
async with Client('http://localhost:8002/mcp') as c:
r = await c.call_tool('template_curve_fetch', {
'curve_iri': 'https://kumagallium.github.io/asterism/starrydata/resource/curve/1-1-1',
})
print(r.structured_content)
asyncio.run(main())
"
For Step 0 — designing a schema for a new (non-starrydata) CSV. This is a local CLI workflow; propose / refine call an LLM, so they need an API key:
pip install -e step0 # installs the asterism-* CLIs
export ANTHROPIC_API_KEY=sk-... # required only by propose/refine
# 1. inspect structure (types / JSON / uniqueness, incl. composite keys)
asterism-inspect mydata.csv --fk id
# 2. let the LLM draft the design artifacts (TBox / Mermaid / MIE / mapping spec)
asterism-propose mydata.csv --domain "measurement curves; PROV-O; no blank nodes" > proposal.md
# 3. (optional) feed back review comments
asterism-refine proposal.md --comment "use a composite (paper_id, sample_id) key" > refined.md
# 4. split the Markdown into individual files
asterism-materialize refined.md --name mydata --output-dir out/
# 5. validate the bundle against the *full* CSV (8-trap check; exit 0/1, CI-friendly)
asterism-validate --mie out/mydata-mie.yaml --mapping-ir out/mydata-mapping.yaml --csv mydata.csv
asterism-local runs the whole workbench loopback-only on one machine: data lives
under your OS user-data directory (macOS: ~/Library/Application Support/Asterism),
the write token is minted and injected automatically (nothing to paste), and
Oxigraph plus the Ask agent (demo-agent) are started as child processes. Designed
for researchers whose unpublished data must never leave their machine — see
docs/architecture/local-first-distribution.md.
brew install oxigraph # or: cargo install oxigraph-cli
cd ui && npm ci && VITE_DEMO_MODE=live VITE_DEMO_AGENT_URL=/ npm run build && cd ..
cd api && uv venv .venv && uv pip install -e ../ingest && uv pip install -e '.[local]'
.venv/bin/asterism-local # opens http://127.0.0.1:8080/
Useful flags: --data-dir, --oxigraph-url (reuse a running store instead of
spawning one), --no-ask, --port, --no-browser. Ask needs an LLM key (entered
in the browser, or a local model): local LLMs (Ollama / LM Studio) work via
Settings → provider openai-compatible with a local base URL.
Prefer a native window? The same stack ships as a desktop app (Tauri) — see
desktop/README.md: cd desktop && npm install && npm run dev.
Asterism's MCP front is meant to be mounted next to the public-data MCP servers an agent already uses (e.g. dbcls/togomcp, which fronts UniProt / ChEBI / PubChem / … over rdfportal). The federation happens in the agent, not in either server: one reasoning turn can pull a public fact from one server and join it against your own unpublished measurements here.
{ "mcpServers": {
"togomcp": { "url": "http://127.0.0.1:8000/mcp" },
"asterism": { "url": "http://127.0.0.1:8002/mcp" } } }
(Ports are this repo's compose defaults; /mcp is FastMCP's HTTP transport path —
check each server's own docs if you run them elsewhere.)
find_datasets is the entry point on this side — the counterpart to togomcp's
find_databases. It answers which datasets does this server hold, and what may I
call on each, returning per dataset its id, name, description, the classes its
design declares, its citable graph, and its typed tools under the exact names
the caller must send. It reads the registry at call time, so a dataset promoted
after the server started is listed without a restart, and it lists only citable
(promoted) datasets unless asked otherwise.
Two things it deliberately does not copy from togomcp: there are no categories
(a dataset's declared classes carry that signal and are not a taxonomy someone has
to maintain), and cross-server joins are not executed here — SERVICE federation
stays rejected on the SPARQL escape (SSRF / exfiltration), so a cross-server join
is the agent's to make.
The typed tools that find_datasets reports come from the workbench registry, so
the MCP front needs to see it (CSV2RDF_REGISTRY_ROOT); both composes wire this
up. Going the other direction — publishing a promoted asterism dataset into the
togomcp catalog so its own find_databases finds it — is
docs/architecture/togomcp-auto-publish.md.
The quickstart above is for local, single-user use. Asterism is designed to be self-hosted over confidential, unpublished data, so the defaults are safe-by-default:
compose.yaml (Oxigraph 7878,
upload-api 8080, togomcp 8000, MCP front 8002) and compose.demo.yaml
(8090) binds to 127.0.0.1. Oxigraph has no authentication and a writable
/update endpoint — never publish 7878 on a shared network. Sibling services
reach it in-network via http://oxigraph:7878.sparql_query, /api/sparql, /demo/sparql) is withheld unless you set
ASTERISM_EXPOSE_RAW_SPARQL=1. Typed, human-vetted query tools are always on.
Even when enabled the escape is scoped to promoted canonical graphs: a
caller-supplied FROM/FROM NAMED must name an allowlisted graph (no reaching
into unreviewed drafts), SERVICE federation is blocked (SSRF/exfiltration), and
schema_summary only introspects canonical/ontology graphs.asterism.functions) and confined CSV/JSON file sources are allowed (no DuckDB
rml:query, no absolute / .. / URL sources). See
docs/architecture/ingestion-execution-safety.md.To expose any surface beyond localhost: put it behind an authenticating reverse
proxy (TLS + auth), set ASTERISM_API_TOKEN to gate the write/design and SPARQL
endpoints, keep the store on a network with no outbound egress, and for a sensitive
remote store use the typed-only topology B
(compose.mcp-front.yaml,
docs/architecture/store-mcp-split.md).
Apache-2.0. See LICENSE.
Built on the shoulders of the DBCLS ecosystem (rdf-config, togopackage, togomcp), Oxigraph, QLever, and Morph-KGC.