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.dev"
    )
    
    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.dev
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.dev",
    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.3.tar.gz (16.8 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.3-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for skimly-2.0.3.tar.gz
Algorithm Hash digest
SHA256 e52855a43b5164fecb2b281c030d17baf2c8c7396354b6fa8f6f6733902db4b6
MD5 1f4b684fbf948b2f0355593b6558bd34
BLAKE2b-256 2aef5c5389151278afeeaff04686e7f059e26f141fce5d6722a4b63c582316fd

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for skimly-2.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 6f87e2cff035e0244bddc507d439d5e2f13ff6b18373d69554c8ead90796da9f
MD5 ef5f455795a2d30820b49919e1eb7261
BLAKE2b-256 f3943dac09942859720c5828b4d634168a7f5e79a5b1254a65cfd76b1b02b1c4

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