PixiGPT Python Client
Production-grade Python client for the PixiGPT API.
Features
- 🚀 High Performance: Connection pooling with 100 connections
- 🔄 Smart Retries: Exponential backoff (0.1s → 0.8s)
- ⏱️ Timeouts: 30s default, fully configurable
- 🎯 Type Hints: Full typing support for modern Python
- 📦 Minimal Dependencies: Just
requests+urllib3 - 🔧 OpenAI Compatible: Familiar API surface
- 🧠 Chain of Thought: Server-extracted CoT reasoning in
reasoning_content - 🛠️ Tool Calling: Full OpenAI-compatible function calling support
Installation
pip install pixigpt
Quick Start
from pixigpt import Client, ChatCompletionRequest, Message
client = Client("sk-proj-YOUR_API_KEY", "https://pixigpt.com/v1")
# Option 1: With assistant personality
response = client.create_chat_completion(
ChatCompletionRequest(
assistant_id="your-assistant-id", # Optional
messages=[Message(role="user", content="Hello!")],
)
)
# Option 2: Pure OpenAI mode (no assistant)
response = client.create_chat_completion(
ChatCompletionRequest(
messages=[
Message(role="system", content="You are helpful"),
Message(role="user", content="Hello!"),
],
)
)
print(response.choices[0].message.content)
# Access chain of thought reasoning (if enable_thinking=true)
if response.choices[0].reasoning_content:
print(f"Reasoning: {response.choices[0].reasoning_content}")
Configuration
from pixigpt import Client
# Custom timeout and retries
client = Client(
api_key="sk-proj-...",
base_url="https://pixigpt.com/v1",
timeout=60, # 60 second timeout
max_retries=5, # Retry up to 5 times
)
# Custom session
import requests
session = requests.Session()
session.proxies = {"http": "http://proxy:8080"}
client = Client(
api_key="sk-proj-...",
base_url="https://pixigpt.com/v1",
session=session,
)
API Methods
Vision & Moderation
Image/video analysis and content moderation:
from pixigpt import (
VisionAnalyzeRequest,
VisionTagsRequest,
VisionOCRRequest,
VisionVideoRequest,
ModerationTextRequest,
ModerationMediaRequest,
)
# Image analysis
response = client.analyze_image(
VisionAnalyzeRequest(
image_url="https://example.com/image.jpg",
user_prompt="Describe this in detail.",
)
)
# Tag generation
response = client.analyze_image_for_tags(
VisionTagsRequest(image_url="https://example.com/image.jpg")
)
# OCR text extraction
response = client.extract_text(
VisionOCRRequest(image_url="https://example.com/document.jpg")
)
# Video analysis (< 10MB)
response = client.analyze_video(
VisionVideoRequest(
video_url="https://example.com/video.mp4",
user_prompt="Describe what happens.",
)
)
# Text moderation (11 categories)
response = client.moderate_text(
ModerationTextRequest(prompt="text to moderate")
)
# Returns: category (SAFE, SEXUAL_ADULT, UNDERAGE_SEXUAL, etc.) + score (0.0-1.0)
# Image/video moderation
response = client.moderate_media(
ModerationMediaRequest(
media_url="https://example.com/image.jpg",
is_video=False,
)
)
Moderation Categories:
- CRITICAL:
UNDERAGE_SEXUAL(priority),JAILBREAK,SUICIDE_SELF_HARM,PII,COPYRIGHT_VIOLATION - WARNING:
VIOLENT,ILLEGAL_ACTS,UNETHICAL,HATE_SPEECH - ALLOWED:
SEXUAL_ADULT(explicit only),SAFE(everything else)
Chat Completions (Stateless)
from pixigpt import ChatCompletionRequest, Message
# Basic completion
response = client.create_chat_completion(
ChatCompletionRequest(
assistant_id=assistant_id, # Optional - omit for pure OpenAI mode
messages=[
Message(role="user", content="What's the weather?"),
],
temperature=0.7,
max_tokens=2000,
enable_thinking=True, # Enable chain of thought (default: True)
)
)
# Access response
print(response.choices[0].message.content)
print(f"Tokens: {response.usage.total_tokens}")
# Access reasoning (server-provided, automatically extracted from <think> tags)
if response.choices[0].reasoning_content:
print(f"Reasoning: {response.choices[0].reasoning_content}")
Tool Calling (Function Calling)
from pixigpt import ChatCompletionRequest, Message
# Define tools (OpenAI format)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"}
},
"required": ["location"]
}
}
}
]
# Request with tools
response = client.create_chat_completion(
ChatCompletionRequest(
messages=[
Message(role="system", content="You are helpful"),
Message(role="user", content="What's the weather in Paris?"),
],
tools=tools,
)
)
# Check if model wants to call a tool
if response.choices[0].finish_reason == "tool_calls":
for tool_call in response.choices[0].message.tool_calls:
print(f"Tool: {tool_call.function.name}")
print(f"Args: {tool_call.function.arguments}")
# Execute tool, then send result back
result = {"temperature": 18, "conditions": "cloudy"}
response = client.create_chat_completion(
ChatCompletionRequest(
messages=[
Message(role="system", content="You are helpful"),
Message(role="user", content="What's the weather in Paris?"),
response.choices[0].message, # Assistant's tool call
Message(
role="tool",
content=json.dumps(result),
tool_call_id=tool_call.id,
),
],
tools=tools,
)
)
Threads (Async with Memory)
# Create thread
thread = client.create_thread()
# Add message
msg = client.create_message(thread.id, "user", "Hello!")
# Run assistant
run = client.create_run(thread.id, assistant_id, enable_thinking=True)
# Wait for completion (message included in response!)
completed_run = client.wait_for_run(thread.id, run.id)
# Access the assistant's response directly
content = completed_run.message.content[0].text["value"]
print(f"assistant: {content}")
# Access reasoning if available
if completed_run.message.reasoning_content:
print(f"Reasoning: {completed_run.message.reasoning_content}")
# Access tool execution results (Pixi tools only - when assistant has tools_config=null)
if completed_run.message.sources:
for src in completed_run.message.sources:
print(f"Source [{src.tool_name}]: {src.title} - {src.url}")
if completed_run.message.media:
for media in completed_run.message.media:
print(f"Media [{media.source}]: {media.signed_url}")
if completed_run.message.code:
for code in completed_run.message.code:
print(f"Code [{code.language}]: {code.stdout}")
Assistants
# List
assistants = client.list_assistants()
# Create
assistant = client.create_assistant(
name="My Assistant",
instructions="You are a helpful assistant.",
tools_config=None,
)
# Update
assistant = client.update_assistant(
assistant_id=assistant.id,
name="Updated Name",
instructions="New instructions",
)
# Delete
client.delete_assistant(assistant.id)
Context Manager
with Client(api_key, base_url) as client:
response = client.create_chat_completion(...)
# Session automatically closed
Error Handling
from pixigpt import APIError, is_auth_error, is_rate_limit_error
try:
response = client.create_chat_completion(request)
except APIError as e:
if is_auth_error(e):
print("Invalid API key")
elif is_rate_limit_error(e):
print("Rate limit exceeded")
else:
print(f"API error: {e}")
Chain of Thought Reasoning
When enable_thinking=True (default), the server automatically extracts reasoning from <think> tags:
response = client.create_chat_completion(
ChatCompletionRequest(
messages=[
Message(role="system", content="You are helpful"),
Message(role="user", content="Explain quantum physics"),
],
enable_thinking=True, # Default: true
)
)
# Main response (thinking tags removed by server)
print(response.choices[0].message.content)
# Reasoning content (automatically extracted by vLLM, provided in separate field)
if response.choices[0].reasoning_content:
print(f"Chain of thought: {response.choices[0].reasoning_content}")
Note: reasoning_content is provided directly by the server (vLLM extracts it). Both content and reasoning_content are automatically trimmed of whitespace. When thinking is enabled and max_tokens < 3000, it's automatically bumped to 3000 (CoT needs space).
Examples
See examples/ directory:
chat.py- Simple chat completionthread.py- Multi-turn conversationvision.py- Vision analysis and content moderation
# Install dev dependencies
pip install pixigpt[dev]
# Run examples
python examples/chat.py
python examples/vision.py
Testing
pip install pixigpt[dev]
pytest
Publishing to PyPI
# Update version in pyproject.toml
./publish.sh
License
MIT
Metadata
Release files for pixigpt 0.1.5
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 |
|---|---|---|---|---|
| pixigpt-0.1.5.tar.gz | 16.2 kB | Without provenance | Details for pixigpt-0.1.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pixigpt-0.1.5-py3-none-any.whl | Python 3 | none | any | Details for pixigpt-0.1.5-py3-none-any.whl |
Total release size: 28.6 kB
Release files / pixigpt-0.1.5.tar.gz
| Download URL | pixigpt-0.1.5.tar.gz |
|---|---|
| Size | 16.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
31cc5c4ed2227bc5fd544543b13ae44f71cd7ab1ede9c439b47f22085fef3d05
|
|
BLAKE2b-256 checksum How to use checksums |
87d14329e1342976287fcbd5696ff3561690d99f9bfe9bf2ad657e2a9533d367
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.20
|
Release files / pixigpt-0.1.5-py3-none-any.whl
| Download URL | pixigpt-0.1.5-py3-none-any.whl |
|---|---|
| Size | 12.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8dab8b2adab1804749274f1db49148fa8e478929ec76a9d2449462a14f913ad5
|
|
BLAKE2b-256 checksum How to use checksums |
1600a10650958310d62e8a0ddbe5d4a84c533c6bdeda2784784ed645adbfb9b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.20
|
Security for pixigpt 0.1.5
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.