Unified LLM provider interface for multi-agent systems
Project description
Provider Hub
Unified LLM provider interface for multi-agent systems.
Table of Contents
Installation
pip install provider_hub
Quick Start
1. Environment Setup
Create a .env file in your project root:
OPENAI_API_KEY=your-openai-api-key
DEEPSEEK_API_KEY=your-deepseek-api-key
DASHSCOPE_API_KEY=your-qwen-api-key
ARK_API_KEY=your-doubao-api-key
2. Basic Usage
from provider_hub import LLM
# Simple text chat
llm = LLM(
model="doubao-seed-1-6-250615",
temperature=0.7,
top_p=0.9,
max_tokens=100,
timeout=30
)
response = llm.chat("Hello, how are you?")
print(response.content)
Core Features
📝 Text Processing
All models support standard text chat functionality with configurable parameters.
from provider_hub import LLM
llm = LLM(
model="qwen-plus",
temperature=0.7,
top_p=0.9,
max_tokens=100,
timeout=30
)
response = llm.chat("Explain quantum computing")
print(response.content)
🖼️ Vision Processing
Process both local images and URLs with vision-capable models.
from provider_hub import LLM, ChatMessage, prepare_image_content
# Vision model setup
vision_llm = LLM(
model="qwen-vl-plus",
temperature=0.5,
max_tokens=150,
timeout=60
)
# Process local image
image_content = prepare_image_content("path/to/your/image.jpg")
# Or process image URL
# image_content = prepare_image_content("https://example.com/image.jpg")
messages = [ChatMessage(
role="user",
content=[
{"type": "text", "text": "What do you see in this image?"},
image_content
]
)]
response = vision_llm.chat(messages)
print(response.content)
You can also include multiple images in the same request by preparing each image and appending them to the content list:
# Prepare local images
image_content1 = prepare_image_content("path/to/your/image1.jpg")
image_content2 = prepare_image_content("path/to/your/image2.jpg")
# Add more images as needed
# Create a message with text + multiple images
messages = [
ChatMessage(
role="user",
content=[
{"type": "text", "text": "What do you see in these images?"},
image_content1,
image_content2,
# Add additional image_content items here
]
)
]
# Continue with the rest of your code...
🧠 Reasoning Mode
Enable step-by-step reasoning for complex problem solving.
from provider_hub import LLM
# DeepSeek reasoning
deepseek_reasoning = LLM(
model="deepseek-reasoner",
thinking=True,
temperature=0.3,
max_tokens=200,
timeout=60
)
# Qwen reasoning
qwen_reasoning = LLM(
model="qwen3-max-preview",
thinking=True,
temperature=0.5,
max_tokens=180,
timeout=50
)
# Doubao reasoning
doubao_reasoning = LLM(
model="doubao-seed-1-6-250615",
thinking={"type": "enabled"},
temperature=0.4,
max_tokens=200,
timeout=45
)
response = qwen_reasoning.chat("Calculate 15 * 23 step by step")
print(response.content)
💬 System prompt
Set a default system prompt when creating an LLM so it is automatically prepended to every request. system_prompt accepts either a simple string or a list of structured system messages (dicts with role/content).
Examples:
from provider_hub import LLM
# Simple string system prompt
llm = LLM(
model="doubao-seed-1-6-250615",
temperature=0.7,
top_p=0.9,
max_tokens=100,
timeout=30,
system_prompt="You are a concise assistant."
)
response = llm.chat("Explain recursion in one paragraph")
print(response.content)
# Structured system prompt (list of role/content dicts)
llm2 = LLM(
model="doubao-seed-1-6-250615",
temperature=0.7,
top_p=0.9,
max_tokens=100,
timeout=30,
system_prompt=[{"role": "system", "content": "You are a helpful assistant."}]
)
response2 = llm2.chat("Summarize the API")
print(response2.content)
Notes:
- If you pass a
systemrole message directly tochat(...)it will raise aValueErrorto avoid duplicate system prompts; prefer usingsystem_promptat initialization. system_promptsupports both string and structured list formats. But for list formats, the"role"can only be set to"system".
📡 Streaming mode
*only support Doubao and Qwen models for now This library provides two mechanisms for controlling streaming behavior when supported by a provider:
stream(bool):True: The provider returns an iterator that yields partial chunk dictionaries as the model generates its response.False(default): The provider returns a finalChatResponseobject.
stream_options(dict[str, bool]): Additional options for streaming responses. Only set this whenstream=True.- Qwen:
{"include_usage": True}→ includes the total token usage in the last line of the output.
- Doubao:
{"include_usage": True}→ includes the total token usage in the last line of the output.{"chunk_include_usage": True}→ includes the cumulative token usage in every chunk of the output.
- Qwen:
Usage examples:
from provider_hub import LLM
# Simple string system prompt
llm = LLM(
model="doubao-seed-1-6-250615",
temperature=0.7,
top_p=0.9,
max_tokens=100,
timeout=30,
stream=True,
stream_options={"include_usage": True}
)
response = llm.chat("Hello, how are you?")
for chunk in response:
for choice in chunk.choices:
if choice.delta.content:
print(chunk.model_dump_json())
for chunk in response:
if chunk.choices:
for choice in chunk.choices:
# only print chunks that include response
if choice.delta.content:
print(chunk.model_dump_json())
# Print the last line with total token usage
else:
print(chunk.model_dump_json())
# # Or if you only want to flush out the response word by word:
# for chunk in response:
# for choice in chunk.choices:
# if choice.delta.content:
# print(choice.delta.content, end='', flush=True)
# print()
# # Print only total token usage data
# else:
# print("\n", chunk.usage)
{"id":"0217588133559349544d93cbdf8c60805d428c33f3725821804f8","choices":[{"delta":{"content":"Hello","function_call":null,"role":"assistant","tool_calls":null,"reasoning_content":null},"finish_reason":null,"moderation_hit_type":null,"index":0,"logprobs":null}],"created":1758813356,"model":"doubao-seed-1-6-250615","service_tier":"default","object":"chat.completion.chunk","usage":null}
{"id":"0217588133559349544d93cbdf8c60805d428c33f3725821804f8","choices":[{"delta":{"content":"!","function_call":null,"role":"assistant","tool_calls":null,"reasoning_content":null},"finish_reason":null,"moderation_hit_type":null,"index":0,"logprobs":null}],"created":1758813356,"model":"doubao-seed-1-6-250615","service_tier":"default","object":"chat.completion.chunk","usage":null}
...
{"id":"0217588133559349544d93cbdf8c60805d428c33f3725821804f8","choices":[{"delta":{"content":" 😊","function_call":null,"role":"assistant","tool_calls":null,"reasoning_content":null},"finish_reason":null,"moderation_hit_type":null,"index":0,"logprobs":null}],"created":1758813356,"model":"doubao-seed-1-6-250615","service_tier":"default","object":"chat.completion.chunk","usage":null}
{"id":"0217588133559349544d93cbdf8c60805d428c33f3725821804f8","choices":[],"created":1758813356,"model":"doubao-seed-1-6-250615","service_tier":null,"object":"chat.completion.chunk","usage":{"completion_tokens":124,"prompt_tokens":90,"total_tokens":214,"prompt_tokens_details":{"cached_tokens":0,"provisioned_tokens":null},"completion_tokens_details":{"reasoning_tokens":106,"provisioned_tokens":null}}}
Note:
- Not all providers or models support streaming. Always check a model’s capabilities before enabling streaming to avoid runtime errors.
stream_optionsis provider-specific. Refer to the provider’s documentation for the supported keys.
⚡ OpenAI GPT-5 Reasoning Effort
GPT-5 models support adjustable reasoning intensity through the chat method.
from provider_hub import LLM
gpt5_reasoning = LLM(
model="gpt-5",
max_tokens=200,
timeout=40
)
response = gpt5_reasoning.chat(
"Solve this complex problem step by step",
reasoning_effort="high" # Options: "low", "medium", "high"
)
print(response.content)
API Reference
Parameters
| Parameter | Type | Description | Range/Options |
|---|---|---|---|
model |
string | Model identifier | See Supported Models |
temperature |
float | Controls randomness | 0.0-2.0 (0=deterministic, 2=very creative) |
top_p |
float | Nucleus sampling threshold | 0.0-1.0 |
max_tokens |
int | Maximum response length | Positive integer |
timeout |
int | Request timeout | Seconds (default: 30) |
thinking |
bool/dict | Enable reasoning mode | Provider-specific format |
reasoning_effort |
string | GPT-5 reasoning intensity | "low", "medium", "high" |
Parameter Support by Provider
| Parameter | OpenAI | DeepSeek | Qwen | Doubao | Notes |
|---|---|---|---|---|---|
temperature |
✅ | ✅ | ✅ | ✅ | GPT-5 series limited to 1.0 |
top_p |
✅ | ✅ | ✅ | ✅ | Full support |
max_tokens |
✅ | ✅ | ✅ | ✅ | GPT-5 auto-converts to max_completion_tokens |
timeout |
✅ | ✅ | ✅ | ✅ | Full support |
thinking |
❌ | ✅ | ✅ | ✅ | Model-specific availability |
reasoning_effort |
✅ | ❌ | ❌ | ❌ | GPT-5 series only |
Provider-Specific Notes
OpenAI
- GPT-5 series: Only support
temperature=1.0, usereasoning_effortinstead ofthinking - GPT-4.1: Full parameter support
- Reasoning: Use
reasoning_effort="high"for complex problems
DeepSeek
- Thinking support: Only
deepseek-reasonermodel - Format:
thinking=True - Best for: Mathematical and logical reasoning
Qwen
- Thinking support: Only
qwen3-*models (qwen3-max-preview, qwen3-coder-plus, qwen3-coder-flash) - Format:
thinking=True - Vision models: qwen-vl-max, qwen-vl-plus support image processing
Doubao
- Thinking support: All models
- Format:
thinking={"type": "enabled"} - Vision support: doubao-seed-1-6-vision-250815
Classes
LLM
Main interface for all LLM providers.
llm = LLM(
model="model-name",
temperature=0.7,
max_tokens=100,
# ... other parameters
)
Methods:
chat(messages, **kwargs)→ChatResponse: Send messages and get responsereasoning_effort(OpenAI GPT-5 only): "low", "medium", "high"
ChatMessage
Container for structured messages.
message = ChatMessage(
role="user", # "user", "assistant"
content="text or list of content items"
)
ChatResponse
Response object from LLM.
Attributes:
content: Response textmodel: Model usedusage: Token usage statisticsfinish_reason: Completion reason
Utility Functions
prepare_image_content(image_input)
Prepares image content for vision models.
# Local file
image_content = prepare_image_content("./image.jpg")
# URL
image_content = prepare_image_content("https://example.com/image.jpg")
test_connection()
Quick connectivity test for available models.
from provider_hub import test_connection
test_connection()
Supported Models
OpenAI
gpt-5gpt-5-minigpt-5-nanogpt-4.1
DeepSeek
deepseek-chatdeepseek-reasoner
Qwen
qwen3-max-previewqwen-plusqwen-flashqwen3-coder-plusqwen3-coder-flashqwen-vl-maxqwen-vl-plus
Doubao
doubao-seed-1-6-250615doubao-seed-1-6-vision-250815doubao-seed-1-6-flash-250828
Testing
Quick Test
Test connectivity to available models:
from provider_hub import test_connection
test_connection()
Comprehensive Test Suite
Run full model testing with detailed reports:
python test_connection.py
This generates:
test_report.json- Machine-readable resultstest_report.md- Human-readable report
CLI: running provider tests
This project includes a small CLI entry point (provider-hub) to run provider connection tests from the repository.
Flags supported:
-
-t,--test:- No args: run the full test suite.
- Two args: run a single-model test:
provider model. - Example (run all):
provider-hub -t
- Example (single model + disable thinking):
provider-hub -t Doubao doubao-seed-1-6-250615
- Example (single model + enable thinking):
provider-hub -t Doubao doubao-seed-1-6-250615 -k
-
-q,--quick-test:- No args: run all quick tests.
- One arg: run quick tests for a single provider.
- Example (run all quick tests):
provider-hub -q
- Example (quick test for Doubao):
provider-hub -q Doubao
-
-k,--thinking:- A boolean flag used together with a single-model
-tinvocation to enable provider "thinking" where supported.
- A boolean flag used together with a single-model
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file provider_hub-0.4.0.tar.gz.
File metadata
- Download URL: provider_hub-0.4.0.tar.gz
- Upload date:
- Size: 22.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d6f65755513a5b786559d7a0122a933d6ff9ab71b7cce4a9ae19446ba25de62
|
|
| MD5 |
2a23fe4904744fc869d11930dfc27ecd
|
|
| BLAKE2b-256 |
d869d7a0fff0ba434698dbb86d1e31e67f4041d7119c0d5557934095a68fe89c
|
File details
Details for the file provider_hub-0.4.0-py3-none-any.whl.
File metadata
- Download URL: provider_hub-0.4.0-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a56363418e0159c1763d96200e36343a21c1732b68beb074a82d24f25f60ac0
|
|
| MD5 |
1a64ac4fae8115da9deb2af8d65779b4
|
|
| BLAKE2b-256 |
00d5fbd8956c55e6e2c785fbde6ffeac81b5262c83aa6964d853e2fa7e95234e
|