Building AI Chatbots with Chinese Models: Complete Developer Guide (2026)

August 14, 2026 · 20 min read

AI chatbots are the most common production application of large language models. This guide walks you through building a production-ready chatbot using Chinese AI models via TokenEase — from basic conversation handling to advanced features like memory, personas, and multi-turn context management.

Architecture Overview

┌─────────────┐     ┌──────────────┐     ┌─────────────┐     ┌─────────────┐
│   User      │────▶│   Web/App    │────▶│  Chatbot    │────▶│  TokenEase  │
│  Interface  │◀────│   Frontend   │◀────│   Backend   │◀────│    API      │
└─────────────┘     └──────────────┘     └─────────────┘     └─────────────┘
                                                │
                                                ▼
                                         ┌─────────────┐
                                         │   Database  │
                                         │  (Memory)   │
                                         └─────────────┘

Step 1: Basic Chatbot Backend

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
import requests
import uuid
from datetime import datetime

app = FastAPI()
TOKEN = "your_tokenease_api_key"
BASE_URL = "https://tokenease.io/v1"

class Message(BaseModel):
    role: str  # "user" or "assistant"
    content: str
    timestamp: Optional[str] = None

class ChatRequest(BaseModel):
    message: str
    session_id: Optional[str] = None
    model: str = "deepseek-v4"

class ChatResponse(BaseModel):
    response: str
    session_id: str
    tokens_used: int

# In-memory session store (use Redis in production)
sessions = {}

def get_session_history(session_id: str) -> List[dict]:
    """Retrieve conversation history for a session"""
    return sessions.get(session_id, [])

def add_to_session(session_id: str, message: dict):
    """Add message to session history"""
    if session_id not in sessions:
        sessions[session_id] = []
    sessions[session_id].append(message)
    
    # Keep last 20 messages to manage context window
    if len(sessions[session_id]) > 20:
        sessions[session_id] = sessions[session_id][-20:]

@app.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest):
    """Main chat endpoint"""
    
    # Generate session ID if new
    session_id = request.session_id or str(uuid.uuid4())
    
    # Get conversation history
    history = get_session_history(session_id)
    
    # Build messages array
    messages = history + [{"role": "user", "content": request.message}]
    
    # Call TokenEase API
    try:
        response = requests.post(
            f"{BASE_URL}/chat/completions",
            headers={"Authorization": f"Bearer {TOKEN}"},
            json={
                "model": request.model,
                "messages": messages,
                "temperature": 0.7,
                "max_tokens": 1024
            }
        )
        
        data = response.json()
        assistant_message = data["choices"][0]["message"]["content"]
        tokens_used = data.get("usage", {}).get("total_tokens", 0)
        
        # Update session
        add_to_session(session_id, {"role": "user", "content": request.message})
        add_to_session(session_id, {"role": "assistant", "content": assistant_message})
        
        return ChatResponse(
            response=assistant_message,
            session_id=session_id,
            tokens_used=tokens_used
        )
        
    except Exception as e:
        raise HTTPException(500, f"Chat error: {str(e)}")

@app.get("/chat/{session_id}/history")
async def get_history(session_id: str):
    """Get conversation history"""
    return {"session_id": session_id, "messages": get_session_history(session_id)}

@app.delete("/chat/{session_id}")
async def clear_session(session_id: str):
    """Clear conversation history"""
    if session_id in sessions:
        del sessions[session_id]
    return {"status": "cleared"}

Step 2: Adding a System Persona

PERSONAS = {
    "helpful_assistant": {
        "name": "Helpful Assistant",
        "system_prompt": "You are a helpful, friendly assistant. Answer questions accurately and concisely."
    },
    "code_expert": {
        "name": "Code Expert",
        "system_prompt": "You are an expert programmer. Provide clean, well-commented code with explanations. Prefer Python and modern best practices."
    },
    "creative_writer": {
        "name": "Creative Writer",
        "system_prompt": "You are a creative writing assistant. Help with storytelling, character development, and editing. Be imaginative and encouraging."
    },
    "customer_support": {
        "name": "Customer Support",
        "system_prompt": "You are a professional customer support agent. Be polite, empathetic, and solution-oriented. If you cannot help, escalate appropriately."
    },
    "math_tutor": {
        "name": "Math Tutor",
        "system_prompt": "You are a patient math tutor. Explain concepts step by step. Use analogies and examples. Never give the answer directly — guide the student."
    }
}

@app.post("/chat")
async def chat_with_persona(request: ChatRequest):
    """Chat with persona support"""
    
    session_id = request.session_id or str(uuid.uuid4())
    persona = request.persona or "helpful_assistant"
    
    # Get persona system prompt
    system_prompt = PERSONAS.get(persona, PERSONAS["helpful_assistant"])["system_prompt"]
    
    # Build messages with system prompt
    history = get_session_history(session_id)
    messages = [{"role": "system", "content": system_prompt}] + history
    messages.append({"role": "user", "content": request.message})
    
    # Call API
    response = requests.post(
        f"{BASE_URL}/chat/completions",
        headers={"Authorization": f"Bearer {TOKEN}"},
        json={
            "model": request.model,
            "messages": messages,
            "temperature": 0.7
        }
    )
    
    # ... process and store response

Step 3: Streaming for Real-time Responses

from fastapi.responses import StreamingResponse

@app.post("/chat/stream")
async def chat_stream(request: ChatRequest):
    """Streaming chat endpoint for real-time responses"""
    
    session_id = request.session_id or str(uuid.uuid4())
    history = get_session_history(session_id)
    
    messages = history + [{"role": "user", "content": request.message}]
    
    def generate():
        full_response = ""
        
        response = requests.post(
            f"{BASE_URL}/chat/completions",
            headers={"Authorization": f"Bearer {TOKEN}"},
            json={
                "model": request.model,
                "messages": messages,
                "stream": True,
                "temperature": 0.7
            },
            stream=True
        )
        
        for line in response.iter_lines():
            if line:
                line = line.decode("utf-8")
                if line.startswith("data: "):
                    data = line[6:]
                    if data == "[DONE]":
                        # Store complete response
                        add_to_session(session_id, {"role": "user", "content": request.message})
                        add_to_session(session_id, {"role": "assistant", "content": full_response})
                        break
                    try:
                        chunk = json.loads(data)
                        token = chunk["choices"][0]["delta"].get("content", "")
                        if token:
                            full_response += token
                            yield f"data: {json.dumps({'token': token})}\n\n"
                    except:
                        pass
    
    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}
    )

Step 4: Context Management and Summarization

def summarize_conversation(messages: List[dict], model: str = "kimi-k2") -> str:
    """Summarize long conversations to manage context window"""
    
    conversation_text = "\n".join([
        f"{m['role']}: {m['content']}" for m in messages
    ])
    
    summary_prompt = f"""Summarize the following conversation, preserving key facts, decisions, and context:

{conversation_text}

Summary:"""
    
    response = requests.post(
        f"{BASE_URL}/chat/completions",
        headers={"Authorization": f"Bearer {TOKEN}"},
        json={
            "model": model,
            "messages": [{"role": "user", "content": summary_prompt}],
            "max_tokens": 500
        }
    )
    
    return response.json()["choices"][0]["message"]["content"]

def manage_context(session_id: str, max_messages: int = 10):
    """Keep conversation within context limits by summarizing"""
    history = get_session_history(session_id)
    
    if len(history) > max_messages * 2:  # Each turn = user + assistant
        # Keep most recent messages
        recent = history[-max_messages * 2:]
        
        # Summarize older messages
        older = history[:-max_messages * 2]
        summary = summarize_conversation(older)
        
        # Replace with summary + recent
        sessions[session_id] = [
            {"role": "system", "content": f"Previous conversation summary: {summary}"}
        ] + recent
        
        return True
    
    return False

Step 5: Frontend Integration

class ChatbotUI {
    constructor(apiUrl, containerId) {
        this.apiUrl = apiUrl;
        this.container = document.getElementById(containerId);
        this.sessionId = localStorage.getItem("chat_session_id") || null;
        this.messages = [];
        this.init();
    }
    
    init() {
        this.container.innerHTML = `
            
`; this.input = this.container.querySelector("input"); this.button = this.container.querySelector("button"); this.messagesDiv = this.container.querySelector(".chat-messages"); this.button.addEventListener("click", () => this.sendMessage()); this.input.addEventListener("keypress", (e) => { if (e.key === "Enter") this.sendMessage(); }); } async sendMessage() { const text = this.input.value.trim(); if (!text) return; this.input.value = ""; this.addMessage("user", text); // Show typing indicator const typingId = this.showTyping(); try { const response = await fetch(this.apiUrl, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ message: text, session_id: this.sessionId, model: "deepseek-v4" }) }); const data = await response.json(); this.sessionId = data.session_id; localStorage.setItem("chat_session_id", this.sessionId); this.hideTyping(typingId); this.addMessage("assistant", data.response); } catch (error) { this.hideTyping(typingId); this.addMessage("assistant", "Sorry, I encountered an error. Please try again."); } } addMessage(role, text) { const msgDiv = document.createElement("div"); msgDiv.className = `message ${role}`; msgDiv.textContent = text; this.messagesDiv.appendChild(msgDiv); this.messagesDiv.scrollTop = this.messagesDiv.scrollHeight; } showTyping() { const id = "typing-" + Date.now(); const div = document.createElement("div"); div.id = id; div.className = "message assistant typing"; div.textContent = "..."; this.messagesDiv.appendChild(div); return id; } hideTyping(id) { const el = document.getElementById(id); if (el) el.remove(); } } // Initialize const chatbot = new ChatbotUI("/chat", "chat-container");

Step 6: Multi-language Support

def detect_language(text: str) -> str:
    """Simple language detection"""
    chinese_chars = sum(1 for c in text if '\u4e00' <= c <= '\u9fff')
    if chinese_chars / len(text) > 0.3:
        return "zh"
    return "en"

def get_model_for_language(lang: str) -> str:
    """Select optimal model for language"""
    if lang == "zh":
        return "glm-4"  # Excellent Chinese understanding
    return "deepseek-v4"  # Strong multilingual performance

@app.post("/chat")
async def multilingual_chat(request: ChatRequest):
    """Auto-detect language and select appropriate model"""
    
    lang = detect_language(request.message)
    model = get_model_for_language(lang)
    
    # Continue with chat using selected model
    # ...

Model Selection for Chatbots

Use CaseRecommended ModelWhy
General Q&ADeepSeek-V4Balanced quality and cost
Chinese conversationsGLM-4Superior Chinese nuance
Fast responsesKimi-K2Lowest latency
Technical supportQwen-MaxStrong reasoning
Budget-consciousDoubao-ProCheapest per token

Deployment Checklist

Cost Analysis

Running a chatbot serving 10,000 conversations/day (avg 10 turns each):

Next Steps

  1. Build your basic chatbot backend with the code above
  2. Add streaming for a better user experience
  3. Implement conversation memory and summarization
  4. Choose personas for different use cases
  5. Deploy with Redis for production session management
  6. Get your TokenEase API key to power your chatbot

For advanced features, see our guides on AI agent development and real-time streaming APIs.

Last updated: August 2026. Model recommendations may change with new releases.