Test / Readme.md
Hfzune's picture
Update Readme.md
d645ec8 verified
|
Raw History Blame Contribute Delete
11.2 kB

A newer version of the Gradio SDK is available: 6.31.0

Upgrade
metadata
title: DeepSeek-OCR Full-Page CSV
emoji: 📄
colorFrom: blue
colorTo: green
sdk: gradio
sdk_version: 5.49.1
python_version: '3.10'
app_file: app.py
pinned: false

🤖 Qwen Telegram Bot

A Telegram bot backed by Qwen2.5-1.5B-Instruct running on Hugging Face ZeroGPU (free tier), with streaming responses, per-user token access, and a full admin panel for monitoring conversations, managing tokens, and exporting logs.

Built to survive the ZeroGPU free tier: no Docker, no external servers, no paid APIs.


✨ Features

For users (Telegram)

  • 🔒 Token-gated access — only users with an admin-issued token can chat
  • ⚡ Streaming replies — see the response as it's generated
  • 💻 Proper code formatting — Markdown → Telegram HTML, with language-tagged code boxes
  • 📜 Conversation memory — rolling window of past turns (configurable)
  • 🧹 /reset to clear the current chat's memory
  • 📊 /stats to see your own usage

For admin (web panel)

  • 🔐 Password-gated admin tab inside the Gradio UI
  • 📊 Dashboard — users, turns, GPU quota consumed today
  • 👥 User management — view, revoke, delete users
  • 💬 Conversation logs — filter by user, search, view full history
  • 📤 Export logs — JSON / CSV / Markdown, full conversation dump
  • 🎟️ Token management — generate individually, bulk-generate, revoke, reassign
  • ⚙️ Runtime settings — system prompt, temperature, top_p, max tokens, conversation window, daily limit
  • 🩺 Health — recent GPU calls, latency, quota status

🏗️ Architecture

Telegram  ──webhook──▶  HF Space (Gradio SDK, ZeroGPU)
                          │
                          ├── Gradio UI (Status + Admin tabs)
                          ├── /webhook        → bot logic
                          ├── /health         → keep-alive target
                          ├── /admin/*        → admin API
                          │
                          ├── SQLite (/data/bot.db)   users, tokens, convs, gpu_log
                          └── @spaces.GPU generate_stream()
                                  │
                                  ▼
                          Qwen2.5-1.5B on Blackwell GPU (48 GB slice)
  • Single Gradio app — admin panel is a tab, not a separate mount (this avoids the 33 s Node SSR startup hang)
  • Route injection at index 0 — /webhook and /health take priority over Gradio's catch-all
  • Model loaded at module scope — ZeroGPU "packs" weights to disk; each @spaces.GPU call attaches the GPU
  • All persistence in the main process — SQLite in WAL mode; conversation state survives GPU worker forks

🚀 Deployment

1. Create the Space

2. Get a Telegram bot token

  • Message @BotFather → /newbot
  • Save the token (looks like 123456789:ABC...)

3. Configure Space secrets

Settings → Variables and secrets → add:

Name Required Value
TELEGRAM_BOT_TOKEN ✅ Bot token from BotFather
PUBLIC_URL ✅ https://<user>-<space>.hf.space (your Space URL, no trailing slash)
TELEGRAM_WEBHOOK_SECRET ⭐ recommended Random string — Telegram will send it in X-Telegram-Bot-Api-Secret-Token
ADMIN_PASSWORD ⭐ recommended Password for the web admin panel. Default: tom123 — change it!
ADMIN_TELEGRAM_IDS optional Comma-separated Telegram IDs allowed to use /admin bot command
MODEL_ID optional Override model. Default: thirdeyeai/Qwen2.5-1.5B-Instruct-uncensored
TELEGRAM_PROXY optional Cloudflare Worker URL if api.telegram.org is blocked in your Space's region

4. Upload the files

Push the repo (git, web upload, or HF CLI). Structure:

.
├── app.py
├── requirements.txt
├── README.md
├── admin/
│   ├── __init__.py
│   ├── auth.py
│   ├── exports.py
│   └── panel.py
├── bot/
│   ├── __init__.py
│   ├── onboarding.py
│   ├── streaming.py
│   ├── telegram_api.py
│   └── webhook.py
├── db/
│   ├── __init__.py
│   ├── init.py
│   ├── models.py
│   └── schema.sql
├── model/
│   ├── __init__.py
│   └── qwen.py
└── utils/
    ├── __init__.py
    ├── audit.py
    ├── health.py
    └── quota.py

5. Wait for the build

First boot downloads ~3 GB of model weights. Watch the Logs tab for:

Loading weights: 100%|██████████|
db: DB initialised at /data/bot.db
app: Launching Gradio...
app: Boot complete. Blocking.

6. Register the webhook

The app auto-registers on boot if PUBLIC_URL is set. Verify with:

https://api.telegram.org/bot<TOKEN>/getWebhookInfo

You should see your Space URL and no last_error_message.

7. Keep it awake

ZeroGPU Spaces sleep after idle. Set up an external pinger:

Option A — cron-job.org (free, 5 min)

  • URL: https://<user>-<space>.hf.space/health
  • Interval: every 5 minutes

Option B — GitHub Actions

name: keepalive
on:
  schedule: [{cron: "*/5 * * * *"}]
jobs:
  ping:
    runs-on: ubuntu-latest
    steps:
      - run: curl -fsS https://<user>-<space>.hf.space/health || true

⚠️ Internal heartbeats don't count. The container must receive external traffic.

8. First admin login

  • Visit https://<user>-<space>.hf.space/
  • Click 🔐 Admin Panel tab
  • Enter tom123 (or your ADMIN_PASSWORD)

9. Issue your first token

  • Admin → 🎟️ Tokens tab → Generate batch (1)
  • Copy the token
  • In Telegram, DM your bot: /token <that-token>
  • You'll see Token accepted. — you can now chat

💬 Telegram Commands

Command Description
/start Welcome / onboarding
/token VALUE Submit or replace your access token
/reset Clear this chat's conversation memory
/stats Show your usage stats
/help List commands
/admin (Admin IDs only) — reminder of the web admin URL

🌐 HTTP Endpoints

Method Path Purpose
GET /health Keep-alive target — returns JSON with uptime
POST /webhook Telegram updates (validated by secret header)
GET /admin Redirects to / (admin is a tab)
GET /admin/quota JSON quota snapshot
POST /admin/boot_webhook Re-register the Telegram webhook

🗄️ Database Schema

All tables live in /data/bot.db (persistent across Space restarts).

Table Purpose
users Telegram user records, is_active flag, token binding
tokens Issued tokens with assigned_to, turns_used, last_used
conversations Every user/assistant message with timestamps and latency
admin_audit Admin actions (boot, generate, revoke)
gpu_log Every GPU call with duration — used for quota tracking
settings Runtime-configurable key/value pairs

⚙️ Runtime Settings (Admin → Settings tab)

Setting Default Notes
system_prompt "You are a helpful assistant." Change this to steer the model's behavior
conversation_window 6 turns How many past turns are sent as context
max_new_tokens 1024 Hard cap on reply length
temperature 0.7 0 = deterministic, 1.0 = creative
top_p 0.9 Nucleus sampling cutoff
daily_turn_limit 100 Max turns per user per day

Changes apply immediately to the next message — no restart needed.


📤 Export Formats

Admin → Conversations → Export:

  • JSON — full nested structure, one object per user with all their turns
  • CSV — flat, one row per message (best for spreadsheets)
  • Markdown — human-readable transcript per user

Each message row includes timestamp, role, content, latency_ms, gpu_time_ms.


🧠 Free-Tier Reality Check

ZeroGPU free tier gives roughly 300 seconds of GPU time per day. A typical chat turn on a 1.5B model at BF16 costs 2–5 seconds. That works out to roughly 60–100 turns per day across all users.

Practical implications:

  • Admin → Dashboard shows GPU seconds used today / 300
  • The bot refuses new generations when usage exceeds ~280 s (safety margin)
  • Keep conversations short — larger conversation_window = more tokens = more GPU time
  • If you need more headroom, either:
    • Reduce max_new_tokens
    • Reduce conversation_window
    • Upgrade to HF PRO (~25× more GPU quota)

🛠️ Troubleshooting

Bot replies to /start but ignores messages

Check user_has_valid_token — the user must have redeemed a token via /token.

Bad Request: unsupported parse_mode

Only happens if you modified telegram_api.py. The fix: never send parse_mode: null — omit the key entirely for plain text.

Messages are cut off mid-sentence

Increase max_new_tokens in Admin → Settings. Or ask for shorter responses.

Code blocks show as raw text

Means the model produced HTML that our converter didn't recognize. Check Admin → Conversations to see the raw output and open an issue with the exact text.

Space sleeps and cold-starts take 30 s

External pinger isn't running. Check cron-job.org logs. Remember: only external traffic resets the idle timer.

Bad Request: message is too long

Shouldn't happen — we auto-split at 3900 chars. If you see it, a single HTML entity is likely breaking the length math; open an issue.


⚠️ Security Notes

  • Never paste your TELEGRAM_BOT_TOKEN publicly. If leaked, revoke it via BotFather (/revoke → pick bot).
  • Change ADMIN_PASSWORD from the default tom123 before going public.
  • Set TELEGRAM_WEBHOOK_SECRET — otherwise anyone who guesses your Space URL can POST fake updates.
  • The bot accepts only text messages. Photos, voice, and files are rejected — this is by design.
  • Conversation content is stored in plain SQLite. Don't paste secrets into the chat.

📋 Project Structure Notes

  • app.py — entry point. HfFolder shim → Gradio build → launch → route injection → block.
  • model/qwen.py — the only file with @spaces.GPU. Everything else runs on CPU.
  • bot/telegram_api.py — all Telegram HTTP calls, markdown→HTML conversion, and message chunking.
  • db/models.py — all SQL. No ORM, just explicit queries.
  • admin/panel.py — Gradio Blocks built inside the main app context (no second mount).

📜 License

Personal project. Do whatever you want with it.


🙏 Credits