telebot / ARCHITECTURE.md
Esmaill1
Add AI Quiz Bot files
92d6323

๐Ÿ—๏ธ Architecture Documentation - AI Quiz Bot

System design, API specifications, and data structures.

๐Ÿ“‘ Table of Contents

๐Ÿ—๏ธ System Architecture

High-Level Overview

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     Telegram Users                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Telegram Bot API (python-telegram-bot)              โ”‚
โ”‚  - Polling for messages                                     โ”‚
โ”‚  - Sending polls and messages                               โ”‚
โ”‚  - File download capability                                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              AI Quiz Bot (bot.py)                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚ Message Handlers                                      โ”‚   โ”‚
โ”‚  โ”‚ - handle_file() [Images/PDFs]                         โ”‚   โ”‚
โ”‚  โ”‚ - handle_text() [Text messages]                       โ”‚   โ”‚
โ”‚  โ”‚ - Commands (/start, /help)                           โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                   โ”‚                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚ Processing Layer                                      โ”‚   โ”‚
โ”‚  โ”‚ - extract_text_from_image()                          โ”‚   โ”‚
โ”‚  โ”‚ - extract_text_from_pdf()                            โ”‚   โ”‚
โ”‚  โ”‚ - parse_num_questions()                              โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                   โ”‚                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚ Generation Layer                                      โ”‚   โ”‚
โ”‚  โ”‚ - generate_quiz_questions()                          โ”‚   โ”‚
โ”‚  โ”‚ - Quiz JSON parsing                                  โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                   โ”‚                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚ Delivery Layer                                        โ”‚   โ”‚
โ”‚  โ”‚ - send_quiz_poll()                                   โ”‚   โ”‚
โ”‚  โ”‚ - Completion messages                                โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ†“                     โ†“
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚ Ollama Cloud API โ”‚   โ”‚  External APIs   โ”‚
     โ”‚ (REST HTTP/HTTPS)โ”‚   โ”‚  Telegram API    โ”‚
     โ”‚                  โ”‚   โ”‚                  โ”‚
     โ”‚ - /api/chat      โ”‚   โ”‚  (https)         โ”‚
     โ”‚   Vision Model   โ”‚   โ”‚                  โ”‚
     โ”‚   Chat Model     โ”‚   โ”‚                  โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Component Layers

1. Telegram Integration Layer

  • Receives messages via polling
  • Handles file downloads
  • Sends messages and polls
  • Manages message edits

2. Message Handler Layer

  • Routes incoming messages to appropriate handlers
  • Validates message type (file vs text vs command)
  • Extracts metadata (chat ID, user ID, caption, etc.)
  • Shows loading messages

3. Processing Layer

  • Extracts text from images (Vision API)
  • Extracts text from PDFs (PyPDF2)
  • Parses user input (question count)
  • Handles errors and retries

4. Generation Layer

  • Sends text to Chat API
  • Manages prompts and system instructions
  • Parses JSON responses
  • Validates question format

5. Delivery Layer

  • Sends each question as a Telegram poll
  • Manages rate limiting (1-second delays)
  • Sends completion messages
  • Logs delivery success/failure

๐Ÿ”Œ API Specifications

Ollama Cloud API

Base URL: https://ollama.com

Authentication: Bearer Token (in Authorization header)

Endpoint: POST /api/chat

Purpose: Vision analysis, chat completion, JSON generation

Request Headers:

Authorization: Bearer {OLLAMA_API_KEY}
Content-Type: application/json

Request Body:

{
  "model": "ministral-3:8b",
  "messages": [
    {
      "role": "user",
      "content": "Text or prompt",
      "images": ["base64_encoded_image"]  // Optional
    }
  ],
  "stream": false,
  "format": "json"  // Optional, ensures JSON output
}

Response:

{
  "model": "ministral-3:8b",
  "created_at": "2026-02-01T10:00:00Z",
  "message": {
    "role": "assistant",
    "content": "Response text or JSON"
  },
  "done": true,
  "total_duration": 1234567,
  "load_duration": 567,
  "prompt_eval_count": 50,
  "eval_count": 100,
  "eval_duration": 100000
}

Parameters:

Parameter Type Required Description
model string Yes Model name (e.g., "ministral-3:14b")
messages array Yes Array of message objects
stream boolean No Default: false (we don't use streaming)
format string No "json" to ensure JSON output

Message Object:

{
  "role": "user" | "assistant" | "system",
  "content": "Text content",
  "images": ["base64_string"]  // Optional, only for vision models
}

Telegram Bot API

Used Methods:

1. send_poll

await bot.send_poll(
    chat_id=12345,
    question="Question text?",
    options=["A", "B", "C", "D"],
    type="quiz",
    correct_option_id=1,
    is_anonymous=False
)

2. send_message

await bot.send_message(
    chat_id=12345,
    text="Message text",
    reply_to_message_id=67890
)

3. edit_message_text

await message.edit_text("Updated text")

4. get_file

file = await bot.get_file(file_id)
file_bytes = await file.download_as_bytearray()

๐Ÿ“Š Data Structures

Question Object (JSON)

{
  "question": "What is the capital of France?",
  "options": ["London", "Berlin", "Paris", "Madrid"],
  "correct_option_id": 2
}

Fields:

  • question (string): Question text (max 300 chars in Telegram)
  • options (array): Array of option strings (max 10 options in Telegram)
  • correct_option_id (number): Index of correct option (0-based)

Questions Array

[
  {
    "question": "Question 1?",
    "options": ["A", "B", "C", "D"],
    "correct_option_id": 0
  },
  {
    "question": "Question 2?",
    "options": ["A", "B", "C", "D"],
    "correct_option_id": 1
  }
]

Image Object

Format: Base64-encoded JPEG/PNG/WebP

Usage in API:

{
  "role": "user",
  "content": "Describe this image",
  "images": ["iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="]
}

๐Ÿ“ค Request/Response Examples

Example 1: Image Analysis

User Action: Send image with caption "5"

Request to Ollama:

POST https://ollama.com/api/chat
Authorization: Bearer 830f2fd6fedc491ba49c91a0709c94d9.4Z84I1pRSwd8iPDT1J4Tfu6c
Content-Type: application/json

{
  "model": "ministral-3:8b",
  "messages": [
    {
      "role": "user",
      "content": "Just transcribe all the text in the image in details. Output only the text, nothing else.",
      "images": ["base64_encoded_image_here..."]
    }
  ],
  "stream": false
}

Response from Ollama:

{
  "message": {
    "role": "assistant",
    "content": "The extracted text from the image goes here...\nThis is the text the bot analyzed."
  },
  "done": true
}

Bot Processing:

  1. Receives extracted text
  2. Parses caption: 5 questions
  3. Calls quiz generation

Example 2: Quiz Generation

Request to Ollama:

POST https://ollama.com/api/chat
Authorization: Bearer 830f2fd6fedc491ba49c91a0709c94d9.4Z84I1pRSwd8iPDT1J4Tfu6c
Content-Type: application/json

{
  "model": "ministral-3:14b",
  "messages": [
    {
      "role": "system",
      "content": "You are a strict Quiz Generator.\nRules:\n1. Output ONLY the questions and answers.\n2. Do NOT provide any conversational text..."
    },
    {
      "role": "user",
      "content": "Based on the text I provide, generate 5 multiple-choice quiz questions.\n\nYou must output valid JSON only...\n\nText to analyze:\nThe extracted text goes here..."
    }
  ],
  "stream": false,
  "format": "json"
}

Response from Ollama:

{
  "message": {
    "role": "assistant",
    "content": "[{\"question\":\"Q1?\",\"options\":[\"A\",\"B\",\"C\",\"D\"],\"correct_option_id\":0},{\"question\":\"Q2?\",\"options\":[\"A\",\"B\",\"C\",\"D\"],\"correct_option_id\":1}]"
  },
  "done": true
}

Bot Processing:

  1. Receives JSON string
  2. Cleans markdown if present
  3. Parses JSON
  4. Validates each question
  5. Sends as Telegram polls

Example 3: Send Quiz Poll to Telegram

Request to Telegram:

POST https://api.telegram.org/bot7319290683:AAFpfIEGCZGOky3OOB2V-xcn8rq8pc7TEUQ/sendPoll
Content-Type: application/json

{
  "chat_id": 123456789,
  "question": "What is the capital of France?",
  "options": ["London", "Berlin", "Paris", "Madrid"],
  "type": "quiz",
  "correct_option_id": 2,
  "is_anonymous": false
}

Response from Telegram:

{
  "ok": true,
  "result": {
    "message_id": 12345,
    "chat": {"id": 123456789},
    "poll": {
      "id": "poll123",
      "question": "What is the capital of France?",
      "options": [
        {"text": "London", "voter_count": 0},
        {"text": "Berlin", "voter_count": 0},
        {"text": "Paris", "voter_count": 0},
        {"text": "Madrid", "voter_count": 0}
      ],
      "type": "quiz",
      "total_voter_count": 0,
      "is_closed": false,
      "is_anonymous": false,
      "allows_multiple_answers": false,
      "correct_option_id": 2
    }
  }
}

๐Ÿ›ก๏ธ Error Handling

API Error Types

Error HTTP Code Cause Bot Response
Invalid API Key 401 Wrong/expired OLLAMA_API_KEY "ุญุตู„ ู…ุดูƒู„ุฉ" + retry
Model Not Found 404 Invalid VISION_MODEL or CHAT_MODEL "Model not found" error
Rate Limited 429 Too many requests Retry with backoff
Timeout 504 API slow "API timeout" message
DNS Error N/A Wrong OLLAMA_HOST Network error

Error Flow

Error Occurs
    โ†“
Logger.error() called with details
    โ†“
Exception raised/caught
    โ†“
IF API Error: Notify user with friendly message
ELSE IF Validation Error: Show specific error
ELSE: Generic "ุญุตู„ ู…ุดูƒู„ุฉ" message
    โ†“
Message edit/delete if needed
    โ†“
Continue waiting for next user input

User-Facing Error Messages

# Network errors
"โŒ ู†ูˆุน ู…ู„ู ู…ุด ู…ุฏุนูˆู…!"

# Processing errors
"โŒ ู…ุด ู‚ุงุฏุฑ ุงุณุชุฎุฑุฌ ู†ุต ูƒุงููŠ"

# Generation errors
"โŒ ู…ุด ู‚ุงุฏุฑ ุงุนู…ู„ ุงุณุฆู„ุฉ ู…ู† ุงู„ู†ุต ุฏู‡"

# Validation errors
"โŒ ุงู„ู†ุต ู‚ุตูŠุฑ ุดูˆูŠุฉ!"

# Generic errors
"โŒ ุญุตู„ ู…ุดูƒู„ุฉ: {error_details}"

๐Ÿ“ˆ Scalability Considerations

Current Limitations

  1. Sequential Processing

    • Each question sent with 1-second delay
    • Multiple users processed sequentially
    • No concurrent request batching
  2. Memory Usage

    • Entire image/PDF loaded into memory
    • Full text stored in variables
    • No streaming or chunking
  3. Rate Limiting

    • No rate limiting per user
    • Telegram has built-in limits
    • Ollama API has unknown limits

Scaling Improvements

1. Add Request Queuing

import asyncio
from asyncio import Queue

class BotQueue:
    def __init__(self, max_concurrent=3):
        self.queue = Queue()
        self.processing = set()
    
    async def process(self, user_id, request):
        await self.queue.put((user_id, request))
        await self._process_queue()

2. Add Redis Caching

import redis

cache = redis.Redis(host='localhost', port=6379)

async def generate_quiz_questions_cached(text, num_questions):
    cache_key = f"quiz:{hash(text)}:{num_questions}"
    cached = cache.get(cache_key)
    if cached:
        return json.loads(cached)
    
    # Generate new questions
    questions = await generate_quiz_questions(text, num_questions)
    cache.setex(cache_key, 3600, json.dumps(questions))  # 1 hour TTL
    return questions

3. Add Database Logging

import sqlite3

def log_request(user_id, request_type, status):
    conn = sqlite3.connect('bot.db')
    c = conn.cursor()
    c.execute('''INSERT INTO requests (user_id, type, status, timestamp)
                 VALUES (?, ?, ?, ?)''',
              (user_id, request_type, status, datetime.now()))
    conn.commit()

4. Concurrent File Processing

# For multiple images/PDFs
async def process_multiple_files(files):
    tasks = [extract_text_from_image(f) for f in files]
    results = await asyncio.gather(*tasks)
    return results

Performance Metrics

Current Performance:

  • Image analysis: 5-15 seconds
  • PDF extraction: 1-5 seconds
  • Quiz generation: 10-30 seconds
  • Total time: 20-50 seconds

Bottlenecks:

  1. Ollama API response time (50-80%)
  2. Image base64 encoding (5-10%)
  3. Network latency (10-20%)

๐Ÿ”„ Deployment Architecture

Development

Local PC
โ”œโ”€โ”€ Python 3.9+
โ”œโ”€โ”€ bot.py
โ”œโ”€โ”€ .env (with test credentials)
โ””โ”€โ”€ Internet connection to Ollama Cloud

Production

Server/Cloud
โ”œโ”€โ”€ Python 3.9+
โ”œโ”€โ”€ bot.py
โ”œโ”€โ”€ .env (with production credentials)
โ”œโ”€โ”€ Systemd/Docker service
โ”œโ”€โ”€ Error logging
โ””โ”€โ”€ Database backup

Docker Deployment

FROM python:3.9-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY bot.py .
COPY .env .

CMD ["python", "bot.py"]
docker build -t aiquiz-bot .
docker run -d --name aiquiz-bot aiquiz-bot

Last Updated: February 2026
Architecture Version: 1.0
API Version: Ollama Cloud API v1