Official Python SDK for Reno AI API
Project description
Reno AI SDK
Official Python client for the Reno API. Simple, fast, and built with production use in mind.
Table of Contents
- Installation
- Quick Start
- Authentication
- Making Requests
- Models
- Response Objects
- Error Handling
- Error Codes Reference
- Configuration
- Running Tests
Installation
pip install renoai
Requires Python 3.8 or higher.
Quick Start
from renoai import Reno
client = Reno(api_key="reno_sk_xxx")
answer = client.ask("What is machine learning?")
print(answer)
Authentication
Every request requires an API key. You can pass it directly or load it from an environment variable (recommended for production):
import os
from renoai import Reno
client = Reno(api_key=os.environ["RENO_API_KEY"])
API keys follow the format reno_sk_.... Keep them secret and never commit them to version control.
Making Requests
ask()
The simplest way to get a response. Sends a single message and returns the reply as a plain string.
answer = client.ask("Explain quantum computing in simple terms.")
print(answer)
With an optional system prompt:
answer = client.ask(
"What is the boiling point of water?",
system="You are a science teacher. Keep answers under 2 sentences.",
temperature=0.3,
max_tokens=100,
)
print(answer)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
prompt |
str |
required | The user's question or instruction |
system |
str |
None |
Optional system message |
model |
str |
gemma2:2b-instruct |
Model to use |
temperature |
float |
0.7 |
Sampling temperature, 0 to 2 |
max_tokens |
int |
None |
Maximum tokens to generate |
chat()
Full control over the conversation with a list of messages. Returns a Completion object.
response = client.chat([
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is Python?"},
{"role": "assistant", "content": "Python is a high-level programming language."},
{"role": "user", "content": "What is it mainly used for?"},
])
print(response.text)
print(response.usage.total_tokens)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
messages |
list |
required | List of {"role": ..., "content": ...} dicts |
model |
str |
gemma2:2b-instruct |
Model to use |
temperature |
float |
0.7 |
Sampling temperature, 0 to 2 |
max_tokens |
int |
None |
Maximum tokens to generate |
stream |
bool |
False |
Enable streaming mode |
Valid roles are user, assistant, and system.
Streaming
Stream tokens as they are generated instead of waiting for the full response.
Using stream_text() — yields plain strings, the easiest option:
for token in client.stream_text("Write me a short poem about the ocean."):
print(token, end="", flush=True)
print()
Using chat() with stream=True — yields StreamChunk objects for full control:
chunks = client.chat(
[{"role": "user", "content": "Tell me a story."}],
stream=True,
)
full_text = ""
for chunk in chunks:
if chunk.delta:
full_text += chunk.delta
print(chunk.delta, end="", flush=True)
if chunk.is_final:
print(f"\n\nFinished. Reason: {chunk.finish_reason}")
Conversations
Conversation manages message history automatically so you can focus on the dialogue.
from renoai import Reno, Conversation
client = Reno(api_key="reno_sk_xxx")
conv = Conversation(client, system="You are a friendly cooking assistant.")
print(conv.say("What should I make for dinner tonight?"))
print(conv.say("I only have chicken and rice."))
print(conv.say("How long will it take?"))
You can inspect or reset the history at any time:
# See the full message history
print(conv.history)
# Reset but keep the system prompt
conv.reset(keep_system=True)
# Reset everything
conv.reset(keep_system=False)
Models
Pass any supported model name via the model parameter:
response = client.chat(
[{"role": "user", "content": "Hello!"}],
model="gemma2:2b-instruct",
)
The default model is gemma2:2b-instruct.
Response Objects
Completion
Returned by chat() when not streaming.
response = client.chat([{"role": "user", "content": "Hi"}])
response.text # the generated reply as a string
response.content # alias for response.text
response.id # unique response ID
response.model # model that generated the response
response.choices # list of Choice objects
response.usage # token usage info
response.to_message() # {"role": "assistant", "content": "..."} ready to append to history
response.to_dict() # raw API response as a dict
Usage
response.usage.prompt_tokens # tokens in your input
response.usage.completion_tokens # tokens in the reply
response.usage.total_tokens # total tokens consumed
StreamChunk
Yielded by streaming calls.
chunk.delta # the new text in this chunk (str or None)
chunk.finish_reason # "stop" on the last chunk, None otherwise
chunk.is_final # True when this is the last chunk
chunk.to_dict() # raw chunk data
Error Handling
The SDK raises typed exceptions so you can handle each failure case precisely.
from renoai import (
RenoError,
RenoConnectionError,
RenoTimeoutError,
RenoValidationError,
)
import time
try:
answer = client.ask("Hello")
except RenoValidationError as e:
# Bad input before the request was even sent
print("Fix your input:", e.message)
except RenoConnectionError as e:
# Could not reach the server at all
print("Server unreachable:", e.message)
except RenoTimeoutError as e:
# Request started but took too long
print("Timed out:", e.message)
except RenoError as e:
# Any other API-level error
print(e.user_friendly())
if e.is_retryable:
wait = e.retry_after or 5
print(f"Retrying in {wait}s...")
time.sleep(wait)
Exception Hierarchy
RenoError # base class for all SDK exceptions
RenoConnectionError # network or DNS failure (code 6002)
RenoTimeoutError # request exceeded timeout (code 6003)
RenoValidationError # invalid input caught client-side (code 2001)
RenoError Properties
| Property | Type | Description |
|---|---|---|
code |
int |
Reno error code |
message |
str |
Short description of the error |
details |
str |
Extra context or suggestion from the server |
is_retryable |
bool |
Whether it is safe to retry this request |
retry_after |
float |
Seconds to wait before retrying (from Retry-After header) |
user_friendly() |
str |
Formatted message with title, description, and tip |
Production Loop Example
import time
from renoai import Reno, RenoError, RenoConnectionError, RenoTimeoutError, RenoValidationError
client = Reno(api_key="reno_sk_xxx")
while True:
try:
answer = client.ask("Summarize today's AI news.")
print(answer)
except RenoValidationError as e:
print("Validation error:", e.message)
break # code bug, do not retry
except RenoConnectionError:
print("Connection failed, retrying in 10s...")
time.sleep(10)
continue
except RenoTimeoutError:
print("Timed out, retrying in 5s...")
time.sleep(5)
continue
except RenoError as e:
if e.is_retryable:
wait = e.retry_after or 5
print(f"Retryable error [{e.code}], waiting {wait}s...")
time.sleep(wait)
continue
else:
print(e.user_friendly())
break # auth, billing, content policy, etc.
except KeyboardInterrupt:
print("Stopped.")
break
time.sleep(3)
client.close()
Error Codes Reference
| Range | Category |
|---|---|
| 1001 to 1008 | Authentication and API key errors |
| 2001 to 2009 | Request validation errors |
| 3001 to 3007 | Model availability errors |
| 4001 to 4005 | Token and context length errors |
| 5001 to 5006 | Rate limiting and quota errors |
| 6001 to 6006 | Server and infrastructure errors |
| 7001 to 7004 | Content moderation errors |
| 8001 to 8004 | Billing and subscription errors |
| 9001 to 9004 | Internal and unexpected errors |
Call error.user_friendly() on any RenoError to get a plain-English title, description, and actionable tip for any of these codes.
Configuration
Client Options
client = Reno(
api_key="reno_sk_xxx",
base_url="http://127.0.0.1:8000/api/v1", # default
timeout=30, # seconds, default 30
max_retries=3, # default 3
)
Context Manager
The client can be used as a context manager to ensure the HTTP session is always closed:
with Reno(api_key="reno_sk_xxx") as client:
print(client.ask("Hello!"))
Running Tests
pip install pytest
pytest tests/ -v
To run a specific test file or test:
pytest tests/test_renoai.py -v
pytest tests/test_renoai.py::TestClientRequests::test_ask_success -v
License
MIT License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 renoai-0.1.6.tar.gz.
File metadata
- Download URL: renoai-0.1.6.tar.gz
- Upload date:
- Size: 23.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8077fc4a89fcb181d4297789b00ddf4daade36a96cdb55d564d1424c539eb695
|
|
| MD5 |
ab682ee06dc9efaa39095dc1eef50b04
|
|
| BLAKE2b-256 |
144576c3e10330ac975194aa98b92c2aca5dbb46bf63f8366218b43f1aea5e2d
|
File details
Details for the file renoai-0.1.6-py3-none-any.whl.
File metadata
- Download URL: renoai-0.1.6-py3-none-any.whl
- Upload date:
- Size: 15.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf81f9a14118f2b01d1b87b7d5a01d0f19f91c1d6157f3d8f8604453e2e6c4bf
|
|
| MD5 |
4f7c9ea66e8cdadbc075a60787153bcb
|
|
| BLAKE2b-256 |
088e55d25098dc0c6c0c4fa3acfd42bda6f5212676bf63f9c5c00f89e1f65cc7
|