Metadata-Version: 2.4
Name: apideepseek
Version: 0.1.1
Summary: High-performance async Python client for the private DeepSeek API
Author: inmyuse
License-Expression: MIT
Project-URL: Homepage, https://github.com/inmyuse/apideepseek
Project-URL: Documentation, https://github.com/inmyuse/apideepseek#documentation
Project-URL: Issues, https://github.com/inmyuse/apideepseek/issues
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: C++
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Framework :: AsyncIO
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.9
Dynamic: license-file

# apideepseek

<p align="left">
  <img src="docs/assets/icon.svg" width="90">
</p>

![Python](https://img.shields.io/badge/python-3.9+-blue.svg)
![Platform](https://img.shields.io/badge/platform-linux%20%7C%20windows-lightgrey)
![Async](https://img.shields.io/badge/asyncio-fully%20async-blueviolet)
![DeepSeek](https://img.shields.io/badge/API-DeepSeek-blue)

`apideepseek` is an async Python client for the private DeepSeek API. It supports token or email/password authentication, streaming responses, multi-turn conversations, image uploads, model modes, and account registration.

Russian documentation: [docs/ru/README.md](docs/ru/README.md)

## Installation

```bash
pip install apideepseek
```

Building from source requires a C++17 compiler with AVX2 support and `pybind11` for the PoW extension. See [docs/en/pow.md](docs/en/pow.md).

## Quick Start

### Ask One Question

```python
import asyncio
from apideepseek import DeepSeekClient

async def main():
    async with DeepSeekClient(token="YOUR_TOKEN") as client:
        result = await client.ask("Hello!")
        print(result.text)

asyncio.run(main())
```

You can also log in with email and password:

```python
async with DeepSeekClient(email="myname@example.com", password="password123") as client:
    result = await client.ask("Hello!")
    print(result.text)
```

## Model Modes

Use `ModelType` when creating the client or for a single request.

| Mode | Use When | Code |
|------|----------|------|
| Fast/default | Normal text chat, fastest general mode | `ModelType.DEFAULT` |
| Expert | Harder reasoning or expert answers | `ModelType.EXPERT` |
| Vision/recognition | Questions about an image | `ModelType.VISION` |

```python
import asyncio
from apideepseek import DeepSeekClient, ModelType

async def main():
    async with DeepSeekClient(token="YOUR_TOKEN", model=ModelType.DEFAULT) as client:
        fast = await client.ask("Short answer: what is asyncio?")
        expert = await client.ask(
            "Analyze the tradeoffs in detail",
            model=ModelType.EXPERT,
        )
        print(fast.text)
        print(expert.text)

asyncio.run(main())
```

## Attach an Image to a Prompt

The current upload helper supports PNG and JPEG images. It does not upload arbitrary PDF, DOCX, TXT, or ZIP files.

The simplest form is passing `Path` directly to `ask`; the client uploads the image and attaches it to the prompt:

```python
import asyncio
from pathlib import Path
from apideepseek import DeepSeekClient, ModelType

async def main():
    async with DeepSeekClient(token="YOUR_TOKEN") as client:
        result = await client.ask(
            "What is shown in this image?",
            image=Path("photo.jpg"),
            model=ModelType.VISION,
        )
        print(result.text)

asyncio.run(main())
```

If you want to reuse the same image in several requests, upload it once:

```python
img = await client.upload_image(Path("photo.jpg"))
result = await client.ask("Describe the image", image=img, model=ModelType.VISION)
```

Raw bytes also work:

```python
data = Path("photo.png").read_bytes()
result = await client.ask("Read the text in this image", image=data, model=ModelType.VISION)
```

## Create a New Conversation

Use `client.new_conversation()` for a multi-turn chat. The `Conversation` object remembers the last `message_id` and sends it as `parent_message_id` on the next turn.

```python
import asyncio
from apideepseek import DeepSeekClient

async def main():
    async with DeepSeekClient(token="YOUR_TOKEN") as client:
        chat = client.new_conversation()
        first = await chat.ask("My name is Alex. Remember it.")
        second = await chat.ask("What is my name?")
        print(first.text)
        print(second.text)

asyncio.run(main())
```

Create another independent thread by creating another `Conversation`:

```python
chat_a = client.new_conversation()
chat_b = client.new_conversation()
```

## Streaming

By default `ask_stream()` yields only new text fragments. Use `cumulative=True` if you need the full text so far on every iteration.

```python
async for chunk in client.ask_stream("Tell me about Python"):
    print(chunk, end="", flush=True)
```

Streaming also works inside a conversation:

```python
chat = client.new_conversation()
async for chunk in chat.ask_stream("Explain async/await"):
    print(chunk, end="", flush=True)
```

## Register a New Account

```python
import asyncio
from apideepseek import DeepSeekClient

async def main():
    await DeepSeekClient.send_reg_code("myname@example.com")
    code = input("Code from email: ")
    token = await DeepSeekClient.confirm_reg_code(
        "myname@example.com",
        "password123",
        code,
    )
    print("Token:", token)

asyncio.run(main())
```

## Result Object

`ask()` and `Conversation.ask()` return `DeepSeekTurnResult`:

```python
result = await client.ask("Hello")
print(result.text)        # full assistant response
print(result.session_id)  # DeepSeek chat session id
print(result.message_id)  # assistant message id for threading
```

## Error Handling

```python
from apideepseek import DeepSeekClient, AuthorizationError, DeepSeekError

try:
    async with DeepSeekClient(token="invalid") as client:
        await client.ask("Hello")
except AuthorizationError:
    print("Token is invalid")
except DeepSeekError as e:
    print(f"API error: {e}")
```

## Documentation

- [DeepSeekClient methods](docs/en/client.md)
- [Conversation](docs/en/conversation.md)
- [Data types](docs/en/types.md)
- [Exceptions](docs/en/exceptions.md)
- [Proof-of-Work](docs/en/pow.md)

## Requirements

- Python 3.9+
- `aiohttp >= 3.9`
- C++17 compiler with AVX2 to build the PoW extension from source, or a prebuilt wheel
