Skip to main content

Production-grade Python SDK for Skimly - AI token optimization with async streaming, tools, and full API coverage

Project description

Skimly Python SDK

A production-grade Python SDK for Skimly - the drop-in gateway for AI-powered coding tools that reduces output token usage through smart compression.

Features

  • 🚀 Full Type Hints - Complete type annotations with dataclasses and TypedDict
  • 🌊 Async Streaming - Real-time streaming with AsyncIterator support
  • 🛠️ Tool Calling - Complete tool calling interface with helper functions
  • 📦 Blob Management - Large content handling with automatic deduplication
  • Performance - Built-in retry logic, timeouts, and connection pooling
  • 🔄 Provider Agnostic - Works with OpenAI, Anthropic, and other providers
  • 💾 Smart Caching - Automatic blob deduplication to reduce costs
  • 🔀 Sync & Async - Both synchronous and asynchronous clients

Installation

pip install skimly

Quick Start

from skimly import AsyncSkimlyClient

async def main():
    client = AsyncSkimlyClient(
        api_key="sk-your-api-key",
        base_url="https://api.skimly.com"
    )
    
    async with client:
        response = await client.messages.create({
            "provider": "anthropic",
            "model": "claude-3-5-sonnet-20241022",
            "max_tokens": 1024,
            "messages": [{
                "role": "user",
                "content": "Hello, world!"
            }]
        })
        
        print(response["content"][0]["text"])
        print("Tokens saved:", response["skimly_meta"]["tokens_saved"])

import asyncio
asyncio.run(main())

Streaming

async def streaming_example():
    client = AsyncSkimlyClient.from_env()
    
    async with client:
        stream = client.messages.stream({
            "provider": "openai",
            "model": "gpt-4",
            "messages": [{"role": "user", "content": "Write a story"}],
            "stream": True
        })
        
        async for chunk in stream:
            if chunk.get("type") == "content_block_delta":
                if text := chunk.get("delta", {}).get("text"):
                    print(text, end="", flush=True)

Tool Calling

async def tool_calling_example():
    client = AsyncSkimlyClient.from_env()
    
    async with client:
        response = await client.messages.create({
            "provider": "anthropic",
            "model": "claude-3-5-sonnet-20241022",
            "messages": [{"role": "user", "content": "What's the weather in SF?"}],
            "tools": [{
                "type": "function",
                "function": {
                    "name": "get_weather",
                    "description": "Get weather for a location",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "location": {"type": "string"}
                        },
                        "required": ["location"]
                    }
                }
            }]
        })
        
        # Check for tool uses
        tool_uses = [
            block for block in response["content"]
            if block.get("type") == "tool_use"
        ]
        print("Tool uses:", tool_uses)

Blob Management

async def blob_example():
    client = AsyncSkimlyClient.from_env()
    
    # Large document
    large_doc = "Very large document content..." * 1000
    
    async with client:
        # Upload blob
        blob_response = await client.create_blob(large_doc)
        blob_id = blob_response["blob_id"]
        
        # Use in chat with pointer
        response = await client.messages.create({
            "provider": "anthropic",
            "model": "claude-3-5-sonnet-20241022",
            "messages": [{
                "role": "user",
                "content": [
                    {"type": "text", "text": "Summarize this:"},
                    {"type": "pointer", "blob_id": blob_id}
                ]
            }]
        })
        
        print("Summary:", response["content"][0]["text"])
        print("Tokens saved:", response["skimly_meta"]["tokens_saved"])
        
        # Automatic deduplication
        deduped = await client.create_blob_if_new(large_doc)
        print("Same blob ID:", deduped["blob_id"] == blob_id)

Environment Setup

export SKIMLY_KEY=sk-your-api-key
export SKIMLY_BASE=https://api.skimly.com
from skimly import AsyncSkimlyClient
client = AsyncSkimlyClient.from_env()

Error Handling

from skimly import (
    SkimlyError,
    SkimlyAPIError,
    SkimlyAuthenticationError,
    SkimlyRateLimitError
)

try:
    response = await client.messages.create(params)
except SkimlyAuthenticationError:
    print("Invalid API key")
except SkimlyRateLimitError:
    print("Rate limit exceeded")
except SkimlyAPIError as e:
    print(f"API error {e.status}: {e.message}")

Configuration

client = AsyncSkimlyClient(
    api_key="sk-your-key",
    base_url="https://api.skimly.com",
    timeout=60000,        # 60 seconds
    max_retries=3,        # Retry failed requests
    default_headers={
        "User-Agent": "MyApp/1.0"
    }
)

Synchronous Client

For non-async environments:

from skimly import SkimlyClient

client = SkimlyClient.from_env()

response = client.create_message({
    "provider": "anthropic",
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 1024,
    "messages": [{
        "role": "user",
        "content": "Hello from sync client!"
    }]
})

print(response["content"][0]["text"])

Advanced Usage

Streaming Collection

from skimly import collect_stream

stream = client.messages.stream(params)
message = await collect_stream(stream)
print(message["content"][0]["text"])

Streaming Message Helper

from skimly import StreamingMessage

streaming_msg = StreamingMessage()

async for chunk in stream:
    streaming_msg.add_chunk(chunk)
    
    if streaming_msg.is_complete():
        break

print("Final text:", streaming_msg.get_text())
print("Tool uses:", streaming_msg.get_tool_uses())

Transform Tool Results

compressed = await client.transform(
    result=json.dumps(tool_output),
    tool_name="code_analysis",
    command="analyze_files",
    model="claude-3-5-sonnet-20241022"
)

Fetch with Range

content = await client.fetch_blob(
    blob_id, 
    range_params={"start": 0, "end": 1000}
)

Type Hints

Complete type definitions are included:

from skimly.types_enhanced import (
    MessageParams,
    MessageResponse,
    StreamingChunk,
    ContentBlock,
    Tool,
    SkimlyClientOptions
)

Examples

See the examples directory for complete usage examples:

Requirements

  • Python 3.8+
  • httpx
  • typing_extensions (Python < 3.11)

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

skimly-2.0.1.tar.gz (17.7 kB view details)

Uploaded Source

Built Distribution

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

skimly-2.0.1-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file skimly-2.0.1.tar.gz.

File metadata

  • Download URL: skimly-2.0.1.tar.gz
  • Upload date:
  • Size: 17.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for skimly-2.0.1.tar.gz
Algorithm Hash digest
SHA256 6fdc2d3c697815e6406e92a4bde3707c48655c614c5b27c9bda5f51b2b0c18a8
MD5 d4b9b79206c1236af70ab4f82666c812
BLAKE2b-256 a07f0bbfd4c85e944d1e25024cad0d06585080e40f617a8192ab7ae33339a7fe

See more details on using hashes here.

File details

Details for the file skimly-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: skimly-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 13.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for skimly-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 acae337dce89a761b3e13d7671bd27cea4407a96bafb8b7e122239966d695b26
MD5 8e0acb5495b061a6d606cad8f2dd2216
BLAKE2b-256 ffcffd02e191febea05ce606de0f52b4df2480d443456e35a66bce6344fd4b92

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