Skip to content

feat(api): pluggable LLM provider (Ollama/Anthropic) + /ingest/json#2

Merged
gzileni merged 2 commits into
mainfrom
feat/anthropic-llm-provider
Jun 10, 2026
Merged

feat(api): pluggable LLM provider (Ollama/Anthropic) + /ingest/json#2
gzileni merged 2 commits into
mainfrom
feat/anthropic-llm-provider

Conversation

@gzileni

@gzileni gzileni commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Introduce a small LLMProvider ABC under pipeline/llm/ (base + Ollama + Anthropic + factory) so the extraction-stage LLM is decoupled from Ollama. Selection via env: KG_LLM_PROVIDER=ollama (default) or anthropic.
  • Anthropic path uses the official anthropic SDK with Claude Haiku (claude-haiku-4-5) by default — extraction is high-volume narrow JSON, the right tool for Haiku.
  • Add POST /ingest/json for ingesting structured news articles directly (no client-side filesystem). Payload {title, body, url, source, published_at, namespace} is serialised to a temp .txt and fed through the existing pipeline (no router changes — .txt is already supported).
  • Embeddings deliberately untouched: the vector index is sized for nomic-embed-text (768 dims), so embeddings always go to Ollama regardless of KG_LLM_PROVIDER.
  • Health endpoint adds a llm_provider field; existing ollama boolean stays for backward compat.

Motivation

We are integrating this knowledge graph as the news-aware backend for a separate trading-intelligence product. That product runs entirely on Anthropic Claude (Sonnet 4.6 for predictions, Haiku 4.5 for classification) and has no local Ollama infrastructure. Routing extraction to Claude Haiku lets the KG slot in without standing up Ollama, while keeping the Ollama path 100% intact for users who prefer local inference.

/ingest/json is the matching ingress shape: news pipelines emit structured items, not files.

Test plan

  • pytest tests/23/23 green (14 new + 9 pre-existing untouched).
  • ruff check clean on every touched file.
  • Default KG_LLM_PROVIDER=ollama behaviour unchanged (existing test_ingest_txt_file still uses the Ollama HTTP mock and passes).
  • AnthropicProvider rejects construction with missing API key (RuntimeError).
  • Factory rejects unknown provider values.
  • Manual smoke test against a real Anthropic key (left to reviewers — fixtures cover the SDK shape).

Backward compatibility

  • Default KG_LLM_PROVIDER=ollama preserves the current behaviour byte-for-byte.
  • HealthResponse.ollama stays present and truthful (/api/tags reachability).
  • No existing config keys removed; new keys are additive.

🤖 Generated with Claude Code

Extraction-time LLM is now decoupled from the legacy Ollama-only path
through a small ``LLMProvider`` ABC under ``pipeline/llm/``. The active
provider is selected by ``KG_LLM_PROVIDER`` (default ``ollama``); set it
to ``anthropic`` to route extraction to Claude Haiku via the official
``anthropic`` SDK. Embeddings stay on Ollama unconditionally — the
vector index is sized for ``nomic-embed-text``.

Also adds ``POST /ingest/json`` for ingesting structured news articles
without writing files on the client side. The endpoint serialises
``{title, body, url, source, published_at, namespace}`` to a temp .txt
and feeds it through the existing pipeline (no router changes needed —
.txt is already supported).

Tests: 14 new tests (extractor refactor, both providers, factory, JSON
ingest serialisation contract). Full suite 23/23 green.
Comment thread knowledge-graph-api/api/routes/ingest.py Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 798f5c34a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +88 to +89
if provider == "anthropic" and not settings.ANTHROPIC_API_KEY:
logger.warning("health_anthropic_no_key")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the Anthropic key check in health status

When KG_LLM_PROVIDER=anthropic but ANTHROPIC_API_KEY is unset, this branch only logs a warning; all_ok still depends solely on Neo4j, Redis, and Ollama, so /health can report healthy even though the first ingestion will fail during EntityExtractor construction because AnthropicProvider.__init__ raises RuntimeError. This makes health checks miss a configuration that renders the configured extraction provider unusable.

Useful? React with 👍 / 👎.

CodeQL flagged the (whitelist-sanitised) safe_stem as "uncontrolled
data in path expression". The readable-filename feature was debug
ergonomics, not a contract — the URL and source already live inside
the file body. Use NamedTemporaryFile's random default name instead.

Tests untouched (the contract is the file contents, not the path).
@gzileni gzileni merged commit 52f6b7e into main Jun 10, 2026
6 checks passed
@gzileni gzileni deleted the feat/anthropic-llm-provider branch June 10, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants