Metadata-Version: 2.4
Name: qwen-web-sdk
Version: 0.1.1
Summary: Professional Python SDK for Qwen Web - OpenAI-compatible API client and server
Project-URL: Homepage, https://github.com/galihrhgnwn/qwen-web-sdk
Project-URL: Repository, https://github.com/galihrhgnwn/qwen-web-sdk
Project-URL: Issues, https://github.com/galihrhgnwn/qwen-web-sdk/issues
Author-email: galihrhgnwn <mirhamgunawan@gmail.com>
License: MIT
License-File: LICENSE
Keywords: ai,alibaba,api,chat,cli,llm,openai-compatible,qwen,qwen-web,sdk,streaming,tongyi
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: httpx[http2]>=0.27.0
Requires-Dist: orjson>=3.9.0
Requires-Dist: pydantic>=2.5.0
Requires-Dist: rich>=13.7.0
Requires-Dist: tenacity>=8.2.0
Requires-Dist: typer>=0.12.0
Requires-Dist: typing-extensions>=4.9.0
Requires-Dist: websockets>=12.0
Provides-Extra: all
Requires-Dist: browser-cookie3>=0.19.0; extra == 'all'
Requires-Dist: fastapi>=0.109.0; extra == 'all'
Requires-Dist: playwright>=1.40.0; extra == 'all'
Requires-Dist: python-multipart>=0.0.6; extra == 'all'
Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'all'
Provides-Extra: browser
Requires-Dist: browser-cookie3>=0.19.0; extra == 'browser'
Provides-Extra: playwright
Requires-Dist: playwright>=1.40.0; extra == 'playwright'
Provides-Extra: server
Requires-Dist: fastapi>=0.109.0; extra == 'server'
Requires-Dist: python-multipart>=0.0.6; extra == 'server'
Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'server'
Description-Content-Type: text/markdown

# Qwen Web SDK

[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

A professional Python SDK that transforms [Qwen Web](https://chat.qwen.ai) into a programmable interface with OpenAI-compatible API support.

## Features

- **Modern Python SDK** - Similar developer experience to OpenAI SDK
- **OpenAI-compatible API Server** - Drop-in replacement for OpenAI API
- **Multiple Authentication Methods**:
  - Manual token from browser
  - Automatic browser token extraction (Chrome, Brave, Edge)
  - Programmatic login with email/password
- **Streaming Support** - Real-time streaming for chat completions via SSE
- **Async Support** - Full async/await support
- **Conversation Management** - Create, list, rename, delete conversations
- **File Upload** - Upload documents for context
- **Image Generation** - Generate images through chat
- **Model Discovery** - Auto-discover available models
- **CLI Tool** - Command-line interface for all operations
- **Retry Logic** - Automatic retry with exponential backoff
- **Type Hints** - Fully typed for IDE support

## Installation

```bash
# Basic installation
pip install qwen-web-sdk

# With browser extraction support
pip install qwen-web-sdk[browser]

# With Playwright automation support
pip install qwen-web-sdk[playwright]

# With API server
pip install qwen-web-sdk[server]

# All features
pip install qwen-web-sdk[all]
```

## Quick Start

### 1. Get Your Token

Log in to [chat.qwen.ai](https://chat.qwen.ai), open browser DevTools, and run:

```javascript
localStorage.getItem("token")
```

### 2. Basic Usage

```python
from qwen_web import QwenClient

client = QwenClient(token="your-token")

# Simple chat
response = client.chat("What is machine learning?")
print(response.text)

# With specific model
response = client.chat(
    messages=[{"role": "user", "content": "Explain quantum computing"}],
    model="qwen3.7-plus"
)
print(response.text)
```

### 3. Streaming

```python
for chunk in client.chat_stream("Write a poem about AI"):
    if not chunk.done:
        print(chunk.text, end="", flush=True)
```

### 4. Async Usage

```python
import asyncio
from qwen_web import AsyncQwenClient

async def main():
    async with AsyncQwenClient(token="your-token") as client:
        response = await client.chat("Hello!")
        print(response.text)

asyncio.run(main())
```

## Authentication Methods

### Manual Token

```python
from qwen_web import QwenClient
client = QwenClient(token="your-token")
```

### Browser Extraction (Chrome, Brave, Edge)

```python
from qwen_web import QwenClient
client = QwenClient.from_browser()  # Auto-extracts token
```

### Programmatic Login

```python
from qwen_web.auth import login_with_password
token = login_with_password("your@email.com", "your-password")

from qwen_web import QwenClient
client = QwenClient(token=token)
```

### Environment Variable

```bash
export QWEN_TOKEN="your-token"
```

```python
from qwen_web import QwenClient
client = QwenClient()  # Reads from QWEN_TOKEN
```

## OpenAI Compatibility

### As Client Library

```python
from qwen_web.openai import OpenAICompatibleClient

client = OpenAICompatibleClient(token="your-token")

response = client.chat.completions.create(
    model="qwen3.7-plus",
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
```

### As API Server

Start the server:

```bash
qwen serve
# Or with options
qwen serve --host 0.0.0.0 --port 7080
```

Use with any OpenAI-compatible tool:

```python
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:7080/v1",
    api_key="sk-local-qwen"
)

response = client.chat.completions.create(
    model="qwen3.7-plus",
    messages=[{"role": "user", "content": "Hello!"}]
)
```

### Compatible Applications

- **OpenClaw** - Set provider to "OpenAI Compatible", base URL to `http://localhost:7080/v1`
- **LiteLLM** - Use as a custom provider
- **Open WebUI** - Set OpenAI API base URL
- **LibreChat** - Configure custom endpoint
- **Continue** - Add as custom provider
- **Cline** - Use OpenAI-compatible setting
- **Aider** - Set `--openai-api-base`

## CLI Commands

```bash
# Login
qwen login --token <your-token>
qwen login --browser  # Extract from browser

# User info
qwen whoami
qwen token

# List models
qwen models

# Interactive chat
qwen chat
qwen chat --message "Hello" --model qwen3.7-plus

# Manage conversations
qwen conversations
qwen conversations --delete <chat-id>

# Start API server
qwen serve
qwen serve --host 0.0.0.0 --port 7080

# Diagnostic
qwen doctor
```

## Conversation Management

```python
# List conversations
conversations = client.conversations_list()

# Create conversation
conv = client.conversation_create(title="My Chat")

# Get conversation
chat = client.conversation_get(conv["id"])

# Rename
client.conversation_rename(conv["id"], "New Title")

# Delete
client.conversation_delete(conv["id"])
```

## File Upload

```python
# Upload a file
file_info = client.upload_file("document.pdf")
print(file_info.id, file_info.url)
```

## Advanced Configuration

```python
from qwen_web import QwenClient
from qwen_web.utils import QwenConfig

config = QwenConfig(
    base_url="https://chat.qwen.ai",
    timeout=120.0,
    max_retries=3,
    locale="en-US",
    http2=True,
)

client = QwenClient(token="your-token", config=config)
```

## Model Discovery

```python
# List all models
models = client.models_list()
for model in models:
    print(f"{model.id}: {model.name}")
    print(f"  Context: {model.max_context_length}")
    print(f"  Vision: {model.capabilities.vision}")
    print(f"  Thinking: {model.capabilities.thinking}")

# Get specific model
model = client.models.get("qwen3.7-plus")
```

## Error Handling

```python
from qwen_web import QwenClient
from qwen_web.exceptions import (
    AuthenticationError,
    RateLimitError,
    QuotaExceededError,
    ModelNotFoundError,
)

client = QwenClient(token="your-token")

try:
    response = client.chat("Hello")
except AuthenticationError:
    print("Invalid token")
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}s")
except QuotaExceededError:
    print("Quota exceeded")
except ModelNotFoundError as e:
    print(f"Model not found: {e.model_id}")
```

## Development

```bash
# Clone repository
git clone https://github.com/qwen-web-sdk/qwen-web-sdk.git
cd qwen-web-sdk

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=qwen_web --cov-report=term-missing

# Lint
ruff check qwen_web tests

# Type check
mypy qwen_web
```

## API Endpoints

The API server provides these OpenAI-compatible endpoints:

| Method | Path | Description |
|--------|------|-------------|
| GET | `/v1/models` | List available models |
| POST | `/v1/chat/completions` | Chat completions (streaming supported) |
| POST | `/v1/responses` | Alias for chat completions |
| GET | `/health` | Health check |
| GET | `/version` | Server version |

## Architecture

```
qwen_web/
├── auth/           # Authentication (browser, login, session)
├── client/         # HTTP clients (sync, async)
├── chat/           # Chat completions
├── models/         # Model discovery
├── images/         # Image generation
├── files/          # File upload
├── openai/         # OpenAI compatibility layer
│   ├── compatibility.py  # Format converters
│   ├── client.py         # OpenAI-compatible client
│   └── server.py         # API server
├── types/          # Type definitions
├── utils/          # Utilities (config, headers, SSE parser)
├── exceptions.py   # Custom exceptions
└── cli.py          # Command-line interface
```

## License

MIT License - see [LICENSE](LICENSE) file.

## Disclaimer

This is an unofficial SDK. It is not affiliated with or endorsed by Alibaba Cloud or the Qwen team. Use at your own risk. The API may change without notice.
