mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-12 22:14:05 +00:00
The backend import package is now docsgpt, the name it will carry on PyPI; application was far too generic to install into anyone's site-packages. git mv plus a mechanical rewrite of every import, dotted string and path reference: 734 Python files, the compose files, Dockerfile, workflows, docs, setup scripts, devcontainer, k8s manifests, vscode config, pytest and coverage config, .gitignore. Behaviour is unchanged. Kept for one release: - A top-level application package whose meta-path finder resolves application.x.y to the already-imported docsgpt.x.y object, so old imports and entry points (celery -A application.app.celery, uvicorn application.asgi:asgi_app) keep working with a FutureWarning. - Celery registers every application.* task name as an alias of its docsgpt.* task on start-up, so messages queued by the previous release still run. The redbeat key prefix moves to redbeat:docsgpt:v2: so schedule entries the previous release wrote are left unread instead of firing twice. The backend image builds from the repository root (docker build -f docsgpt/Dockerfile .) so it can ship the alias package; a root .dockerignore allow-lists docsgpt/ and application/ and keeps caches, local data, .env files, the sample index files and the Dockerfile out. Compose and the image workflows point at the new context.
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 docsgpt.core.model_settings import AvailableModel
|
|
from docsgpt.core.model_yaml import ProviderCatalog
|
|
from docsgpt.core.settings import Settings
|
|
from docsgpt.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 ``docsgpt/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)
|