MicroFish/.kiro/specs/graphiti-ollama-embedder/requirements.md

129 lines
7.3 KiB
Markdown

# Requirements Document
## Project Description (Input)
Fix Graphiti embedding integration with Ollama (mxbai-embed-large) and stop silently swallowing embedding failures. Two bugs: (1) No first-class support for local Ollama embedders — `EMBEDDING_MODEL` defaults to OpenAI's `text-embedding-3-small` and the embedder reuses `LLM_BASE_URL` when `EMBEDDING_BASE_URL` is unset, so Ollama users get 404s; `.env.example` and `CLAUDE.md` don't document Ollama. (2) `backend/app/services/graphiti_adapter.py:471-473` catches every exception during episode ingestion, logs a truncated `WARNING`, and substitutes a placeholder UUID, so a graph build appears to succeed but writes nothing. Tracked as GitHub issue #18.
## Introduction
This feature adds first-class documentation for using a local Ollama embedder
(`mxbai-embed-large`, 1024-dim) with the Graphiti adapter and removes the
silent placeholder-UUID fallback in `_GraphNamespace.add_batch` so that
embedding failures terminate the surrounding background `Task` with the
underlying error visible in the UI and logs.
The work spans two narrowly scoped changes:
1. **Documentation update**`.env.example`, `CLAUDE.md`, and the README /
docker-compose comments gain a short Ollama section that explains how to
point the embedder at a local Ollama instance, why `mxbai-embed-large` is
the recommended model (1024-dim, matches Graphiti's default
`EMBEDDING_DIM`), and how to smoke-test connectivity with one `curl`
command before kicking off a graph build.
2. **Loud failure** — the broad `except Exception` in
`_GraphNamespace.add_batch` is removed (or narrowed to a small set of
transient network errors). Episode ingestion failures now propagate to
the calling background task, which marks itself `FAILED` with the
underlying error message attached, rather than logging a `WARNING` and
returning a fake UUID.
No new dependency, environment variable, or config flag is introduced.
All existing OpenAI/Gemini configurations continue to work unchanged.
## Boundary Context
- **In scope**: documenting Ollama as a third supported embedder provider
in `.env.example`, `CLAUDE.md`, and the docker-compose / README comments;
removing the silent placeholder-UUID fallback in
`_GraphNamespace.add_batch`; surfacing the underlying ingestion error to
the background `Task` so it terminates with `status=FAILED`; documenting
a one-line `curl` smoke test for embedder connectivity.
- **Out of scope**: a startup-time embedder health probe that refuses to
boot on dim/model mismatch; making `EMBEDDING_DIM` env-configurable so
768-dim or 1536-dim embedders can be used; adding a per-provider
embedder factory (today the adapter only branches on `openai` and
`gemini`); generic retry/backoff policy changes elsewhere in the
pipeline.
- **Adjacent expectations**: the existing background-task error-handling
contract from `.kiro/steering/error-handling.md` already specifies that
worker exceptions must call `fail_task(...)`. This feature relies on
that contract — it does not introduce a new one. The single-episode
`_GraphNamespace.add(...)` path is left untouched because it already
re-raises naturally.
## Requirements
### Requirement 1: Ollama Embedder Documentation
**Objective:** As a self-hosting MiroFish operator, I want first-class
documentation for using a local Ollama embedder, so that I can run the
Graphiti pipeline without needing an OpenAI- or Gemini-compatible
embeddings endpoint.
#### Acceptance Criteria
1. The `.env.example` file shall contain a commented Ollama embedder block
showing `EMBEDDING_BASE_URL`, `EMBEDDING_API_KEY`, and `EMBEDDING_MODEL`
set to `http://host.docker.internal:11434/v1`, a non-empty placeholder
string, and `mxbai-embed-large` respectively, with a comment noting the
`ollama pull mxbai-embed-large` prerequisite.
2. The `CLAUDE.md` file shall list the three supported embedder providers
(OpenAI, Gemini, Ollama) and shall state the 1024-dim constraint that
forces `mxbai-embed-large` over `nomic-embed-text` (768-dim).
3. Where the user runs MiroFish in Docker, the docker-compose comments or
README shall note that Ollama on the host is reached from the
`mirofish` container via `host.docker.internal:11434`.
4. The documentation shall include a one-line `curl` example that calls
`$EMBEDDING_BASE_URL/embeddings` with the configured model and confirms
the response embedding length is 1024.
5. When the operator follows the documented Ollama configuration with
`mxbai-embed-large` pulled in Ollama, the existing graph-build pipeline
shall complete end-to-end and write real nodes and edges to Neo4j with
no code changes beyond the env-var configuration.
### Requirement 2: Loud Embedding Failure
**Objective:** As a MiroFish operator, I want embedding failures during
graph build to surface as a visible task failure with the underlying
error, so that I can fix my embedder configuration instead of seeing an
"empty graph" with no diagnostic.
#### Acceptance Criteria
1. The `_GraphNamespace.add_batch` method shall not return a placeholder
`_EpisodeResult` UUID when the underlying `add_episode` call raises an
exception.
2. If `add_episode` raises any exception other than a narrowly defined set
of transient network errors, then `_GraphNamespace.add_batch` shall
propagate the exception to its caller.
3. When `_GraphNamespace.add_batch` propagates an exception, the
surrounding graph-build background `Task` shall transition to
`FAILED` with `Task.error` containing a non-empty message derived from
the underlying exception (per the existing
`.kiro/steering/error-handling.md` contract).
4. While a graph-build task is failing because of a misconfigured
`EMBEDDING_MODEL`, `EMBEDDING_BASE_URL`, or `EMBEDDING_API_KEY`, the
adapter shall log the underlying `add_episode` error at `ERROR` level
(not `WARNING`) before raising, so the root cause is visible in
server logs.
5. Where the configured `EMBEDDING_MODEL` is invalid (e.g. a typo, or a
model not pulled in Ollama), the user-facing project state shall move
out of `GRAPH_BUILDING` and the task shall surface the underlying
embedder error to the frontend without producing a placeholder-UUID
"successful" episode.
6. The `_GraphNamespace.add_batch` method shall preserve its current
contract for successful episodes: each successfully ingested episode
shall still produce one `_EpisodeResult` whose `uuid_` matches the
Graphiti-assigned episode UUID, in input order.
### Requirement 3: Backwards Compatibility
**Objective:** As an existing MiroFish operator already running with an
OpenAI- or Gemini-compatible embedder, I want this change to be invisible
on the happy path, so that no upgrade action is required.
#### Acceptance Criteria
1. Where `EMBEDDING_BASE_URL`, `EMBEDDING_API_KEY`, and `EMBEDDING_MODEL`
are unset or set to OpenAI/Gemini-compatible values, the embedder
construction in `_build_llm_and_embedder` shall behave identically to
the current implementation.
2. The graph-build pipeline shall not require any new environment
variable to function; Ollama support shall be enabled purely by
setting the three existing `EMBEDDING_*` variables.
3. While Graphiti's default `EMBEDDING_DIM` is 1024, the documentation
shall explicitly note that any embedder model with a different output
dimension is unsupported by this change and is an explicit follow-up
item.