Skip to content

[Extensibility 3/4] feat: local LLMs via Ollama, behind ENABLE_OLLAMA (stacked on #259) - #261

Closed
amal66 wants to merge 2 commits into
Open-Legal-Products:mainfrom
amal66:olp-pr/ollama
Closed

[Extensibility 3/4] feat: local LLMs via Ollama, behind ENABLE_OLLAMA (stacked on #259)#261
amal66 wants to merge 2 commits into
Open-Legal-Products:mainfrom
amal66:olp-pr/ollama

Conversation

@amal66

@amal66 amal66 commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #259 — merge that first; until it merges, this diff shows its commit too. This PR's own change is the single Ollama commit.

Closes #23.

Summary

Opt-in local LLM support via Ollama's OpenAI-compatible endpoint: a self-hosted deployment can run chat inference entirely on its own hardware — documents never leave the building, and with this flag neither does inference. Everything is behind ENABLE_OLLAMA=true (default off): with the flag unset, no new models appear and nothing changes.

Changes

  • providers/ollama.ts (new): registry entry that routes local model IDs (llama3.3, phi4, qwen2.5, + OLLAMA_MODELS extras) through the existing OpenAI adapter pointed at http://localhost:11434/v1. No new dependencies, no new streaming code path.
  • baseUrl.ts (new) + openai.ts: OPENAI_BASE_URL resolution with an SSRF guard — http/localhost/private-IP endpoints rejected in production unless explicitly allowed. Defaults to https://api.openai.com/v1 (unchanged when unset).
  • privateIp.ts (new): shared private/reserved IP classifier (IPv4 + IPv6 incl. mapped/NAT64/6to4).
  • .env.example: documents the opt-in config.
  • Tests: ollama gate, baseUrl, privateIp (21 tests).

Why

The most-requested self-hosting capability (#23), done as a registry entry instead of a bespoke client — the first external provider to use the registry, which is exactly what it was built for.

Testing

On this branch: backend npm test300 passed, 5 skipped (includes the 21 new tests). Flag gate verified: only the exact string "true" registers the provider.

Provenance

Mechanical port of code running in amal66/mike (main); privateIp.ts and providers/ollama.ts byte-identical to the fork. Full provenance in amal66#34.

🤖 Generated with Claude Code

@amal66
amal66 requested a review from willchen96 July 26, 2026 14:10
@amal66

amal66 commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator Author

Keeping this in draft — an adversarial re-review found three confirmed bugs to fix first: (1) the https-in-production check fires before OPENAI_ALLOW_LOCAL_BASE_URL is consulted, so the documented production config throws on every request; (2) the reused OpenAI tool loop depends on previous_response_id, which Ollama's stateless endpoint silently drops — tool-using chats lose all context; (3) the model picker is a static list, so enabled Ollama models aren't selectable from the UI. Please skip this one until it's reworked — #259/#260/#262 are the reviewable part of the series.

amal66 and others added 2 commits August 2, 2026 18:51
Replace the per-provider if/else chains in lib/llm/index.ts and the
env-var switch in lib/userApiKeys.ts with a provider registry
(lib/llm/registry.ts) and an API-key provider table
(core/apiKeyProviders.ts). Adding a provider is now a
registerProvider()/registerApiKeyProvider() call — no edits to
index.ts, models.ts, or userApiKeys.ts required.

Ported from the amal66/mike monorepo fork (origin/main, b3166dd);
mechanical translation into the backend/ layout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEguyEgXa9JjCciXCcVemC
…OLLAMA)

Mechanical port from b3166dd (apps/api -> backend):
- lib/llm/providers/ollama.ts: Ollama adapter registered through the
  provider registry, gated by ENABLE_OLLAMA (off by default)
- lib/llm/baseUrl.ts: OPENAI_BASE_URL resolution with SSRF guard
  (OPENAI_ALLOW_LOCAL_BASE_URL) so the OpenAI adapter can point at a
  local Ollama server
- lib/privateIp.ts: shared private/reserved IP classifier used by the
  base-URL guard
- lib/llm/openai.ts: fetch openAIResponsesUrl() instead of the
  hard-coded api.openai.com constant
- lib/llm/index.ts: register Ollama in registerBuiltinProviders() when
  ENABLE_OLLAMA=true
- .env.example: document the opt-in Ollama configuration
- tests for the ollama gate, base-URL resolution, and IP classifier

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEguyEgXa9JjCciXCcVemC
@willchen96

Copy link
Copy Markdown
Collaborator

Closing as superseded by the Ollama implementation already on main.

The current implementation includes dynamic model discovery, frontend model selection, tool-calling with conversation context preserved, configurable connection settings, optional authentication, and documentation.

This draft is also conflicting and its known issues are addressed by the implementation now on main, so there is nothing remaining here that needs to be merged.

@willchen96 willchen96 closed this Aug 5, 2026
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.

Allow for self-hosted inference engines.

2 participants