From 2c155a3383fb97f8367baf7e7e4ec27edb71a3e5 Mon Sep 17 00:00:00 2001 From: Ben Dines Date: Tue, 9 Jun 2026 15:40:51 -0700 Subject: [PATCH] Add CustomProvider for custom OpenAI compatible LLM providers # Summary For Issue #77 (Add Ollama LLM Provider). While ollama technically has its own REST API, it also supports standard OpenAI compatible calls (the `/v1` base url instead of `/api`). This means we can still use the openai module, and support any other local LLM provider (thus the "custom" name instead of "ollama"). Signed-off-by: Ben Dines --- .../src/dna/llm_providers/custom_provider.py | 27 +++++++++++++++++++ .../dna/llm_providers/llm_provider_base.py | 5 ++++ 2 files changed, 32 insertions(+) create mode 100644 backend/src/dna/llm_providers/custom_provider.py diff --git a/backend/src/dna/llm_providers/custom_provider.py b/backend/src/dna/llm_providers/custom_provider.py new file mode 100644 index 00000000..30b1f504 --- /dev/null +++ b/backend/src/dna/llm_providers/custom_provider.py @@ -0,0 +1,27 @@ +"""Custom OpenAI Compatible LLM Provider. + +Custom OpenAI Compatible implementation of the LLM provider interface. +""" + +import os + +from openai import AsyncOpenAI + +from dna.llm_providers.llm_provider_base import LLMProviderBase + + +class CustomProvider(LLMProviderBase): + """Custom OpenAI Compatible implementation of the LLM provider.""" + + LLM_PROVIDER_NAME = "CUSTOM_LLM" + + DEFAULT_MODEL = "gpt-oss-20b" + DEFAULT_URL = "http://localhost:11434/v1" + + def _get_provider_client(self): + """Construct an instance of the LLM provider's client.""" + return AsyncOpenAI( + api_key=self.api_key, + base_url=os.getenv(f"{self.LLM_PROVIDER_NAME}_URL", self.DEFAULT_URL), + timeout=self.timeout, + ) diff --git a/backend/src/dna/llm_providers/llm_provider_base.py b/backend/src/dna/llm_providers/llm_provider_base.py index 017372dd..f1d4cedb 100644 --- a/backend/src/dna/llm_providers/llm_provider_base.py +++ b/backend/src/dna/llm_providers/llm_provider_base.py @@ -346,4 +346,9 @@ def get_llm_provider() -> LLMProviderBase: return OpenAIProvider() + if provider_type == "custom": + from dna.llm_providers.custom_provider import CustomProvider + + return CustomProvider() + raise ValueError(f"Unknown LLM provider: {provider_type}")