From 3e270f2e162658d77247890104fbf7ffc2470942 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sat, 25 Apr 2026 15:32:18 +0000 Subject: [PATCH] docs: document graphiti+neo4j backend architecture and translate .env.example to English - INSTALL.md: add section 3 covering the pluggable graph backend (architecture diagram, interface table, Zep vs Graphiti comparison, optional deps, env vars, Azure ACI deployment details, test instructions) - .env.example: translate all Chinese comments to English; add GRAPH_BACKEND selector and Graphiti/Neo4j variables (commented out) Co-Authored-By: Claude Sonnet 4.6 --- .env.example | 42 +++++++++------ INSTALL.md | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index be590005..62de5cea 100644 --- a/.env.example +++ b/.env.example @@ -1,25 +1,35 @@ -# LLM API配置(支持 OpenAI SDK 格式的任意 LLM API) -# 推荐使用阿里百炼平台qwen-plus模型:https://bailian.console.aliyun.com/ -# 注意消耗较大,可先进行小于40轮的模拟尝试 +# LLM API configuration (supports any OpenAI-compatible API) +# Recommended: Alibaba Qwen via Bailian platform: https://bailian.console.aliyun.com/ +# Note: high token consumption — start with simulations under 40 rounds LLM_API_KEY=your_api_key_here LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 LLM_MODEL_NAME=qwen-plus -# ===== ZEP记忆图谱配置 ===== -# 每月免费额度即可支撑简单使用:https://app.getzep.com/ +# ===== Graph backend selection ===== +# Options: "zep" (default, cloud-managed) or "graphiti" (self-hosted Neo4j) +GRAPH_BACKEND=zep + +# ===== Zep Cloud configuration (required when GRAPH_BACKEND=zep) ===== +# Free monthly quota is sufficient for basic use: https://app.getzep.com/ ZEP_API_KEY=your_zep_api_key_here -# ===== 加速 LLM 配置(可选)===== -# 注意如果不使用加速配置,env文件中就不要出现下面的配置项 -LLM_BOOST_API_KEY=your_api_key_here -LLM_BOOST_BASE_URL=your_base_url_here -LLM_BOOST_MODEL_NAME=your_model_name_here +# ===== Graphiti + Neo4j configuration (required when GRAPH_BACKEND=graphiti) ===== +# NEO4J_URI=bolt://localhost:7687 +# NEO4J_USER=neo4j +# NEO4J_PASSWORD=your_neo4j_password_here +# NEO4J_DATABASE=neo4j -# ===== Autenticació ===== -# Contrasenya de l'usuari "demo" — OBLIGATORI establir en producció -# Default buit = login deshabilitat fins que s'estableixi +# ===== Boost LLM configuration (optional) ===== +# If not using a boost LLM, remove or leave these variables empty +LLM_BOOST_API_KEY= +LLM_BOOST_BASE_URL= +LLM_BOOST_MODEL_NAME= + +# ===== Authentication ===== +# Password for the "demo" user — REQUIRED in production +# Empty default = login disabled until set DEMO_PASSWORD= -# Flask secret key — per signar tokens JWT -# Generar amb: python -c "import secrets; print(secrets.token_hex(32))" -SECRET_KEY=your-secret-key-here \ No newline at end of file +# Flask secret key — used to sign JWT tokens +# Generate with: python -c "import secrets; print(secrets.token_hex(32))" +SECRET_KEY=your-secret-key-here diff --git a/INSTALL.md b/INSTALL.md index 0f0d5439..ccb9df2c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -231,3 +231,150 @@ Flask + gunicorn (1 worker, 4 threads) | Login retorna 401 sempre | `DEMO_PASSWORD` buida o incorrecta | Verifica el valor a `config.sh` / secret Azure | | Container App no arrenca | Imatge no trobada a l'ACR | Verifica que `2-build-deploy.sh` hagi finalitzat sense errors | | Token expirat al cap de 24h | Comportament esperat | Torna a fer login a `/login` | + +--- + +## 3. Backend de graf pluggable (Graphiti + Neo4j) + +La branca `feat-pluggable-graph-backend` introdueix un sistema de backends intercanviables per al graf de coneixement. El backend per defecte és Zep Cloud; l'alternatiu és Graphiti + Neo4j auto-allotjat. + +### Arquitectura + +``` +GraphBuilderService + │ + │ self._graph = get_graph_backend() + ▼ +┌─────────────────────────────────┐ +│ factory.get_graph_backend() │ ← llegeix GRAPH_BACKEND env var +│ (patró Singleton) │ +└────────────┬────────────────────┘ + │ + ┌────────┴────────┐ + ▼ ▼ +ZepBackend GraphitiBackend + │ │ + ▼ ▼ +Zep Cloud API Neo4j (bolt://) + + graphiti-core + + OpenAI embedder +``` + +Tots dos backends implementen la mateixa interfície abstracta `GraphBackend` (`backend/app/graph/base.py`): + +| Mètode | Descripció | +|--------|------------| +| `create_graph(graph_id, name)` | Crea o registra el graf | +| `set_ontology(graph_ids, entities, edges)` | Defineix l'ontologia | +| `add_batch(graph_id, episodes)` | Afegeix episodis de text en lot | +| `get_episode(uuid_)` | Consulta l'estat de processament d'un episodi | +| `get_all_nodes(graph_id)` | Retorna tots els nodes del graf | +| `get_all_edges(graph_id)` | Retorna totes les arestes | +| `get_node(uuid_)` | Node per UUID | +| `get_node_edges(node_uuid)` | Arestes d'un node | +| `search(graph_id, query, limit)` | Cerca semàntica | +| `add_text(graph_id, data)` | Afegeix text directament | +| `delete_graph(graph_id)` | Elimina el graf complet | + +### Fitxers clau + +``` +backend/app/graph/ +├── base.py — interfície abstracta GraphBackend +├── factory.py — factory + singleton (get_graph_backend) +├── zep_backend.py — implementació Zep Cloud +└── graphiti_backend.py — implementació Graphiti + Neo4j +``` + +### Diferències de comportament entre backends + +| Aspecte | ZepBackend | GraphitiBackend | +|---------|-----------|-----------------| +| **Allotjament** | Zep Cloud (SaaS) | Neo4j auto-allotjat | +| **Ontologia** | API nativa Zep | No-op (extracció LLM automàtica) | +| **Polling d'episodis** | `episode.get(uuid_)` real | Retorna sempre `processed=True` | +| **Consultes** | SDK Zep | Queries Cypher directes | +| **Paginació nodes/arestes** | 100 items/pàgina, màx. 2000 | Sense límit explícit | +| **Resiliència** | Retry amb backoff exponencial (3 intents) | Sense retry | +| **Cerca** | `reranker=cross_encoder` | `graphiti_core.search()` | +| **Credencials** | `ZEP_API_KEY` | `NEO4J_URI`, `NEO4J_USER`, `NEO4J_PASSWORD` | +| **Threading async** | No cal (SDK síncron) | Thread daemon + `asyncio.run_coroutine_threadsafe` | + +### Instal·lació de les dependències Graphiti + +Graphiti és una dependència opcional. Per activar-la: + +```bash +# Amb uv (recomanat) +uv pip install -e ".[graphiti]" + +# Amb pip +pip install "mirofish-backend[graphiti]" +# o directament: +pip install "graphiti-core>=0.3.0" "neo4j>=5.23.0" +``` + +Les dependències base (Zep) segueixen instal·lant-se com sempre: + +```bash +uv pip install -r requirements.txt +``` + +### Variables d'entorn per a Graphiti + Neo4j + +```env +# Selecció de backend (per defecte: zep) +GRAPH_BACKEND=graphiti + +# Connexió Neo4j (protocol bolt) +NEO4J_URI=bolt://:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=la-teva-contrasenya + +# LLM_API_KEY, LLM_BASE_URL i LLM_MODEL_NAME segueixen sent necessaris +# (graphiti-core els usa per a l'extracció d'entitats i els embeddings) +``` + +> **Nota:** quan `GRAPH_BACKEND=graphiti`, `ZEP_API_KEY` no és necessari. + +### Desplegament a Azure (aci-graphiti-neo4j) + +Al resource group `rg_mirofish` existeix el container group `aci-graphiti-neo4j` amb tres contenidors al mateix pod: + +| Contenidor | Imatge | Port intern | Funció | +|-----------|--------|-------------|--------| +| `neo4j` | `mirofishgeneacr.azurecr.io/neo4j:5.26.0` | 7474 (HTTP), 7687 (bolt) | Base de dades de graf | +| `graphiti-mcp` | `mirofishgeneacr.azurecr.io/knowledge-graph-mcp:standalone` | 8000 | API graphiti-core via MCP | +| `caddy` | `mirofishgeneacr.azurecr.io/caddy:2` | 443 | Proxy HTTPS per a graphiti-mcp | + +**Ports exposats públicament:** + +| Port | Protocol | Destí | +|------|----------|-------| +| 443 | TCP | caddy → graphiti-mcp (HTTPS, certificat Let's Encrypt) | +| 7687 | TCP | bolt → neo4j (autenticat) | + +**Endpoints:** + +- Graphiti MCP: `https://graphitigene-mcp.westeurope.azurecontainer.io` +- Neo4j bolt: `bolt://52.149.109.53:7687` + +**Variables d'entorn del Container App `mirofishgene` (configuració activa):** + +```env +GRAPH_BACKEND=graphiti +NEO4J_URI=bolt://52.149.109.53:7687 +NEO4J_USER=neo4j +NEO4J_DATABASE=neo4j +NEO4J_PASSWORD= +``` + +### Tests + +```bash +# Executar els tests del factory (no requereix Neo4j ni Zep actius) +cd .worktrees/feat-pluggable-graph-backend +pytest backend/tests/test_graph_factory.py -v +``` + +El fixture `reset_graph_factory_singleton` (a `backend/tests/conftest.py`) reseteja el singleton entre tests per evitar interferències quan es canvia `GRAPH_BACKEND`.