Skip to content

Adapters — API Reference

CDMAdapter

groundworkers.adapters.cdm

CDMAdapter

Adapter for a CDM (Common Data Model) database connection.

Holds the SQLAlchemy engine and session factory for an OMOP CDM database. Shared by services that need to query the CDM directly (VocabService, OmopGraphAdapter).

Pass engine to adapters that wrap their own session management. Use session() for services that need a scoped session context manager.

engine property

The underlying SQLAlchemy engine.

close()

Dispose the engine and release the connection pool.

is_available()

Return True if the CDM database is reachable (SELECT 1 probe).

session()

Return a session context manager.

OmopGraphAdapter

groundworkers.adapters.omop_graph

EmbeddingTierUnavailable

Bases: GroundworkersError

The embedding tier could not run; lexical tiers remain usable.

Raised instead of failing a whole grounding request so GraphService can skip the embedding tier and continue down the tier plan.

OmopGraphAdapter

Dependency-shaped wrapper around the omop-graph backend runtime.

This adapter owns everything omop-graph specific: the KnowledgeGraph lifecycle and embedding configuration, translation of omop-graph/SQLAlchemy exceptions into GroundworkersError, and a set of normalized primitives that each map to roughly one omop-graph operation and return plain dicts / tuples (never raw omop-graph objects).

Multi-step orchestration (hierarchy walks, path assembly, grounding tier selection, neighbourhood shaping) lives in GraphService, which composes these primitives. Keep this class dependency-shaped: no caller-facing policy.

embedding_resolver_active property

Whether the embedding grounding tier can actually produce candidates.

Requires all three inputs, not just a valid store configuration: the vector store backend, the resolved model, and a callable model backend to encode the query. The read-oriented server builds the graph with write=False, and omop-graph derives its on-demand query encoder from the writer interface — so without a Groundworkers-supplied encoder the embedding resolver would run and return nothing. Reporting active in that state is the silent-degradation failure this property exists to prevent.

async_run_ground_tier(resolvers, query, *, constraints, limit) async

Run a grounding tier with native async query encoding when needed.

canonicalize_domain(domain)

Resolve a loosely-typed domain to its canonical domain_id.

Returns None for an unrecognised domain so the caller can reject it, which is distinct from None input meaning "no domain constraint". Use :meth:describe_unknown_domain to build the message.

This previously matched against a hardcoded six-name tuple — the set domain_classify emits — so the other forty-four domains only worked when supplied in exactly the right case.

concept_views(concept_ids)

Batch-fetch normalized concept views keyed by concept_id.

Returns an empty dict when no ids are supplied or the lookup fails, so callers can treat a missing key as "unknown concept" without special-casing backend errors during enrichment.

edges(concept_id, *, direction, predicate_kinds=None, active_only)

Return normalized edges for one concept (no concept-name enrichment).

Each edge: {subject_id, object_id, predicate_id, predicate_kind, valid}.

known_domains()

Every valid domain_id, for validation and select lists.

probe()

Return (available, detail) without raising.

run_ground_tier(resolvers, query, *, constraints, limit)

Run one resolver tier through omop-graph and normalize the hits.

Returns ground hits without concept-view enrichment; GraphService adds vocabulary/domain/class fields and applies tier-selection policy.

Raises EmbeddingTierUnavailable when an embedding tier cannot be encoded, so the caller can fall through to the remaining lexical tiers.

shortest_paths(source_id, target_id, *, max_depth, predicate_kinds=None, within_domain)

Return shortest paths as lists of normalized steps (no name enrichment).

Each step: {subject_id, object_id, predicate, predicate_kind}.

traverse_neighborhood(concept_id, *, predicate_kind_names, max_depth, max_nodes)

Bounded BFS from a seed concept.

Returns {neighbor_ids, edges, edge_count, terminated_reason} where edges are normalized ({subject_id, predicate_id, predicate_kind, object_id}) and neighbor_ids excludes the seed. Raises INVALID_INPUT for an unknown predicate-kind name.

OmopEmbAdapter

groundworkers.adapters.omop_emb

OmopEmbAdapter

Expose stored-vector and live-query operations through public omop-emb APIs.

Stored-neighbour operations require only the vector-store backend. Text search and encoding additionally require the one model backend resolved for this Groundworkers process.

async_encode(text, model_name) async

Encode text with the model backend's native async API.

async_probe_live_query() async

Smoke-test query encoding with the model backend's async client.

Encode a query asynchronously, then search the registered index.

async_search_batch(queries, limit, domain, vocabulary, standard_only, active_only, model_name, batch_size=32) async

Encode and search multiple queries in one provider/index operation.

The query filters are intentionally shared across the batch. Callers with different domain or vocabulary constraints should partition their inputs first, then merge the aligned results by their own item identifiers.

close()

Release cached readers, storage, and model backends.

encode(text, model_name)

Encode text with the configured model backend.

get_neighbours(concept_id, limit, model_name)

Return stored-vector neighbours without calling the model provider.

has_model_backend()

Return whether live text encoding has a configured model backend.

index_status()

Return a secret-safe snapshot of store and registry availability.

is_available()

Return whether the store is reachable and has a registered model.

probe_live_query()

Smoke-test the configured model with one real query embedding.

index_status intentionally checks only the vector store and model registry. This probe verifies the separate capability used by embedding_search and graph embedding resolution.

resolve_model_name(model_name=None)

Resolve a caller-supplied or configured registered model name.

search(query, limit, domain, vocabulary, standard_only, active_only, model_name)

Encode a query with the configured model and search its registered index.

LLMAdapter

groundworkers.adapters.llm

LLMAdapter

Groundworkers' error and payload boundary over one omop-llm ModelBackend.

The backend is provider-neutral (any-llm), so this adapter holds no provider-specific behaviour and no HTTP client of its own. What it does own is the translation into Groundworkers' contracts: GroundworkersError codes instead of provider exceptions, and plain JSON-safe dicts for the MCP tool layer.

Two completion modes are available:

  • Text completion (complete_text): returns a raw text response.
  • Structured completion (complete_structured): requests a JSON response matching a caller-supplied schema. Preferred for MCP-facing tools where downstream agents need to parse the output reliably.

async_complete_structured(prompt, response_schema, *, system_prompt=None, model_name=None, temperature=0.0) async

Structured completion using the backend's native async client.

async_complete_text(prompt, *, system_prompt=None, model_name=None, temperature=0.0) async

Complete a prompt without crossing an async-to-sync model boundary.

async_is_available() async

Return True if the model backend is reachable from an async runtime.

async_status() async

Async availability and configuration snapshot. Never raises.

close()

Release the cached backend.

complete_structured(prompt, response_schema, *, system_prompt=None, model_name=None, temperature=0.0)

Complete a prompt and return a parsed JSON dict guided by response_schema.

The schema is injected into the system prompt and JSON mode is requested from the provider. This is compatible with Ollama, vLLM, and OpenAI endpoints, and deliberately does not use omop-llm's extract(): that requires a Pydantic model and a provider that declares native structured output, whereas callers here supply a raw JSON schema.

The response is parsed but not validated against the schema — callers are responsible for validating the returned dict (e.g. with Pydantic).

Raises INVALID_INPUT if model_name names a different model or if response_schema is not JSON-serializable. Raises BACKEND_UNAVAIL if the call fails. Raises QUERY_ERROR if the response is not valid JSON.

complete_text(prompt, *, system_prompt=None, model_name=None, temperature=0.0)

Complete a prompt and return the response text.

model_name is accepted for call-site compatibility and must match the configured model: one resolved [models.*] entry backs this adapter, so an unrelated name cannot be honoured.

Raises INVALID_INPUT if model_name names a different model. Raises BACKEND_UNAVAIL if the call fails.

is_available()

Return True if the model backend is reachable.

status()

Return availability and configuration details. Never raises.

Probes the provider's model inventory. On failure returns {"available": False, ..., "detail": "<reason>"}.