fed8b2eed7
Build and push multi-arch DocsGPT Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Has been cancelled
Backend release / release (push) Has been cancelled
Bandit Security Scan / bandit_scan (push) Has been cancelled
Build and push multi-arch DocsGPT Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Has been cancelled
Build and push multi-arch DocsGPT Docker image / manifest (push) Has been cancelled
Build and push DocsGPT FE Docker image for development / build (linux/amd64, ubuntu-latest, amd64) (push) Has been cancelled
Build and push DocsGPT FE Docker image for development / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Has been cancelled
Build and push DocsGPT FE Docker image for development / manifest (push) Has been cancelled
Python linting / ruff (push) Has been cancelled
Run python tests with pytest / Run tests and count coverage (3.12) (push) Has been cancelled
React Widget Build / build (push) Has been cancelled
75 lines
2.9 KiB
Python
75 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import TYPE_CHECKING, ClassVar, List, Optional, Type
|
|
|
|
if TYPE_CHECKING:
|
|
from application.core.model_settings import AvailableModel
|
|
from application.core.model_yaml import ProviderCatalog
|
|
from application.core.settings import Settings
|
|
from application.llm.base import BaseLLM
|
|
|
|
|
|
class Provider(ABC):
|
|
"""Owns the *behavior* of an LLM provider.
|
|
|
|
Concrete providers declare their name, the LLM class to instantiate,
|
|
and how to resolve credentials from settings. Static model catalogs
|
|
live in YAML under ``application/core/models/`` and are joined to the
|
|
provider by name at registry load time.
|
|
|
|
Most plugins receive zero or one catalog at registry-build time. The
|
|
``openai_compatible`` plugin is the exception: it receives one catalog
|
|
per matching YAML file, each with its own ``api_key_env`` and
|
|
``base_url``. Plugins that need per-catalog metadata override
|
|
``get_models``; the default implementation merges catalogs and routes
|
|
through ``filter_yaml_models`` + ``extra_models``.
|
|
"""
|
|
|
|
name: ClassVar[str]
|
|
# ``None`` means the provider appears in the catalog but isn't
|
|
# dispatchable through LLMCreator (e.g. Hugging Face today, where the
|
|
# original LLMCreator dict had no entry).
|
|
llm_class: ClassVar[Optional[Type["BaseLLM"]]] = None
|
|
|
|
@abstractmethod
|
|
def get_api_key(self, settings: "Settings") -> Optional[str]:
|
|
"""Return the API key for this provider, or None if unavailable."""
|
|
|
|
def is_enabled(self, settings: "Settings") -> bool:
|
|
"""Whether this provider should contribute models to the registry."""
|
|
return bool(self.get_api_key(settings))
|
|
|
|
def filter_yaml_models(
|
|
self, settings: "Settings", models: List["AvailableModel"]
|
|
) -> List["AvailableModel"]:
|
|
"""Hook to filter YAML-loaded models. Default: return all."""
|
|
return models
|
|
|
|
def extra_models(self, settings: "Settings") -> List["AvailableModel"]:
|
|
"""Hook to add dynamic models not declared in YAML. Default: none."""
|
|
return []
|
|
|
|
def get_models(
|
|
self,
|
|
settings: "Settings",
|
|
catalogs: List["ProviderCatalog"],
|
|
) -> List["AvailableModel"]:
|
|
"""Final list of models this plugin contributes.
|
|
|
|
Default: merge the models across all matched catalogs (later
|
|
catalog wins on duplicate id), filter via ``filter_yaml_models``,
|
|
then append ``extra_models``. Override when per-catalog metadata
|
|
matters (see ``OpenAICompatibleProvider``).
|
|
"""
|
|
merged: List["AvailableModel"] = []
|
|
seen: dict = {}
|
|
for c in catalogs:
|
|
for m in c.models:
|
|
if m.id in seen:
|
|
merged[seen[m.id]] = m
|
|
else:
|
|
seen[m.id] = len(merged)
|
|
merged.append(m)
|
|
return self.filter_yaml_models(settings, merged) + self.extra_models(settings)
|