Files

168 lines
5.4 KiB
Markdown

# ACMS Backend Abstraction Layer
The Backend Abstraction Layer (BAL) provides a uniform interface to heterogeneous
data stores used by the Advanced Context Management System. Context strategies
query text, vector, and graph backends through protocol-defined APIs, enabling
backend implementations to be swapped without changing strategy code.
## Architecture
```
Strategy ──► ScopedView ──► Backend Protocol ──► Physical Store
└── resource_filter (scope)
```
Each backend type has a `Protocol` (structural subtyping) and a corresponding
frozen result `dataclass`. Strategies never instantiate backends directly —
they receive scoped views from the Context Assembly Pipeline via dependency
injection.
## Protocol Contracts
### TextBackend
Full-text search over indexed resource content.
| Method | Signature | Returns |
|--------|-----------|---------|
| `search` | `(query: str, *, scope: frozenset[str], max_results: int = 20)` | `list[TextResult]` |
**Preconditions:**
- `query` must be a non-empty string.
- `max_results` must be a positive integer.
**Postconditions:**
- Returns results ordered by descending `score`.
- Results are restricted to resources whose ULIDs appear in `scope`.
### VectorBackend
Embedding similarity search over chunked resource content.
| Method | Signature | Returns |
|--------|-----------|---------|
| `similarity_search` | `(embedding: list[float], *, scope: frozenset[str], top_k: int = 20)` | `list[VectorResult]` |
**Preconditions:**
- `embedding` must be a non-empty list of floats.
- `top_k` must be a positive integer.
**Postconditions:**
- Returns results ordered by descending `score` (cosine similarity).
- Results are restricted to resources whose ULIDs appear in `scope`.
### GraphBackend
Knowledge-graph queries and traversals over UKO triples.
| Method | Signature | Returns |
|--------|-----------|---------|
| `sparql_query` | `(query: str, *, scope: frozenset[str])` | `GraphResult` |
| `get_triples` | `(subject: str)` | `GraphResult` |
| `traverse` | `(start: str, *, depth: int = 2)` | `GraphResult` |
**Preconditions:**
- `query` and `subject` and `start` must be non-empty strings.
- `depth` must be a non-negative integer.
**Postconditions:**
- `sparql_query` restricts results to resources in `scope`.
- `traverse` returns triples discovered within `depth` hops of `start`.
## Result Types
All result types are frozen (immutable) dataclasses.
### TextResult
| Field | Type | Description |
|-------|------|-------------|
| `uko_uri` | `str` | UKO URI of the matching information unit (non-empty) |
| `content` | `str` | Matched text content |
| `score` | `float` | Relevance score, 0.0 -- 1.0 |
| `metadata` | `dict[str, str]` | Backend-specific metadata (default: empty) |
### VectorResult
| Field | Type | Description |
|-------|------|-------------|
| `uko_uri` | `str` | UKO URI of the matching information unit (non-empty) |
| `content` | `str` | Text content of matched chunk |
| `score` | `float` | Cosine similarity, 0.0 -- 1.0 |
| `metadata` | `dict[str, str]` | Backend-specific metadata (default: empty) |
### GraphResult
| Field | Type | Description |
|-------|------|-------------|
| `triples` | `list[tuple[str, str, str]]` | (subject, predicate, object) triples |
| `metadata` | `dict[str, str]` | Backend-specific metadata (default: empty) |
## Extension Points
### Implementing a Custom Backend
To add a new backend (e.g., Tantivy for text search):
1. Create a class that satisfies the corresponding `Protocol` (e.g., `TextBackend`).
2. Implement all protocol methods with proper argument validation.
3. Register the backend in the DI container by overriding the provider:
```python
from cleveragents.application.container import override_providers
override_providers(text_backend=TantivyTextBackend(index_path="/data/tantivy"))
```
### In-Memory Stubs
The following stubs are provided for development and testing:
| Stub | Protocol | Behaviour |
|------|----------|-----------|
| `InMemoryTextBackend` | `TextBackend` | Returns empty list; validates args |
| `InMemoryVectorBackend` | `VectorBackend` | Returns empty list; validates args |
| `InMemoryGraphBackend` | `GraphBackend` | Returns empty `GraphResult`; validates args |
Stubs are registered as the default providers in the DI container. They can
be overridden at runtime for production or per-test via `override_providers()`.
### DI Container Registration
Backends are registered as singletons in the DI container
(`cleveragents.application.container.Container`):
```python
text_backend = providers.Singleton(InMemoryTextBackend)
vector_backend = providers.Singleton(InMemoryVectorBackend)
graph_backend = providers.Singleton(InMemoryGraphBackend)
```
To swap to a production backend, override the provider before first use:
```python
container = get_container()
container.text_backend.override(providers.Singleton(TantivyTextBackend))
```
## Module Locations
| Module | Purpose |
|--------|---------|
| `cleveragents.domain.models.acms.backends` | Protocol definitions and result dataclasses |
| `cleveragents.domain.models.acms.stubs` | In-memory stub implementations |
| `cleveragents.application.container` | DI container backend registration |
## Related
- [CRP Reference](crp.md) — Context Request Protocol types
- [Specification: ACMS > Backend Abstraction Layer](../specification.md) — Authoritative design
- [ADR-014: Context Management](../adr/ADR-014-context-management-acms.md) — Architecture decision record