Pasii 2-4 din README (creare remote, verificare acces, scriere DRIVE_REMOTE, prima sincronizare) erau de facut de mana, cu ID-ul dosarului copiat corect de fiecare data. Scriptul ii face pe toti dintr-un token `rclone authorize`: valideaza ca tokenul e JSON, refuza devreme daca rclone sau env-ul lipsesc, face backup la env inainte de a-l rescrie, si e idempotent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
8.0 KiB
Punte WhatsApp + RAG pentru Maria (LXC 171)
Bot de suport ROA pe WhatsApp: puntea WhatsApp (Baileys) primeste mesajele,
consumer-ul RAG raspunde folosind DOAR informatiile dintr-un depozit de
documente indexat cu embeddings (Ollama). Controlul (start/stop/restart,
documente, reindexare, sincronizare Google Drive) se face din dashboard-ul
puntii Discord (../discord-bridge/dashboard/), sectiunea "Maria — WhatsApp
- RAG" — un singur panou comun pentru ambele punti de pe acest container, nu un dashboard separat per serviciu.
Continua prototipul descris in
claude-agent/docs/maria-whatsapp-rag-prototype.md (construit initial in
/tmp/maria-bridge/) — aici e mutat in git, ca serviciu persistent.
Nu confunda cu:
- Maria pe Flowise (
vfp_roaauto/COMUN/utile/chatbot/) — chatbot web separat. - Echo /
echo-whatsapp-bridge.service(LXC 110 moltbot) — alt bot, alta punte. - Punte Discord -> Claude Code (
discord-bridge/, acelasi container) — alt proiect, alt scop (comanda Claude Code de pe Discord, nu suport RAG).
Arhitectura
WhatsApp (self-chat, sau numarul legat)
|
v
whatsapp/index.js (Baileys) -- API HTTP :8099 (/status /send /messages /react /qr)
|
v
rag/consumer.py -- polling la /messages, RAG stateless (FARA memorie intre mesaje)
| vezi docs/maria-whatsapp-rag-prototype.md pentru motiv
v
rag/store.py -- depozit documente (.txt/.md) in ~/.maria-bridge/documents/
rag/indexer.py -- chunking + embeddings Ollama -> rag_index.json
rag/sync.py -- rclone pull din Google Drive + reindexare conditionata
../discord-bridge/dashboard/api.py -- panou comun; sectiunea Maria controleaza
maria-whatsapp.service + maria-rag.service, gestioneaza
documentele si declanseaza sincronizare/reindexare
Servicii systemctl --user (vezi ops/):
| Unitate | Ce face |
|---|---|
maria-whatsapp.service |
Puntea Baileys (Node), port 8099 |
maria-rag.service |
Consumer RAG (Python), polling + raspunsuri |
maria-sync.service + .timer |
Sincronizare Drive + reindexare, la 10 min |
Instalare
cd maria-whatsapp-bridge
./ops/install.sh # creeaza ~/.maria-bridge/, venv, npm install, symlink-uri unit
Completeaza manual ~/.maria-bridge/env (copiat din ops/env.example la prima
rulare): cel putin LLM_URL (backend-ul de chat) si, daca vrei sincronizare
automata cu Drive, DRIVE_REMOTE.
OLLAMA_URL (implicit http://127.0.0.1:11434, folosit pentru embeddings la
indexare) presupune un Ollama instalat local pe container — nu exista alt
Ollama documentat in infrastructura. Instalare (facuta deja pe LXC 171,
2026-08-31):
sudo apt-get install -y zstd # dependinta a instalatorului Ollama
curl -fsSL https://ollama.com/install.sh | sh
ollama pull nomic-embed-text # ~274 MB, CPU-only pe acest container
Bridge-ul WhatsApp NU porneste automat la instalare — cere scanarea unui cod QR (actiune manuala, o singura data):
./ops/install.sh --start
# apoi deschide dashboard-ul puntii Discord si scaneaza codul QR din
# sectiunea "Maria — WhatsApp + RAG" -> cardul "Conectare WhatsApp"
Dashboard (comun cu puntea Discord)
Nu exista un dashboard separat pentru Maria. Controlul se face din dashboard-ul
puntii Discord — vezi ../discord-bridge/README.md pentru URL si autentificare
(DASHBOARD_TOKEN din ~/.claude-discord/env, tunel SSH sau Tailscale la
/claude). Acolo, sectiunea "Maria — WhatsApp + RAG":
- start/stop/restart pentru puntea WhatsApp si consumer-ul RAG
- starea conexiunii WhatsApp si codul QR de asociere (cand nu e conectat)
- listare, adaugare si stergere documente din depozitul RAG
- reconstruire index manual, sau sincronizare Drive imediata
- ultimele linii din logurile fiecarui serviciu Maria (
whatsapp.log/rag.log)
Depozitul de documente
Fisiere .txt/.md/.xml in ~/.maria-bridge/documents/ (lista exacta:
store.DOC_EXTENSIONS). Se pot administra:
- manual din dashboard-ul comun (adaugare/stergere text, reindexare automata la salvare);
- prin sincronizare Google Drive — vezi mai jos.
Sincronizare cu Google Drive
Sursa: dosarul document_store din Drive-ul contului mmarius28@gmail.com
(pe Windows apare ca D:\GoogleDrive\romfast\document_store, prin Google Drive
Desktop). ID-ul dosarului: 1C4e75zgH1_7ZK-_oBP5ZZBvUPh3iEo1O.
Containerul e headless (fara browser pentru OAuth), deci autorizarea se face pe o
masina cu browser si se muta aici ca token — fara cont de serviciu si fara consola
Google Cloud. rclone e deja instalat pe LXC 171 (rclone v1.60.1).
Pasi (o singura data):
-
Pe Windows, ia
rclone.exede la https://rclone.org/downloads/ (arhiva portabila, nu cere instalare) si ruleaza in acel dosar:rclone.exe authorize "drive" --drive-scope=drive.readonlySe deschide browserul; autentifica-te cu
mmarius28@gmail.comsi accepta. In consola apare un token JSON intre--->si<---. Copiaza-l intreg. -
Pe container, da tokenul scriptului de configurare:
ops/setup-drive.sh '<TOKEN_JSON>'Face restul singur: creeaza remote-ul
gdrive, verifica accesul la dosar, scrieDRIVE_REMOTEin~/.maria-bridge/env(cu backup) si ruleaza prima sincronizare cu reindexare. E idempotent — se poate rula din nou oricand.Tinta scrisa in env e
gdrive,root_folder_id=<ID>:— sintaxa „connection string" a rclone, care fixeaza dosarul dupa ID, fara sa depinda de structura de nume din My Drive. -
Verifica in dashboard: sectiunea Maria trebuie sa arate „Drive: …" in loc de „Sincronizare Drive dezactivata".
Tokenul se reimprospateaza singur (refresh token) cat timp aplicatia ramane autorizata in contul Google. Daca expira, dashboard-ul arata sincronizarea ca esuata — reia pasii 1-2.
Ce se sincronizeaza
rclone sync aduce doar *.txt, *.md si *.xml (vezi store.DOC_EXTENSIONS).
Restul din dosar — chatflow-uri Flowise .json, scripturi .ps1, .docx — sunt
ignorate deliberat: nu sunt cunostinte de suport.
sync sterge local ce nu mai exista in Drive, deci depozitul e o oglinda a
dosarului din Drive, nu o colectie care creste. Documentele adaugate manual din
dashboard dispar la prima sincronizare daca nu exista si in Drive.
Acelasi document in doua formate
Cand exista X.xml si X.md, in index intra doar .xml (ordinea de
preferinta: .xml > .md > .txt, in rag/store.py). Sursele .xml sunt
structurate pe probleme si de regula mai noi decat exporturile .md — la
d406_saft_knowledge, .xml era cu trei luni mai nou si cu 50% mai mare.
Fisierul umbrit ramane pe disc si apare in dashboard marcat „umbrit de …", ca sa
se vada de ce nu e indexat; daca ar fi indexate ambele, acelasi raspuns ar aparea
de doua ori in rezultatele RAG.
Cum se taie XML-ul in chunk-uri
Un chunk per element de nivel 1 — adica o problema = un chunk, cu mesajul de
eroare si rezolvarea impreuna. Taierea pe linii goale (cea folosita la .md) le-ar
separa, iar cautarea ar gasi eroarea si ar returna un chunk fara raspuns.
Etichetele raman ca prefixe lizibile (mesaj eroare: …, rezolvare: …), fara
paranteze unghiulare. Un XML care nu se poate parsa nu opreste indexarea: cade pe
taierea obisnuita, cu o linie in log. Vezi rag/indexer.py si
tests/test_store_si_chunking.py.
Dupa configurare, maria-sync.timer trage la fiecare 10 minute; reindexarea
ruleaza DOAR daca s-a schimbat efectiv ceva in depozit (amprenta pe nume +
mtime + marime, vezi rag/sync.py), ca sa nu reface embeddings degeaba.
Teste
cd /workspace/romfastsql/proxmox/lxc171-claude-agent/maria-whatsapp-bridge
python3 -m pytest # preferinta de format + taierea XML, fara retea si fara Ollama
Context conversational
rag/consumer.py nu retine memorie intre mesaje — fiecare intrebare e o
interogare RAG independenta (system prompt + top-K chunk-uri + intrebare).
Vezi claude-agent/docs/maria-whatsapp-rag-prototype.md pentru motiv si
comparatie cu celelalte punti (Discord: context nelimitat + /new; Maria pe
Flowise: fereastra fixa de 5 schimburi).