fix: make relay fast and concurrency-safe

This commit is contained in:
2026-07-20 06:17:31 +02:00
parent 4eaa21f20c
commit 67160b2de0
5 changed files with 221 additions and 252 deletions
+69 -49
View File
@@ -1,75 +1,95 @@
# Hermes Relay
# Hermes Relay v3.2
Flask bridge tussen Node-RED en Hermes Agent.
## Architectuur
Snelle Quart-bridge tussen Node-RED en een warme Hermes Agent.
```text
Node-RED ──POST /ask──▶ Quart relay ──serialized call──▶ warme Hermes-agent
│
├── JSON direct terug naar Node-RED
└── Telegram-bezorging op de achtergrond via `hermes send`
```
Node-RED (192.168.1.125) ──POST /ask──▶ Hermes Relay (192.168.1.74:8650)
│
├──▶ hermes chat -q (subprocess)
│ │
│ ▼
│ JSON response ──▶ Node-RED
│
└──▶ hermes send --to telegram
│
▼
Telegram chat
```
## Gedrag en grenzen
- **Warme agent:** Hermes wordt tijdens startup geladen/geïnitialiseerd.
- **Veilige concurrency:** de gedeelde, mutable agent verwerkt precies één LLM-call tegelijk. Overige HTTP-verzoeken wachten in de queue; ze kunnen niet elkaars `messages` resetten.
- **Timeout:** `HERMES_RELAY_TIMEOUT` (standaard 120 s) omvat wachttijd plus LLM-call. Een timeout retourneert HTTP `504`.
- **Snelle response:** Telegram ligt niet meer in het HTTP-pad. Een succesvolle `/ask` reageert zodra het model antwoordt.
- **Background delivery:** Telegram wordt betrouwbaar gelogd. Bij gecontroleerde shutdown wacht de service op lopende bezorgingen.
## Endpoints
### `POST /ask`
Verwacht JSON body:
JSON body:
```json
{ "payload": "Wat is het weer in Best?" }
```
Response:
Succesresponse:
```json
{
"status": "ok",
"answer": "Het is 22°C en zonnig in Best...",
"elapsed_seconds": 8.3,
"telegram_sent": true
"answer": "...",
"elapsed_seconds": 6.213,
"llm_elapsed_seconds": 6.213,
"request_elapsed_seconds": 6.214,
"telegram_queued": true
}
```
### `GET /health`
Health check voor monitoring.
`elapsed_seconds` blijft aanwezig voor compatibiliteit en is de LLM-duur. `request_elapsed_seconds` is de feitelijke HTTP-duur. `telegram_queued` betekent dat bezorging geaccepteerd is voor de achtergrondtaak; raadpleeg journald voor het uiteindelijke bezorgresultaat.
## Setup
Fouten: `400` lege payload, `413` payload groter dan limiet, `504` timeout, `502` onverwachte agentfout.
### `GET /health`
Geeft service-status, versie en het aantal lopende Telegram-bezorgingen terug.
- `/health?detail=true` voegt de **lokale agent-state** toe; dit doet bewust geen dure LLM/provider-call.
## Configuratie
| Variabele | Standaard | Betekenis |
|---|---:|---|
| `HERMES_RELAY_TIMEOUT` | `120` | Max. wachttijd + modelcall per HTTP-request |
| `HERMES_RELAY_DELIVERY_WORKERS` | `2` | Begrensde workers voor Telegram-bezorging |
| `HERMES_RELAY_MAX_PAYLOAD_CHARS` | `12000` | Maximale lengte van `payload` |
| `HERMES_RELAY_MAX_TURNS` | `10` | Agent turn-budget |
| `HERMES_RELAY_MODEL` | profieldefault | Optionele modelovertuiging |
| `HERMES_RELAY_TOOLSETS` | leeg | Alleen invullen met geldige benodigde toolsets |
De relay leest zijn Hermes-config via profiel `voice-assistant`. Pas model/provider/config aan en herstart daarna de service:
```bash
cd /root/hermes-relay
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Test
python app.py
# Of als service
sudo systemctl enable hermes-relay
sudo systemctl start hermes-relay
systemctl restart hermes-relay
```
## Node-RED Nodes
## Testen
### Versturen (HTTP Request node)
- **Method:** POST
```bash
curl -s http://127.0.0.1:8650/health
curl -s -X POST http://127.0.0.1:8650/ask \
-H 'Content-Type: application/json' \
-d '{"payload":"Zeg alleen hoi"}'
journalctl -u hermes-relay -f
```
## Node-RED
Gebruik een HTTP Request-node:
- **Method:** `POST`
- **URL:** `http://192.168.1.74:8650/ask`
- **Return:** a parsed JSON object
- **Timeout:** 120000 (ms) — Hermes kan even duren
- **Return:** parsed JSON
- **Timeout:** `120000` ms
### Ontvangen
Het antwoord komt terug als `msg.payload`:
- `msg.payload.answer` — het Hermes antwoord
- `msg.payload.elapsed_seconds` — hoe lang het duurde
- `msg.payload.telegram_sent` — of het ook naar Telegram is gestuurd
- `msg.payload.status` — "ok" of "error"
Voorafgaande Function-node:
### Health check (optioneel)
- **Method:** GET
- **URL:** `http://192.168.1.74:8650/health`
```javascript
msg.payload = { payload: msg.payload };
return msg;
```