Skip to content

Latest commit

 

History

History
146 lines (117 loc) · 6.96 KB

python.md

File metadata and controls

146 lines (117 loc) · 6.96 KB

Using Fluree from Python

The fluree package runs the Fluree engine inside your Python process: no server to start, and the same engine the server and CLI run. This page gets you started and shows how the rest of this book reads from Python. The Python documentation has a guide to the whole package and its API reference, and each class and method carries its documentation for help() and your editor.

Install

pip install fluree                # or "fluree[pandas]", "fluree[polars]"

Wheels are published for Linux (x86-64 and arm64, glibc 2.28 or later), macOS 14 or later on Apple silicon, and Windows (x86-64), for CPython 3.10 and later. The package version is the version of the engine inside it.

Quick start

import fluree

with fluree.connect("./data") as conn:          # or fluree.connect(":memory:")
    people = conn.create("people")

    people.insert("""
        @prefix ex: <http://example.org/> .
        ex:alice ex:name "Alice" ; ex:age 42 .
    """)
    commit = people.insert({
        "@context": {"ex": "http://example.org/"},
        "@id": "ex:bob", "ex:name": "Bob", "ex:age": 37,
    })

    rows = people.select("""
        PREFIX ex: <http://example.org/>
        SELECT ?name ?age WHERE { ?s ex:name ?name ; ex:age ?age } ORDER BY ?name
    """)
    for name, age in rows:
        print(name, age)              # Alice 42, then Bob 37: native str and int

    # Every past state stays queryable.
    before_bob = people.at(t=commit.t - 1)
    print(before_bob.query("PREFIX ex: <http://example.org/> ASK { ex:bob ?p ?o }"))  # False

conn.ledger("people") opens an existing ledger. Results come back as Python values: int, Decimal, datetime, str, and fluree.IRI for IRIs. A result converts to a DataFrame with to_pandas() or to_polars().

Reading this book from Python

The queries and transactions in this book work as written. A SPARQL, JSON-LD or Cypher query that a page sends to the server goes to ledger.query(), and a transaction body goes to insert(), upsert() or update():

In this book From Python
Query: JSON-LD, SPARQL or Cypher ledger.query(query), or ledger.select(query) for a table
A query whose FROM names ledgers (datasets) conn.query(query)
Insert, upsert, update ledger.insert(data), ledger.upsert(data), ledger.update(txn)
Sync a graph to a payload ledger.sync(data, graph=...)
Time travel (t, ISO time, commit) ledger.at(t=..., time=..., commit=...)
Branching ledger.branch(name), merge(), rebase(), revert()
Policy options (identity, policyClass, ...) ledger.with_policy(identity=..., policy_class=...)
Ledger configuration ledger.update(...) writing the config graph
Full-text and vector search ledger.set_full_text(...), fluree.Vector, and the query functions
Graph sources: Iceberg, Delta, SQL conn.map_iceberg(...), conn.map_delta(...), conn.map_sql(...)
Export, and archives ledger.export(...), ledger.archive(path), conn.restore(path, name)
Connection configuration (S3, DynamoDB, encryption) fluree.connect(config={...})

A few things differ from the server:

  • Policy belongs to the handle. Choose it with ledger.with_policy(...). A query or write that names its own policy (JSON-LD opts, a SPARQL # PRAGMA) is refused, so a query passed in from elsewhere cannot widen what the handle sees.
  • A ledger's query reads that ledger. A query that names other ledgers goes to conn.query().
  • Several writes can be one commit. with ledger.transaction() as txn: stages writes in any language together, and ledger.transact(fn) runs read-then-write work again when another commit lands first.
  • Parameters. query(), update() and stream() take values by name, from a dict or keyword arguments: ledger.query("... $name ...", name="Alice").

asyncio

fluree.aio is the same API with coroutines, for FastAPI and other asyncio applications. Cancelling a task stops its query in the engine:

import fluree.aio

async with fluree.aio.connect("./data") as conn:
    people = await conn.ledger("people")
    rows = await people.query("SELECT ...")

Reading documents

fluree.doc.read reads one document with an extraction model reached over HTTP, exactly as fluree doc read does: it parses the file (PDF, Word, PowerPoint, HTML, Markdown, text, spreadsheets, transcripts, email), sends its text and structure with your ontology and catalog, and returns the reading, which inserts into a ledger as it is:

import fluree

reading = fluree.doc.read("invoice.pdf", ontology="invoices.ttl",
                          catalog="suppliers.ttl", model="reader-small")
print(reading.usage.note)                  # 1,032 tokens
for m in reading.mentions():               # text, begin, end, entity, element
    print(m["text"], "->", m["entity"])

with fluree.connect("./data") as conn:
    conn.create("invoices").insert(reading.to_jsonld())

text= reads a string instead of a file, under an IRI derived from its content unless doc_iri= names one; catalog takes a list of files, each optionally (file, class IRI); to_turtle() and claims() give the reading as Turtle and as rows. Offsets index the parser's text (what fluree doc parse --format text prints), not the file's bytes. The rows read NIF offsets and the pipeline's doc: terms; a reader writing terms of its own keeps them, as written, in reading.nodes and to_jsonld().

The credential: api_key with auth_header is sent as is to url; api_key alone is traded for an hour's token when it is a Fluree.ai API key (flk_…) and sent as a bearer token otherwise; with no key, this machine's fluree login, else FLUREE_AI_API_KEY, each only to its own service (a url elsewhere is called with no credential). With cache_dir, a request read once is answered from there afterwards. Python does no vision escalation: pages the parser can't read are listed in reading.notes.

Next steps

  • The Python guide for the whole package (results, transactions, Cypher, search, graph sources, branches, errors, logging and concurrency) and the API reference.
  • Concepts for how Fluree works.
  • Guides for task-oriented recipes; their queries run unchanged through ledger.query().