Provider Discovery and Loading Mechanism in aisuite's ProviderFactory
The ProviderFactory in aisuite dynamically discovers and loads LLM providers at runtime using a file-based naming convention and importlib for dynamic imports, allowing new providers to be added without modifying core factory code.
aisuite is a Python library that unifies interactions with multiple large language model (LLM) providers behind a common interface. The core of this abstraction lies in ProviderFactory, implemented in aisuite/provider.py, which handles automatic discovery and instantiation of provider-specific implementations located in the aisuite/providers/ directory.
How Provider Discovery Works in aisuite
The discovery mechanism relies on strict file naming conventions and dynamic Python imports. This design eliminates the need for manual registration of new providers.
File-Based Registration Convention
Every provider implementation follows a rigid naming pattern. Each provider lives in a separate file named <key>_provider.py (e.g., openai_provider.py, google_provider.py) and defines a class named <Key>Provider (e.g., OpenaiProvider, GoogleProvider).
To add support for a new LLM service, you only need to create a new file in aisuite/providers/ that follows this pattern. No changes to ProviderFactory or any registry are required.
Scanning the Providers Directory
The ProviderFactory uses the PROVIDERS_DIR constant to locate the providers subdirectory. When get_supported_providers() is called, it scans this directory for all files ending with _provider.py, strips the suffix to extract the provider key, and returns a set of available keys. This method is decorated with @functools.cache to ensure repeated calls are inexpensive.
Key Components of the ProviderFactory
The factory implementation in aisuite/provider.py contains three critical components that enable dynamic loading.
Provider Abstract Base Class
The Provider class defines the minimal API contract that every concrete implementation must satisfy. All providers must implement the chat_completions_create method to ensure a uniform interface across OpenAI, Google, Anthropic, and other services.
Dynamic Import via create_provider
The ProviderFactory.create_provider(key, config) method performs dynamic loading using Python's importlib module:
- It constructs the expected module name as
f"{key}_provider"and class name asf"{key.capitalize()}Provider" - Uses
importlib.import_module(f"aisuite.providers.{module_name}")to load the module - Retrieves the class via
getattr(module, class_name) - Instantiates the provider with the supplied configuration dictionary
If the module cannot be imported, the factory raises a clear ImportError and suggests calling ProviderFactory.get_supported_providers() to list valid keys.
Cached Provider Enumeration
The get_supported_providers() method provides runtime introspection of available backends. By caching the directory scan results, it ensures that UI components (like dropdown menus) can quickly enumerate supported providers without filesystem overhead.
Practical Implementation Examples
Creating a Provider Instance
To instantiate a specific provider, pass the provider key and configuration dictionary to the factory:
from aisuite.provider import ProviderFactory
config = {
"api_key": "sk-...",
"model": "gpt-4o-mini",
}
# Dynamically loads aisuite/providers/openai_provider.py
openai_provider = ProviderFactory.create_provider("openai", config)
# Use the common interface
response = openai_provider.chat_completions_create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello world"}],
)
print(response)
Listing Supported Providers
You can query which providers are available before attempting instantiation:
from aisuite.provider import ProviderFactory
available = ProviderFactory.get_supported_providers()
print("Supported providers:", sorted(available))
# Output: ['anthropic', 'aws', 'azure', 'google', 'openai', ...]
Dynamic Provider Selection
Implement runtime provider selection with validation:
def get_provider(key: str, cfg: dict):
if key not in ProviderFactory.get_supported_providers():
raise ValueError(f"Unsupported provider: {key}")
return ProviderFactory.create_provider(key, cfg)
provider = get_provider("google", {"api_key": "..."})
Extending aisuite with Custom Providers
The factory's use of standard Python import mechanics means you can extend aisuite without modifying the core library. Any third-party module that respects the naming scheme (<key>_provider.py with <Key>Provider class) can be dropped into the aisuite/providers/ directory. The factory will automatically discover and load it on the next instantiation request.
This extensibility makes aisuite suitable for enterprise environments where custom internal LLM endpoints need to integrate with the same interface used for commercial providers like OpenAI and Anthropic.
Summary
- File-based discovery: Providers are automatically discovered via the
<key>_provider.pynaming convention inaisuite/providers/ - Dynamic imports:
ProviderFactory.create_provider()usesimportlib.import_moduleandgetattrto load classes at runtime - Strict naming: Each provider file must contain a class named
<Key>Provider(e.g.,OpenaiProviderinopenai_provider.py) - Cached enumeration:
get_supported_providers()scans the directory once and caches results usingfunctools.cache - Zero-registration: Adding new providers requires only creating a file; no registry updates needed
Frequently Asked Questions
How does ProviderFactory handle missing or invalid provider keys?
If you pass an invalid key to ProviderFactory.create_provider(), the method attempts to import a non-existent module, catches the failure, and raises an ImportError with a message suggesting you call ProviderFactory.get_supported_providers() to see valid options.
Where are the concrete provider implementations located?
Concrete implementations reside in individual files within the aisuite/providers/ directory. For example, OpenAI support is implemented in aisuite/providers/openai_provider.py, Google in aisuite/providers/google_provider.py, and Anthropic in aisuite/providers/anthropic_provider.py.
Can I add a custom provider without modifying the aisuite source code?
Yes. As long as you follow the naming convention (<key>_provider.py with a <Key>Provider class) and place the file in the aisuite/providers/ directory, ProviderFactory will automatically discover and load it. The factory uses standard Python import mechanics, so any module following this pattern is eligible for dynamic loading.
What is the performance impact of provider discovery?
Minimal. The get_supported_providers() method uses @functools.cache to memoize the directory scan results. After the first call, subsequent invocations return the cached set instantly, making it suitable for high-frequency operations like populating UI dropdowns.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →