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, generic file uploads, model modes, and account registration.
Russian documentation: docs/ru/README.md
pip install apideepseekBuilding from source requires a C++17 compiler with AVX2 support and pybind11 for the PoW extension. See docs/en/pow.md.
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())Email/password login also works:
async with DeepSeekClient(email="myname@example.com", password="password123") as client:
result = await client.ask("Hello!")
print(result.text)| Mode | Use When | Code |
|---|---|---|
| Fast/default | Normal text chat and most file questions | ModelType.DEFAULT |
| Expert | Harder reasoning or expert answers | ModelType.EXPERT |
| Vision/recognition | Questions about images | ModelType.VISION |
from apideepseek import DeepSeekClient, ModelType
async with DeepSeekClient(token="...", model=ModelType.DEFAULT) as client:
fast = await client.ask("Short answer: what is asyncio?")
expert = await client.ask("Analyze this deeply", model=ModelType.EXPERT)Use file= for one file and files= for several files. Paths are uploaded automatically before the prompt is sent.
from pathlib import Path
from apideepseek import DeepSeekClient
async with DeepSeekClient(token="...") as client:
result = await client.ask(
"Summarize this file",
file=Path("notes.txt"),
)
print(result.text)You can attach source code the same way:
result = await client.ask(
"Review this function and explain what it returns",
file=Path("sample_code.py"),
)Attach several files:
result = await client.ask(
"Compare the JSON config with the CSV data",
files=[Path("config.json"), Path("data.csv")],
)Upload once and reuse the file object:
uploaded = await client.upload_file(Path("report.pdf"))
first = await client.ask("Summarize the report", file=uploaded)
second = await client.ask("List the key risks", file=uploaded)Raw bytes work too, but you must provide a filename so DeepSeek can detect the format:
data = Path("contract.docx").read_bytes()
uploaded = await client.upload_file(data, filename="contract.docx")
result = await client.ask("Extract the main obligations", file=uploaded)Common formats are passed through the same upload endpoint: TXT, Python/source code, JSON, CSV, PDF, DOCX, and other formats DeepSeek accepts. If DeepSeek rejects a file as empty or unsupported, EmptyUploadedFileError or DeepSeekError is raised.
Images can be attached through image= or through the generic file= parameter. Use image=/upload_image() when you want local PNG/JPEG validation and image dimensions.
from pathlib import Path
from apideepseek import DeepSeekClient, ModelType
async with DeepSeekClient(token="...") as client:
result = await client.ask(
"What is shown in this image?",
image=Path("photo.jpg"),
model=ModelType.VISION,
)
print(result.text)Reuse an uploaded image:
img = await client.upload_image(Path("photo.jpg"))
result = await client.ask("Describe the image", image=img, model=ModelType.VISION)Use client.new_conversation() for a multi-turn chat. It remembers the last message_id and sends it as parent_message_id on the next turn.
chat = client.new_conversation()
await chat.ask("Remember the attached file", file=Path("notes.txt"))
reply = await chat.ask("What did the file say?")
print(reply.text)async for chunk in client.ask_stream("Tell me about Python"):
print(chunk, end="", flush=True)Streaming works with files too:
async for chunk in client.ask_stream("Summarize this file", file=Path("notes.txt")):
print(chunk, end="", flush=True)result = await client.ask("Hello")
print(result.text)
print(result.session_id)
print(result.message_id)