How to Implement a Custom Provider Using AbstractProvider in GPT4Free
To implement a custom provider in GPT4Free, subclass AbstractProvider from g4f/providers/base_provider.py, implement the required create_completion method, declare metadata class attributes like label and working, and import your class in g4f/Provider/__init__.py to auto-register it with the routing system.
The gpt4free library (repository xtekky/gpt4free) routes every LLM request through a provider—a class that encapsulates communication with a specific endpoint. While the framework includes dozens of built-in providers, you can extend it by subclassing AbstractProvider, which lives in g4f/providers/base_provider.py and handles parameter marshaling, streaming helpers, and error bridging.
Understanding the Provider Architecture
All providers inherit from a thin ABC called BaseProvider (defined in g4f/providers/types.py), which establishes the public API surface. AbstractProvider builds on this by implementing the heavy-lifting logic and forcing subclasses to provide a concrete create_completion implementation.
Core Responsibilities
When you subclass AbstractProvider, you must implement:
create_completion(cls, model, messages, **kwargs): A synchronous method that returns aCreateResult(typically a generator yielding strings orImageResponseobjects). This is called byAbstractProvider.create_functionand the async helpercreate_asyncdefined in the base class.- Class metadata: Attributes like
label,working,supports_stream, andsupports_message_historytell the router, CLI (g4f/cli/__init__.py), and GUI whether the provider is available and what capabilities it offers. - Optional async support: If you inherit from
AsyncGeneratorProviderinstead, you implementcreate_async_generatorto yield chunks asynchronously.
Model Discovery with ProviderModelMixin
For endpoints that support multiple model names, mix in ProviderModelMixin. This adds get_models(), default_model, and model_aliases attributes, which the router uses in g4f/providers/any_provider.py to match model strings to providers. Many built-in providers use this mixin to expose model discovery without hardcoding lists in multiple places.
Creating a Minimal Synchronous Provider
For a simple HTTP endpoint that returns complete responses (no streaming), subclass AbstractProvider and return a generator yielding the final text.
# g4f/Provider/my_custom_provider.py
from __future__ import annotations
from ..typing import CreateResult, Messages
from ..providers.base_provider import AbstractProvider, ProviderModelMixin
class MyCustomProvider(AbstractProvider, ProviderModelMixin):
"""Wrapper for a fictional MyLLM API endpoint."""
label = "MyLLM"
working = True
supports_stream = False
supports_message_history = True
supports_system_message = True
@classmethod
def get_models(cls):
return ["mymodel-v1", "mymodel-v2"]
@classmethod
def create_completion(
cls,
model: str,
messages: Messages,
**kwargs,
) -> CreateResult:
import json, requests
payload = {"model": model, "messages": messages}
payload.update(kwargs)
resp = requests.post(
"https://api.my-llm.com/v1/chat/completions",
json=payload,
headers={"Authorization": f"Bearer {kwargs.get('api_key')}"}
)
resp.raise_for_status()
data = resp.json()
text = data["choices"][0]["message"]["content"]
def generator():
yield text
return generator()
Implementing an Async Streaming Provider
For real-time streaming, inherit from AsyncGeneratorProvider (also in g4f/providers/base_provider.py) and implement create_async_generator.
# g4f/Provider/my_streaming_provider.py
from __future__ import annotations
import json
import aiohttp
from ..typing import AsyncResult, Messages
from ..providers.base_provider import AsyncGeneratorProvider, ProviderModelMixin
class MyStreamingProvider(AsyncGeneratorProvider, ProviderModelMixin):
label = "MyStreamingLLM"
working = True
supports_stream = True
supports_message_history = True
supports_system_message = True
@classmethod
async def create_async_generator(
cls,
model: str,
messages: Messages,
stream: bool = True,
**kwargs,
) -> AsyncResult:
async with aiohttp.ClientSession() as session:
async with session.post(
"https://api.my-llm.com/v1/chat/completions",
json={"model": model, "messages": messages, "stream": stream},
headers={"Authorization": f"Bearer {kwargs.get('api_key')}"},
) as resp:
async for line in resp.content:
if line.startswith(b"data: "):
payload = json.loads(line[6:].decode())
chunk = payload["choices"][0]["delta"].get("content", "")
if chunk:
yield chunk
Registering the Provider
The framework auto-discovers providers through a dynamic import scan in g4f/Provider/__init__.py. The file automatically builds Provider.__providers__ by inspecting all imported classes that subclass BaseProvider. Once your module is imported there, it becomes available to the router and CLI.
Add an import statement to g4f/Provider/__init__.py:
from .my_custom_provider import MyCustomProvider
from .my_streaming_provider import MyStreamingProvider
This registration step populates Provider.__map__ (a dictionary mapping class names to providers) and makes your class accessible via g4f.Provider.MyCustomProvider.
Using Your Custom Provider
After registration, use your provider explicitly or through the generic router.
Explicit usage:
import g4f
response = g4f.Provider.MyCustomProvider.create_completion(
model="mymodel-v1",
messages=[{"role": "user", "content": "Hello world"}],
api_key="MY_API_KEY"
)
print("".join(response))
Router usage (requires model aliases setup via ProviderModelMixin):
import g4f
answer = g4f.ChatCompletion.create(
model="mymodel-v1",
messages=[{"role": "user", "content": "Explain quantum computing"}],
)
print(answer)
Summary
- Subclass
AbstractProviderfor synchronous providers orAsyncGeneratorProviderfor streaming async providers, both defined ing4f/providers/base_provider.py. - Implement
create_completion(sync) orcreate_async_generator(async) to return a generator yielding text chunks or image responses. - Declare metadata attributes (
label,working,supports_stream) so the CLI and GUI can filter and display your provider according to the logic ing4f/Provider/__init__.py. - Mix in
ProviderModelMixinif your endpoint supports multiple models and you want automatic model discovery viaget_models(). - Import your class in
g4f/Provider/__init__.pyto register it with the framework's auto-discovery system used by the CLI (g4f/cli/__init__.py) and GUI parsers.
Frequently Asked Questions
What is the difference between BaseProvider and AbstractProvider?
BaseProvider (in g4f/providers/types.py) is a minimal abstract base class defining the interface contract, while AbstractProvider (in g4f/providers/base_provider.py) provides concrete implementations for parameter handling, streaming logic, and error bridging. You almost always want to subclass AbstractProvider rather than BaseProvider directly, as the latter requires you to re-implement framework plumbing.
Do I need to implement both sync and async versions of my provider?
No. If you inherit from AbstractProvider, you only need to implement create_completion. The base class provides create_async automatically by running your sync code in an executor. For high-performance streaming, inherit from AsyncGeneratorProvider and implement create_async_generator instead, which the router will detect via the supports_stream attribute.
How does the framework discover my new provider?
The g4f/Provider/__init__.py file dynamically scans all imported modules and collects any class that is a subclass of BaseProvider into Provider.__providers__. As long as you import your class in that file (or in a file already imported there), it will appear in the CLI --provider list and the GUI dropdown automatically, as both interfaces query the __providers__ list and filter by the working attribute.
Why is my provider not showing up in the CLI or GUI?
Ensure your class has working = True and that you have imported the module in g4f/Provider/__init__.py. The CLI (g4f/cli/__init__.py) and GUI parsers filter providers using the working attribute; setting it to False hides the provider from user interfaces while keeping it available for direct programmatic use.
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 →