Files
litert-lm-orangepi/README.md
T
2026-04-19 10:15:37 +00:00

359 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🤖 LiteRT-LM Web Server
Chạy mô hình **Gemma 4** trên thiết bị nhúng (Orange Pi 5, Raspberry Pi, v.v.) thông qua [LiteRT-LM](https://github.com/google-ai-edge/litert-lm) với giao diện REST API và Web UI.
---
## 📋 Yêu cầu
- Python 3.10+
- [`litert-lm`](https://github.com/google-ai-edge/litert-lm) đã cài và hoạt động
- Thư viện Python:
```bash
pip install -r requirements.txt
```
`requirements.txt`:
```
fastapi
uvicorn
pydantic
huggingface_hub
```
---
## 📁 Cấu trúc
```
.
├── app.py # REST API đơn giản, single-turn
├── server.py # REST API đầy đủ + Web UI, multi-turn sessions
├── templates/
│ └── index.html # Giao diện Web UI (tách riêng khỏi server.py)
├── models/ # Thư mục chứa các file model .litertlm
│ ├── gemma-4-E2B-it.litertlm
│ └── gemma-4-E4B-it.litertlm
├── requirements.txt
└── README.md
```
---
## 🤖 Models hỗ trợ
| Model | Repo HuggingFace | Mô tả |
|-------|-----------------|-------|
| `gemma-4-E2B-it` | [google/gemma-4-E2B-it](https://huggingface.co/google/gemma-4-E2B-it) | Edge 2B — nhanh hơn, nhẹ hơn |
| `gemma-4-E4B-it` | [google/gemma-4-E4B-it](https://huggingface.co/google/gemma-4-E4B-it) | Edge 4B — thông minh hơn, nặng hơn |
> **Lưu ý:** Nên dùng bản `-it` (instruction-tuned) cho chat/hỏi đáp. Bản không có `-it` là base model, chỉ predict token tiếp theo, không phù hợp để hội thoại.
### Tải model về
```bash
# Gemma 4 E2B (nhỏ hơn, ~nhanh hơn)
huggingface-cli download google/gemma-4-E2B-it \
--include '*.litertlm' \
--local-dir models/
# Gemma 4 E4B (lớn hơn, ~thông minh hơn)
huggingface-cli download google/gemma-4-E4B-it \
--include '*.litertlm' \
--local-dir models/
```
---
## 🚀 Hướng dẫn sử dụng
### Bước 1 — Tải ít nhất một model vào thư mục `models/`
Xem lệnh tải ở trên.
### Bước 2 — Chạy server
```bash
python server.py
```
Server sẽ hiển thị menu **chọn model** trước khi khởi động:
```
====================================================
LiteRT-LM Server — Chọn model
====================================================
[1] gemma-4-E2B-it
Gemma 4 Edge 2B — nhỏ hơn, nhanh hơn
✓ có sẵn
[2] gemma-4-E4B-it
Gemma 4 Edge 4B — thông minh hơn, chậm hơn
✗ chưa tải
Chọn model (1/2):
```
Nếu model chưa được tải, server sẽ hiển thị lệnh `huggingface-cli download` tương ứng và hỏi có muốn chọn model khác không.
### Bước 3 — Mở Web UI
```
http://<địa-chỉ-ip>:8000
```
Tên model đang chạy sẽ hiển thị trên header của Web UI.
---
## 📄 `app.py` — REST API đơn giản
File cơ bản, single-turn, không có menu chọn model. Phù hợp để tích hợp nhanh hoặc test.
### Chạy
```bash
python app.py
```
### Endpoint
#### `POST /generate`
Gửi một prompt, nhận phản hồi. Mỗi request là độc lập, **không có bộ nhớ** giữa các lần gọi.
```bash
curl -X POST http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "Bạn là ai?"}'
```
**Response:**
```json
{
"response": "Tôi là Gemma 4, một Mô hình Ngôn ngữ Lớn...",
"tokens": 42,
"elapsed_s": 5.31,
"tokens_per_sec": 7.91
}
```
---
## 🖥️ `server.py` — REST API đầy đủ + Web UI
Phiên bản đầy đủ với chọn model khi khởi động, multi-turn conversation, quản lý session và giao diện chat trên trình duyệt.
---
### 🌐 Web UI
Mở trình duyệt và truy cập `http://<địa-chỉ-ip>:8000`
Tính năng:
- **Chọn model khi khởi động** qua menu CLI — tên model hiển thị trực tiếp trên header
- Giao diện chat trực quan, hỗ trợ tiếng Việt
- Tự động tạo session khi mở trang
- Nhớ ngữ cảnh hội thoại trong cùng một session
- Nút **New** để bắt đầu cuộc trò chuyện mới
- Nút **Clear** để xóa lịch sử và tạo session mới
- `Enter` để gửi, `Shift + Enter` để xuống dòng
- **Render Markdown**: câu trả lời hiển thị đúng định dạng (heading, list, code block, table, bold/italic, v.v.)
- **Đo tốc độ**: badge `⚡ X tok/s` bên dưới mỗi câu trả lời, kèm số token và thời gian xử lý
---
### 🔌 REST API
#### `GET /info`
Trả về thông tin model đang chạy và số session hiện tại.
```bash
curl http://localhost:8000/info
```
**Response:**
```json
{
"model": "gemma-4-E2B-it",
"sessions": 2
}
```
---
#### `POST /generate`
Single-turn, không nhớ context. Dùng khi chỉ cần hỏi đáp đơn lẻ.
```bash
curl -X POST http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "Thủ đô của Việt Nam là gì?"}'
```
**Response:**
```json
{
"response": "Thủ đô của Việt Nam là Hà Nội.",
"tokens": 12,
"elapsed_s": 1.45,
"tokens_per_sec": 8.27
}
```
---
#### `POST /chat/new`
Tạo một session mới. Trả về `session_id` dùng cho các request tiếp theo.
```bash
curl -X POST http://localhost:8000/chat/new
```
**Response:**
```json
{
"session_id": "a3f2c1d4-..."
}
```
---
#### `POST /chat/{session_id}`
Gửi tin nhắn trong một session. Model **nhớ toàn bộ lịch sử hội thoại** trong session đó.
```bash
curl -X POST http://localhost:8000/chat/a3f2c1d4-... \
-H "Content-Type: application/json" \
-d '{"prompt": "Kể thêm về điều đó đi"}'
```
**Response:**
```json
{
"session_id": "a3f2c1d4-...",
"response": "...",
"tokens": 58,
"elapsed_s": 7.12,
"tokens_per_sec": 8.15
}
```
---
#### `DELETE /chat/{session_id}`
Xóa session và giải phóng bộ nhớ.
```bash
curl -X DELETE http://localhost:8000/chat/a3f2c1d4-...
```
**Response:**
```json
{
"status": "cleared",
"session_id": "a3f2c1d4-..."
}
```
---
#### `GET /chat/sessions/list`
Liệt kê tất cả session đang hoạt động.
```bash
curl http://localhost:8000/chat/sessions/list
```
**Response:**
```json
{
"sessions": ["a3f2c1d4-...", "b7e9f2a1-..."],
"count": 2
}
```
---
## 💡 Ví dụ: Multi-turn conversation qua curl
```bash
# 1. Tạo session
SESSION=$(curl -s -X POST http://localhost:8000/chat/new | python3 -c "import sys,json; print(json.load(sys.stdin)['session_id'])")
# 2. Gửi tin nhắn đầu tiên
curl -s -X POST http://localhost:8000/chat/$SESSION \
-H "Content-Type: application/json" \
-d '{"prompt": "Tên tôi là Nam"}' | python3 -m json.tool
# 3. Model nhớ context
curl -s -X POST http://localhost:8000/chat/$SESSION \
-H "Content-Type: application/json" \
-d '{"prompt": "Tên tôi là gì?"}' | python3 -m json.tool
# 4. Xóa session khi xong
curl -X DELETE http://localhost:8000/chat/$SESSION
```
---
## ⚙️ Cấu hình
Các tham số chỉnh trong đầu `server.py`:
| Biến | Mô tả | Mặc định |
|------|-------|---------|
| `MODELS_DIR` | Thư mục chứa model | `./models` |
| `AVAILABLE_MODELS` | Danh sách model + repo HuggingFace | xem trong file |
| `backend` | Backend inference | `litert_lm.Backend.CPU` |
| `host` | Địa chỉ lắng nghe | `0.0.0.0` |
| `port` | Cổng | `8000` |
Để thêm model mới vào menu, bổ sung vào dict `AVAILABLE_MODELS` trong `server.py`:
```python
AVAILABLE_MODELS = {
"gemma-4-E2B-it": {
"file": "gemma-4-E2B-it.litertlm",
"repo": "google/gemma-4-E2B-it",
"desc": "Gemma 4 Edge 2B — nhỏ hơn, nhanh hơn",
},
"ten-model-moi": {
"file": "ten-model-moi.litertlm",
"repo": "org/repo-name",
"desc": "Mô tả model",
},
}
```
Để đổi backend sang GPU (nếu thiết bị hỗ trợ):
```python
engine = litert_lm.Engine(str(MODEL_PATH), backend=litert_lm.Backend.GPU)
```
---
## 📝 Ghi chú
- Mỗi session giữ toàn bộ lịch sử hội thoại trong RAM. Nên xóa session khi không dùng nữa.
- Warning `mel_filterbank` khi khởi động là bình thường — liên quan đến audio encoder của Gemma 4 multimodal, không ảnh hưởng đến text generation.
- Tốc độ generate phụ thuộc vào phần cứng. Trên Orange Pi 5 với CPU, khoảng 515 token/giây.
- Token/s dùng `engine.tokenize()` nếu có, fallback về ước tính `len(text) // 4` nếu không khả dụng.
- Markdown được render bằng [marked.js](https://marked.js.org/) trực tiếp trên trình duyệt, không qua server.
- Chỉ dùng bản `-it` (instruction-tuned) cho chat — bản base model không phù hợp hội thoại.
---
## 📜 License
MIT