Usage / gRPC api
juditha is an in-process library first, but the read-only half of the store (search, extract, percolate) can be served over gRPC. That lets many workers, or workers on other hosts, share one built corpus instead of each carrying their own copy.
No authentication
The api has no auth and no TLS. Anything that can reach the port can query the whole corpus. Bind it to a private network, or put something in front that terminates auth. JUDITHA_RPC_HOST therefore defaults to localhost, not 0.0.0.0.
Serving
Build a store the usual way, then serve it:
export JUDITHA_URI=/var/lib/juditha
juditha load-entities -i entities.ftm.json
juditha build
juditha serve --host 0.0.0.0 --port 50051
| Option | Default | Env var |
|---|---|---|
--host |
localhost |
JUDITHA_RPC_HOST |
--port |
50051 |
JUDITHA_RPC_PORT |
--workers |
10 |
JUDITHA_RPC_WORKERS |
The server opens the tantivy index and the Aho-Corasick automaton, but not the LevelDB aggregator, so other processes on the same host can keep reading the same store directory at the same time. See Settings for the full list.
Querying
Point JUDITHA_URI at the server instead of at a directory. Everything else stays the same:
export JUDITHA_URI=grpc://localhost:50051
juditha lookup "European Parliament"
juditha extract -i document.txt
juditha percolate -i document.txt --slop 1
From Python, get_store() returns an ApiStore for grpc:// URIs and a local Store for everything else. Both implement the same BaseStore interface, so no call site changes:
from juditha import get_store, lookup
store = get_store("grpc://localhost:50051")
store.search("European Parliament") # -> Result | None
store.extract("The European Parliament met.") # -> list[Mention]
store.percolate("The European Parliament met.")
# or via the env var, which `lookup()` picks up too
lookup("European Parliament")
Only the read methods cross the wire. juditha build, the load-* commands and juditha iterate are local-only and raise a ValueError against a grpc:// URI, because they need the LevelDB aggregator.
Docker
The published image runs the server as its entrypoint. Mount a built store at /data:
The image sets JUDITHA_RPC_HOST=0.0.0.0 and JUDITHA_URI=/data/juditha.db.
The wire contract
The service definition lives at juditha/rpc/juditha.proto, and the checked-in python stubs next to it are regenerated with make proto.
service Juditha {
rpc Search (SearchRequest) returns (SearchResponse);
rpc Extract (ExtractRequest) returns (MentionsResponse);
rpc Percolate (PercolateRequest) returns (MentionsResponse);
}
Notes for clients in other languages:
SearchRequest.thresholdand.limitareoptional. Leave them unset to get the server's configured defaults rather than sending your own.SearchResponse.resultis unset when there is no match above the threshold. That is the wire form ofStore.searchreturningNone.Result.common_schemaandResult.captionare computed by the server. The python client ignores them and recomputes locally via rigour and followthemoney; other clients can use them as-is. An emptycaptionmeans there was no name to pick.Result.tookis measured server-side in milliseconds and does not include network time.Mention.schemamatches the JSON field name ofjuditha.model.Mention(the python attribute isschema_).
Message size limits are raised from gRPC's 4 MB default to 64 MB on both ends, because extract and percolate take whole documents. Tune with JUDITHA_RPC_MAX_MESSAGE_LENGTH, and set it on the client too.