Skip to main content

Production-grade Python client for the PixiGPT API

Project description

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:

# 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

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

pixigpt-0.1.5.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pixigpt-0.1.5-py3-none-any.whl (12.4 kB view details)

Uploaded Python 3

File details

Details for the file pixigpt-0.1.5.tar.gz.

File metadata

  • Download URL: pixigpt-0.1.5.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.20

File hashes

Hashes for pixigpt-0.1.5.tar.gz
Algorithm Hash digest
SHA256 31cc5c4ed2227bc5fd544543b13ae44f71cd7ab1ede9c439b47f22085fef3d05
MD5 52750175ba55548a16961f2651939048
BLAKE2b-256 87d14329e1342976287fcbd5696ff3561690d99f9bfe9bf2ad657e2a9533d367

See more details on using hashes here.

File details

Details for the file pixigpt-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: pixigpt-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 12.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.20

File hashes

Hashes for pixigpt-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 8dab8b2adab1804749274f1db49148fa8e478929ec76a9d2449462a14f913ad5
MD5 5baeec47f540204bbcb12d987692ff0a
BLAKE2b-256 1600a10650958310d62e8a0ddbe5d4a84c533c6bdeda2784784ed645adbfb9b8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page