Download Readme.md from Hfzune/Test: direct link, hf CLI and curl.
- Browser
- Download file 11.2 kB
-
https://huggingface.co/spaces/Hfzune/Test/resolve/main/Readme.md
- Command line
-
hf download hf://spaces/Hfzune/Test/Readme.md
-
curl -L -o Readme.md https://huggingface.co/spaces/Hfzune/Test/resolve/main/Readme.md
A newer version of the Gradio SDK is available: 6.31.0
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)
- 🧹
/resetto clear the current chat's memory - 📊
/statsto 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 —
/webhookand/healthtake priority over Gradio's catch-all - Model loaded at module scope — ZeroGPU "packs" weights to disk; each
@spaces.GPUcall attaches the GPU - All persistence in the main process — SQLite in WAL mode; conversation state survives GPU worker forks
🚀 Deployment
1. Create the Space
- Go to https://huggingface.co/new-space
- SDK: Gradio
- Hardware: ZeroGPU (free tier is fine)
- Visibility: Private or Public — your choice
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 yourADMIN_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)
- Reduce
🛠️ 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_TOKENpublicly. If leaked, revoke it via BotFather (/revoke→ pick bot). - Change
ADMIN_PASSWORDfrom the defaulttom123before 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
- Model: thirdeyeai/Qwen2.5-1.5B-Instruct-uncensored
- ZeroGPU: Hugging Face Spaces
- Gradio: gradio.app