Files
zalo-hermes-bot/README.md
T
2026-09-14 22:18:15 +07:00

136 lines
4.4 KiB
Markdown

# Zalo Hermes Bot
Kênh **Zalo Bot ↔ Hermes Agent** (không phải bot KB/wiki `:8766`).
Người dùng chat Zalo → bot long-poll (`python-zalo-bot`) → **Hermes API Server** (`:8642`, agent đầy đủ tool/skill/memory) → format plain-text → trả lại Zalo.
Đây là hiện thực phương án **B** trong thực tế vận hành: event từ Zalo do bridge giữ `chat_id` và lấy câu trả lời agent rồi `send_message`. Webhook Hermes `:8644` không deliver native sang Zalo, nên bridge dùng **API Server** (cùng gateway Hermes) thay vì phụ thuộc deliver platform.
```
Zalo user
→ python-zalo-bot (get_update)
→ POST http://127.0.0.1:8642/v1/chat/completions (model: hermes-agent)
→ format_for_zalo()
→ send_message
```
Khác `zalo-bot-chat` (KB support giá/wiki). Có thể chạy song song với token bot khác.
## Yêu cầu
1. Python ≥ 3.8 (khuyến nghị 3.11)
2. Token Zalo Bot (`BOT_TOKEN`)
3. Hermes gateway đang chạy + **API Server bật** trên `:8642`
### Bật Hermes API Server (một lần)
Docs: [API Server](https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server)
```bash
# Cách nhanh
bash scripts/enable-hermes-api-server.sh 'your-local-api-key'
systemctl --user restart hermes-gateway
# Hoặc tự thêm vào ~/.hermes/.env:
# API_SERVER_ENABLED=true
# API_SERVER_KEY=your-local-api-key
```
Smoke:
```bash
curl -sS http://127.0.0.1:8642/v1/models \
-H "Authorization: Bearer your-local-api-key"
```
## Cài đặt
```bash
cd ~/workspace/zalo-hermes-bot
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# sửa BOT_TOKEN + HERMES_API_KEY (= API_SERVER_KEY)
chmod 600 .env
```
## Chạy tay
```bash
source .venv/bin/activate
python bot_app.py
```
Log mẫu:
```text
[hermes] backend=api base=http://127.0.0.1:8642/v1 health={'ok': True, …}
[zalo] started as …; listening…
```
`Ctrl+C` → `[zalo] stopped (Ctrl+C)`.
## Systemd (user) — tự chạy khi boot
```bash
mkdir -p ~/.config/systemd/user
cp ~/workspace/zalo-hermes-bot/zalo-hermes-bot.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now zalo-hermes-bot.service
sudo loginctl enable-linger "$USER" # nếu chưa
```
```bash
systemctl --user status zalo-hermes-bot.service
journalctl --user -u zalo-hermes-bot.service -f
systemctl --user restart zalo-hermes-bot.service
```
## Luồng tin nhắn
| Bước | Điều kiện | Hành động |
|------|-----------|-----------|
| 1 | `/reset` / `xóa lịch sử` | Xóa history Hermes theo `chat_id` |
| 2 | Còn lại | Gọi Hermes (nền, không chặn poll) → plain text → Zalo |
Mỗi `chat_id` giữ history ngắn (`HERMES_HISTORY_TURNS`). User đang chờ câu trước sẽ nhận thông báo bận thay vì chồng request.
## Biến môi trường
| Biến | Bắt buộc | Mặc định | Mô tả |
|------|----------|----------|--------|
| `BOT_TOKEN` | Có | — | Token Zalo Bot |
| `HERMES_API_BASE` | Không | `http://127.0.0.1:8642/v1` | OpenAI-compatible base |
| `HERMES_API_KEY` | Có* | — | = `API_SERVER_KEY` |
| `HERMES_MODEL` | Không | `hermes-agent` | Model name API Server |
| `HERMES_TIMEOUT` | Không | `180` | Timeout giây |
| `HERMES_HISTORY_TURNS` | Không | `12` | Số lượt user/assistant giữ |
| `HERMES_BACKEND` | Không | `api` | `api` hoặc `cli` (`hermes chat -q`) |
| `HERMES_WORKERS` | Không | `2` | Số job Hermes song song |
| `HERMES_SYSTEM_PROMPT` | Không | (xem `.env.example`) | System prompt |
\*Bắt buộc khi `HERMES_BACKEND=api`.
## Cấu trúc
```text
zalo-hermes-bot/
├── bot_app.py # long-poll + task nền
├── hermes_client.py # API Server / CLI client + history
├── format_zalo.py # plain-text Zalo
├── scripts/enable-hermes-api-server.sh
├── zalo-hermes-bot.service
├── requirements.txt
├── .env.example
└── README.md
```
## Lưu ý
- **Không** trỏ nhầm sang KB `:8766` — đó là `zalo-bot-chat`.
- Dùng **token Zalo Bot riêng** nếu chạy song song với bot KB.
- Câu trả lời agent có tool có thể lâu → bot đã `typing` + chạy nền; tăng `HERMES_TIMEOUT` nếu cần.
- Không commit `.env`.
- Webhook platform Hermes (`hermes webhook …`) vẫn dùng được cho GitHub/CI → Telegram/Discord; bridge này là đường **Zalo ↔ agent** riêng.