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.2.tar.gz (16.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.2-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: skimly-2.0.2.tar.gz
  • Upload date:
  • Size: 16.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.2.tar.gz
Algorithm Hash digest
SHA256 a49fc0ed1d4fe26f77996e7f1adda74225dec5cbb8ca8c127277a752a2912163
MD5 7a88c94402b8f8eb3efc872d5831137c
BLAKE2b-256 630303bc414aba3c492408551f00015c644743a2b374ded647912b0b067303ee

See more details on using hashes here.

File details

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

File metadata

  • Download URL: skimly-2.0.2-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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f3ae7410e2b3e4df78280ea13cccf1886a547e85581cf0f9a9c0ca09d9dabc4b
MD5 1f5ab32d9e4fdeb7f7ffacc9f43aee32
BLAKE2b-256 38018f9fd1b87188d84b1756b8c13e0c46121fcc1d19b735ff679f5fdc152255

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