DrekAI OpenAI Wrapper
A modern, async-first Python wrapper for OpenAI-compatible LLM APIs with built-in tool/function calling support.
Works with OpenAI, Gemini (via proxy), and any OpenAI-compatible endpoint.
✨ Features
- Async-native – built on
httpx/openaiasync client - Tool use – define Python functions as AI-callable tools with automatic sandbox parameter injection
- Streaming – stream responses token-by-token with a simple callback
- Sandboxed parameters – keep secrets invisible to the LLM while still passing them to tools
- Multi-turn chats – conversation history management
- Image support – send local files, URLs, or base64 images inline
- Thinking / reasoning – support for extended-thinking models with effort control
- Gemini compatibility – automatic tool-call shimming for Gemini models behind OpenAI proxies
📦 Installation
pip install drekai
Or install from source:
git clone https://github.com/drek124/drekai.git
cd drekai
pip install .
🚀 Quick Start
import asyncio
from drekai import Model, Chatbot
# 1. Define a model endpoint
model = Model("gpt-4o", "https://api.example.com/v1", api_key="sk-...")
# 2. Create a chatbot
bot = Chatbot(
name="Helper",
system_prompt="You are a helpful assistant.",
parent_model=model,
temperature=0.7,
)
async def main():
# One-shot generation
response = await bot.generate_text("Hello!")
print(response.choices[0].message.content)
# Multi-turn chat
chat = bot.start_chat()
r1 = await chat.generate_reply("What's the weather in Tokyo?")
print(r1.choices[0].message.content)
r2 = await chat.generate_reply("And in London?") # Context retained
print(r2.choices[0].message.content)
asyncio.run(main())
🛠️ Tool Use
from drekai import Model, Chatbot
from drekai.tools import Tool
model = Model("gpt-4o", "https://api.example.com/v1", api_key="sk-...")
bot = Chatbot("Assistant", "You are a helpful assistant.", model)
async def get_weather(city: str):
"""Get the current weather for a city."""
# In a real app, call a weather API here
return f"The weather in {city} is sunny, 25°C."
tools = [
Tool(
name="fetch_weather", # Overwrite function name if needed
callback=get_weather,
)
]
async def main():
chat = bot.start_chat()
response = await chat.generate_reply(
"What's the weather in Paris?",
tools=tools,
)
print(response.choices[0].message.content)
asyncio.run(main())
Sandboxed Parameters
Keep secrets like user IDs invisible to the LLM:
async def get_friends(user: User | SandboxParam, limit: int = 50) -> str:
"""Fetch the user's friends list."""
return str(user.get_friends(limit=limit))
tools = [
Tool(
callback=get_friends, # All info about the function name, description & parameters will be taken from the callback.
)
]
await chat.generate_reply(
"Who are my friends?",
tools=tools,
sandbox_params={"user": current_user}, # injected at call time
)
🖼️ Images
from drekai.messaging import Image
# Local file
await chat.generate_reply(
"Describe this image.",
items=[Image("/path/to/photo.jpg")],
)
# URL
await chat.generate_reply(
"Describe this image.",
items=[Image("https://example.com/photo.jpg")],
)
# Base64
await chat.generate_reply(
"Describe this image.",
items=[Image(base64_data, b64=True)],
)
📖 API Reference
Model(model_id, base_url, *, api_key)
Root model representing an API endpoint.
Chatbot(name, system_prompt, parent_model, *, api_key, temperature, thinking, reasoning_effort)
A named chatbot built on a model.
Chat
Created via chatbot.start_chat(). Manages conversation history.
| Method | Description |
|---|---|
generate_reply(...) |
Generate the next response |
add_message_to_context(content, role) |
Manually add a message |
clear() |
Reset history (keeps system prompt) |
delete_first_message(role) |
Remove first message with given role |
stop_live_generation() |
Stop an active stream mid-generation |
Tool progress callbacks
Long agentic tasks run several model turns ("batches") before the final reply. To follow them live, pass:
batch_callback(content, tool_calls)– called when a turn requests tool calls, with that turn's text (may beNone), before the tools run.tool_callback(tool, args, result)– called after each tool runs;argsholds only the model's arguments.
async def on_batch(content, tool_calls):
if content:
print(content)
async def on_tool(tool, args, result):
print(f"- used {tool.name}")
r = await chat.generate_reply("Set up the server", tools=tools,
batch_callback=on_batch, tool_callback=on_tool)
ChatSettings(max_tokens, show_tool_error_type)
Per-chat configuration.
Tool(name, description, callback)
An AI-callable function.
MessageItem / Image
Chat message attachments.
📄 License
MIT License. See LICENSE for details.
Metadata
Release files for drekai 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| drekai-1.3.0.tar.gz | 10.5 kB | Without provenance | Details for drekai-1.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| drekai-1.3.0-py3-none-any.whl | Python 3 | none | any | Details for drekai-1.3.0-py3-none-any.whl |
Total release size: 23.2 kB
Release files / drekai-1.3.0.tar.gz
| Download URL | drekai-1.3.0.tar.gz |
|---|---|
| Size | 10.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ed067f2707db64907de602d05f378f76bb9e026f4c31b9a89f80efc1bf638fd3
|
|
BLAKE2b-256 checksum How to use checksums |
a2a2729e8be608bd9bcdf7b25c104d2bf3374a657d488cd8cae84baf02c6c0ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / drekai-1.3.0-py3-none-any.whl
| Download URL | drekai-1.3.0-py3-none-any.whl |
|---|---|
| Size | 12.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
77ad807a8f84b6d99cc257da4f0a8468b57452598b5cba6011afb3b1fe8cde8b
|
|
BLAKE2b-256 checksum How to use checksums |
c9c139d1963069a3a985f41429b79ecd3fe52a36d76b9e92e9a96b55ddeff517
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for drekai 1.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.