Tutorial DeepSeek Python

How to Build an AI Chatbot with DeepSeek API

Complete step-by-step tutorial to create a production-ready chatbot with streaming, memory, and multi-turn conversations

What We'll Build

By the end of this tutorial, you'll have built a fully functional AI chatbot with these features:

Our chatbot will use DeepSeek V4 via the TokenEase API gateway, giving you access to one of the most capable Chinese AI models with OpenAI-compatible endpoints.

Prerequisites

Why TokenEase? Instead of managing multiple API providers, TokenEase gives you unified access to DeepSeek, GLM, Qwen, Kimi, and Doubao through a single OpenAI-compatible endpoint. One key, all models.

Project Setup

Let's create our project structure:

mkdir deepseek-chatbot
cd deepseek-chatbot
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install flask requests python-dotenv

Create a .env file with your API key:

TOKENEASE_API_KEY=your_api_key_here
MODEL=deepseek

Basic Chat Implementation

Let's start with a simple script that sends a message and gets a response:

import os
import requests
from dotenv import load_dotenv

load_dotenv()

API_KEY = os.getenv("TOKENEASE_API_KEY")
API_URL = "https://tokenease.io/v1/chat/completions"

def chat(message, history=None):
    if history is None:
        history = []
    
    messages = history + [{"role": "user", "content": message}]
    
    response = requests.post(
        API_URL,
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json"
        },
        json={
            "model": os.getenv("MODEL", "deepseek"),
            "messages": messages,
            "temperature": 0.7,
            "max_tokens": 2000
        }
    )
    
    if response.status_code == 200:
        return response.json()["choices"][0]["message"]["content"]
    else:
        return f"Error: {response.status_code} - {response.text}"

# Test it
if __name__ == "__main__":
    reply = chat("Hello! What can you help me with?")
    print(reply)
Pro Tip: The endpoint is fully OpenAI-compatible. If you have code using OpenAI's API, just change the base URL and API key - everything else stays the same.

Adding Streaming Responses

Streaming makes the chatbot feel much more responsive. Here's how to implement it:

import json

def chat_streaming(message, history=None):
    if history is None:
        history = []
    
    messages = history + [{"role": "user", "content": message}]
    
    response = requests.post(
        API_URL,
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json"
        },
        json={
            "model": os.getenv("MODEL", "deepseek"),
            "messages": messages,
            "stream": True,  # Enable streaming
            "temperature": 0.7,
            "max_tokens": 2000
        },
        stream=True
    )
    
    full_response = ""
    for line in response.iter_lines():
        if line:
            line = line.decode('utf-8')
            if line.startswith('data: '):
                data = line[6:]
                if data == '[DONE]':
                    break
                try:
                    chunk = json.loads(data)
                    if chunk['choices'][0]['delta'].get('content'):
                        content = chunk['choices'][0]['delta']['content']
                        full_response += content
                        print(content, end='', flush=True)
                except:
                    pass
    
    return full_response

# Test streaming
if __name__ == "__main__":
    print("Bot: ", end='', flush=True)
    chat_streaming("Explain quantum computing in simple terms")

Conversation Memory

To make conversations natural, we need to maintain context. Here's a simple memory implementation:

class ChatBot:
    def __init__(self, max_history=10):
        self.history = []
        self.max_history = max_history
    
    def add_message(self, role, content):
        self.history.append({"role": role, "content": content})
        # Keep only recent messages to manage token usage
        if len(self.history) > self.max_history * 2:
            self.history = self.history[-self.max_history * 2:]
    
    def chat(self, message, stream=False):
        self.add_message("user", message)
        
        if stream:
            response = self._chat_streaming(self.history)
        else:
            response = self._chat_basic(self.history)
        
        self.add_message("assistant", response)
        return response
    
    def _chat_basic(self, messages):
        # Same as earlier chat() function
        response = requests.post(API_URL, headers={...}, json={...})
        return response.json()["choices"][0]["message"]["content"]
    
    def clear_history(self):
        self.history = []

# Usage
bot = ChatBot(max_history=10)
print(bot.chat("Hi, I'm Bob"))
print(bot.chat("What's my name?"))  # Remembers you're Bob!
Token Management: Conversation history consumes tokens. Set max_history based on your expected conversation length. For long conversations, consider summarizing older messages.

Simple Web UI

Let's create a web interface using Flask:

from flask import Flask, render_template, request, jsonify

app = Flask(__name__)
bot = ChatBot(max_history=10)

@app.route("/")
def home():
    return render_template("chat.html")

@app.route("/chat", methods=["POST"])
def chat_endpoint():
    data = request.json
    message = data.get("message", "")
    
    if not message:
        return jsonify({"error": "No message provided"}), 400
    
    try:
        response = bot.chat(message, stream=False)
        return jsonify({"response": response})
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route("/clear", methods=["POST"])
def clear():
    bot.clear_history()
    return jsonify({"status": "cleared"})

if __name__ == "__main__":
    app.run(debug=True, port=5000)

Create templates/chat.html:

<!DOCTYPE html>
<html>
<head>
    <title>DeepSeek Chatbot</title>
    <style>
        body { max-width: 800px; margin: 0 auto; padding: 20px; font-family: Arial; }
        #chat { border: 1px solid #ddd; height: 400px; overflow-y: auto; padding: 20px; margin-bottom: 20px; }
        .message { margin: 10px 0; padding: 10px; border-radius: 8px; }
        .user { background: #e3f2fd; text-align: right; }
        .bot { background: #f5f5f5; }
        #input-area { display: flex; gap: 10px; }
        input { flex: 1; padding: 10px; }
        button { padding: 10px 20px; background: #2563eb; color: white; border: none; cursor: pointer; }
    </style>
</head>
<body>
    <h1>DeepSeek Chatbot</h1>
    <div id="chat"></div>
    <div id="input-area">
        <input type="text" id="message" placeholder="Type your message...">
        <button onclick="send()">Send</button>
        <button onclick="clearChat()">Clear</button>
    </div>
    <script>
        async function send() {
            const input = document.getElementById('message');
            const msg = input.value;
            if (!msg) return;
            
            addMessage('user', msg);
            input.value = '';
            
            const res = await fetch('/chat', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({message: msg})
            });
            const data = await res.json();
            addMessage('bot', data.response);
        }
        
        function addMessage(role, text) {
            const chat = document.getElementById('chat');
            chat.innerHTML += `<div class="message ${role}">${text}</div>`;
            chat.scrollTop = chat.scrollHeight;
        }
        
        async function clearChat() {
            await fetch('/clear', {method: 'POST'});
            document.getElementById('chat').innerHTML = '';
        }
        
        document.getElementById('message').addEventListener('keypress', e => {
            if (e.key === 'Enter') send();
        });
    </script>
</body>
</html>

Production Considerations

Before deploying to production, consider these improvements:

ConcernSolution
Rate limitingImplement request throttling per user
Error handlingAdd retries with exponential backoff
SecurityValidate inputs, sanitize outputs, use HTTPS
Cost controlSet max_tokens, monitor usage via dashboard
ScalabilityUse async frameworks (FastAPI) for high concurrency
MonitoringLog conversations, track error rates

Advanced: Switching Models

With TokenEase, switching between models is trivial:

# Use GLM-5 instead of DeepSeek
os.environ["MODEL"] = "zhipu"

# Or Doubao for speed
os.environ["MODEL"] = "doubao"

# Or Kimi for long context
os.environ["MODEL"] = "kimi"

# Same code, different model - that's the power of a unified API
Model Selection Guide:
  • DeepSeek - Best reasoning and coding
  • GLM-5 - Strong Chinese language understanding
  • Doubao - Fastest response times
  • Kimi - Longest context window (up to 2M tokens)
  • Qwen - Excellent multilingual capabilities

Ready to Build Your Chatbot?

Get started with $1 free credit - no credit card required

Access DeepSeek, GLM, Qwen, Kimi & Doubao with one API key

Get Free API Key →
T

TokenEase Team

Building the easiest way to access Chinese AI models. Follow us for more tutorials and AI insights.