-
Notifications
You must be signed in to change notification settings - Fork 378
feat(ops): backend prêt prod + SPA statique (FastAPI+Vite) + CI + systemd/nginx #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ing in prod_check
…nx templates and CI
…eep .env loading order
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Mise en place d’un environnement “prod-like” : API FastAPI servant aussi le frontend Vite (même origine), ajout des endpoints de démonstration agentiques (Reflection, Tool Use, RAG, etc.), scripts d’ingestion RAG, configuration Ops (systemd, nginx) et CI (lint + build + smoke).
- Ajout d’une application FastAPI avec nombreux endpoints agents + RAG + configuration dynamique des providers (in‑memory).
- Intégration d’un frontend React/Vite servi statiquement par FastAPI si dist présent.
- Ajout d’outils Ops (scripts run/dev/ingest, systemd service, nginx conf, CI) et catalogue de patterns.
Reviewed Changes
Copilot reviewed 70 out of 74 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| uvicorn.pid | Ajout d’un artefact PID (exécutable) commité. |
| scripts/prod_check.sh | Script de probes endpoints (healthz / agents). |
| scripts/ingest.sh | Script construction index FAISS RAG. |
| scripts/dev_run.sh | Script d’environnement dev + build conditionnel frontend. |
| scripts/copy_env_templates.sh | Copie de templates .env (dev/prod). |
| run.sh | Script start/stop/status uvicorn + build frontend. |
| ops/systemd/all-agentic.service | Service systemd uvicorn (prod). |
| ops/nginx/all-agentic.conf | Reverse proxy nginx + cache assets. |
| frontend/vite.config.ts | Configuration Vite + plugin React. |
| frontend/tsconfig.node.json | TS config (node/build tooling). |
| frontend/tsconfig.json | TS project references. |
| frontend/tsconfig.app.json | TS config app React. |
| frontend/src/types/patterns.ts | Types TS du catalogue patterns. |
| frontend/src/pages/gallery.css | Styles grille cartes. |
| frontend/src/pages/PatternsCatalog.tsx | Catalogue filtrable des patterns. |
| frontend/src/pages/PatternDetails.tsx | Détails pattern + lancement démo. |
| frontend/src/pages/Gallery17.tsx | Page “Gallery 17” (cards). |
| frontend/src/main.tsx | Entrée React root render. |
| frontend/src/index.css | Styles globaux layout. |
| frontend/src/components/ProviderToggle.tsx | Sélecteur dynamique providers LLM/embeddings. |
| frontend/src/api/patterns.ts | Fonctions fetch API patterns. |
| frontend/src/api.ts | Client API (health / a01 / rag / a02). |
| frontend/src/agents/A09ToT.tsx | UI démo Tree-of-Thoughts. |
| frontend/src/agents/A08GraphMemory.tsx | UI démo Graph Memory. |
| frontend/src/agents/A07EpisodicSemantic.tsx | UI démo mémoire épisodique+sémantique. |
| frontend/src/agents/A06Blackboard.tsx | UI démo blackboard. |
| frontend/src/agents/A05PEV.tsx | UI démo PEV. |
| frontend/src/agents/A04Planning.tsx | UI démo planning. |
| frontend/src/App.tsx | Shell principal + navigation + pages. |
| frontend/src/App.css | Styles résiduels template Vite (partiellement inutilisés). |
| frontend/package.json | Dépendances frontend React/Vite. |
| frontend/index.html | Entrée HTML Vite. |
| frontend/eslint.config.js | Config ESLint TS/React. |
| frontend/README.md | README template Vite/React. |
| frontend/.gitignore | Ignore node_modules/dist etc. |
| backend/requirements.txt | Dépendances FastAPI, LangChain, embeddings, etc. |
| backend/ops/env_templates/.env.production.example | Template env prod. |
| backend/ops/env_templates/.env.example | Template env dev. |
| backend/ingestion/build_faiss.py | Construction index FAISS (RAG). |
| backend/ingestion/init.py | Init vide. |
| backend/core/tools.py | Wrapper outil Tavily avec garde clé. |
| backend/core/schemas.py | Pydantic schemas (agents, RAG, patterns). |
| backend/core/rag.py | Chargement index FAISS + retriever. |
| backend/core/patterns_data.py | Données catalogue patterns (17). |
| backend/core/llm.py | Fabrique LLM OpenAI/Gemini. |
| backend/core/graph_utils.py | Utilitaire passthrough. |
| backend/core/embed.py | Fabrique embeddings OpenAI/Gemini. |
| backend/core/init.py | Init vide. |
| backend/app.py | Application FastAPI + endpoints SPA/static. |
| backend/agents/a17_reflexive_metacognitive.py | Agent réflexif métacognitif. |
| backend/agents/a16_simulator_mitl.py | Agent simulateur MITL. |
| backend/agents/a15_rlhf_loop.py | Boucle RLHF-like. |
| backend/agents/a14_dry_run.py | Dry-run multi prompts reflection. |
| backend/agents/a13_chain_of_verification.py | Chain-of-Verification agent. |
| backend/agents/a12_self_ask.py | Self-Ask agent. |
| backend/agents/a11_meta_controller.py | Meta-controller router. |
| backend/agents/a10_ensemble_decision.py | Ensemble/vote agent. |
| backend/agents/a09_tree_of_thoughts.py | ToT agent (exploration). |
| backend/agents/a08_graph_memory.py | Extraction graphe simple. |
| backend/agents/a07_episodic_semantic.py | Mémoire épisodique+sémantique. |
| backend/agents/a06_blackboard.py | Blackboard agent. |
| backend/agents/a05_pev.py | Plan-Execute-Verify agent. |
| backend/agents/a04_planning.py | Planning agent. |
| backend/agents/a03_react.py | ReAct agent. |
| backend/agents/a02_tool_use.py | Tool Use agent. |
| backend/agents/a01_reflection.py | Reflection agent. |
| backend/agents/init.py | Init vide. |
| backend/init.py | Init vide. |
| DEPLOY_VPS.md | Instructions déploiement env prod. |
| .github/workflows/ci.yml | Workflow CI lint + build + smoke. |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| curl -sS "http://$HOST:$PORT/api/a01/run" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d '{"prompt":"Explique la loi des grands nombres simplement."}' \ | ||
| | python - <<'PY' | ||
| import sys, json | ||
| print(json.dumps(json.load(sys.stdin), indent=2, ensure_ascii=False)) | ||
| PY |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JSON pretty-print is only executed when curl fails because '||' is used instead of piping; as written, successful responses are not formatted. Replace '|| python - <<'PY'' with a pipe '|' so the curl output (on success) is passed to python for formatting.
| curl -sS "http://$HOST:$PORT/api/rag/qa" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d '{"question":"Quels thèmes sont évoqués dans la démo RAG ?","k":5}' \ | ||
| | python - <<'PY' | ||
| import sys, json | ||
| print(json.dumps(json.load(sys.stdin), indent=2, ensure_ascii=False)) | ||
| PY |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue: using '||' causes the pretty-printer to run only on error; use a pipe '|' to format successful JSON output.
| curl -sS "http://$HOST:$PORT/api/a02/run" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d '{"question":"Quelles ont été les annonces majeures de la dernière WWDC ?"}' \ | ||
| | python - <<'PY' | ||
| import sys, json | ||
| raw = sys.stdin.read().strip() | ||
| if not raw: | ||
| print("[WARN] vide (peut-être Tavily absent)"); sys.exit(0) | ||
| try: | ||
| print(json.dumps(json.loads(raw), indent=2, ensure_ascii=False)) | ||
| except Exception: | ||
| print("[WARN] réponse non JSON:") | ||
| print(raw) |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback pretty-print block executes only if curl fails due to '||'; to always inspect and format output, switch to a pipe '|' before python and handle non-JSON inside the script as already implemented.
scripts/dev_run.sh
Outdated
|
|
||
| # build frontend si nécessaire | ||
| if [ -d frontend ] && [ ! -d frontend/dist ]; then | ||
| ( cd frontend && npm i && npm run build ) |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Use 'npm ci' instead of 'npm i' for deterministic builds in CI/dev scripts (it uses package-lock and fails on mismatch), improving reproducibility. Suggested change: '( cd frontend && npm ci && npm run build )'.
| ( cd frontend && npm i && npm run build ) | |
| ( cd frontend && npm ci && npm run build ) |
| await fetch("/api/config/provider", { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify(cfg), | ||
| }).then((r) => r.json()); | ||
| setMsg("✅ Appliqué. (In-memory) — Les prochains appels utiliseront ces valeurs."); |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The response status is ignored; if the server returns a non-2xx status (e.g. 400/500 with HTML or error JSON), '.json()' may throw producing an unhelpful message. Check r.ok and throw a descriptive error before parsing JSON. Example: 'const r = await fetch(...); if(!r.ok) throw new Error(Failed: ${r.status}); const data = await r.json();'.
| task: str | ||
| breadth: int | ||
| depth: int |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'depth' parameter is never used to limit expansion; the graph always has an unconditional self-edge 'expand' -> 'expand' plus a direct edge to 'final', so depth control is ineffective and may loop more times than intended. Introduce a depth counter in state (e.g. increment on each expansion) and conditionally route to 'final' when the configured depth is reached instead of unconditional edges.
| g = StateGraph(S) | ||
| g.add_node("init", n_init) | ||
| g.add_node("expand", n_expand_layer) | ||
| g.add_node("final", n_last_answer) | ||
| g.set_entry_point("init") | ||
| g.add_edge("init","expand") | ||
| g.add_edge("expand","expand") | ||
| g.add_edge("expand","final") |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'depth' parameter is never used to limit expansion; the graph always has an unconditional self-edge 'expand' -> 'expand' plus a direct edge to 'final', so depth control is ineffective and may loop more times than intended. Introduce a depth counter in state (e.g. increment on each expansion) and conditionally route to 'final' when the configured depth is reached instead of unconditional edges.
| b = int(body.get("breadth", 3)) | ||
| d = int(body.get("depth", 2)) |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'breadth' and 'depth' are taken directly from user input without validation; large values could trigger excessive LLM calls and resource usage. Clamp to safe maxima (e.g. breadth<=5, depth<=5) or return 422 for out-of-range values before running the graph.
| b = int(body.get("breadth", 3)) | |
| d = int(body.get("depth", 2)) | |
| try: | |
| b = int(body.get("breadth", 3)) | |
| d = int(body.get("depth", 2)) | |
| except (ValueError, TypeError): | |
| raise HTTPException(status_code=422, detail="breadth and depth must be integers") | |
| if not (1 <= b <= 5) or not (1 <= d <= 5): | |
| raise HTTPException(status_code=422, detail="breadth and depth must be between 1 and 5") |
| @app.post("/api/config/provider") | ||
| def set_provider_config( | ||
| llm: dict = Body(default={}), | ||
| embeddings: dict = Body(default={}) | ||
| ): | ||
| """Met à jour os.environ pour les appels suivants (ne modifie pas .env sur disque).""" | ||
| if "provider" in llm: | ||
| os.environ["DEFAULT_LLM_PROVIDER"] = str(llm["provider"]).lower() | ||
| if "model" in llm: | ||
| os.environ["DEFAULT_LLM_MODEL"] = str(llm["model"]) | ||
| if "provider" in embeddings: | ||
| os.environ["DEFAULT_EMBEDDING_PROVIDER"] = str(embeddings["provider"]).lower() | ||
| if "model" in embeddings: | ||
| os.environ["DEFAULT_EMBEDDING_MODEL"] = str(embeddings["model"]) | ||
| return {"ok": True, "applied": get_provider_config()} |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This endpoint mutates process-wide environment variables which only affect the current worker; in a multi-worker uvicorn deployment (workers>1) requests may see inconsistent provider settings. Consider keeping an in-memory configuration object (thread-safe) and documenting non-persistence, or providing a persistent config mechanism applied at startup across all workers.
uvicorn.pid
Outdated
| @@ -0,0 +1 @@ | |||
| 923988 | |||
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Committing a runtime PID file can cause stale process management and unnecessary merge noise; it should be added to .gitignore and removed from version control.
| 923988 |
…un, restart) + .nvmrc; fix lint & port collisions - Add .nvmrc with Node v20.19.0 for consistent Node version - Create scripts/ensure_venv.sh: creates/validates venv, upgrades pip, installs deps - Create scripts/port_free.sh: frees port by killing uvicorn processes from this repo - Create scripts/dev_run.sh: complete dev environment (venv + front build + backend launch) - Create scripts/restart.sh: restarts dev environment cleanly - All scripts are POSIX-compliant with set -euo pipefail - Scripts handle port conflicts automatically (fallback to 8011) - Scripts are idempotent and can be run multiple times safely - Fix frontend build issues with clean node_modules reinstall - All scripts are executable and tested working
Objet
Rendre le backend opérationnel “prod-like” et servir le frontend buildé (Vite) depuis la même origine, + artefacts Ops.
Points clés
Backend FastAPI :
/sifrontend/distprésent (même origine que l’API)./healthzenrichi (headers X-LLM-Provider/Embeddings).LLM/Embeddings :
backend/core/llm.py: fabrique OpenAI/Gemini sans kwargs non supportés par Gemini.backend/core/embed.py: embeddings OpenAI ou Gemini.backend/core/tools.py: Tavily avec garde si clé absente.Ingestion RAG :
backend/ingestion/build_faiss.py+ varsRAG_DATA_DIR/RAG_INDEX_DIR.Frontend (Vite/React TS) :
ProviderToggle(changement in-memory des providers).CI GitHub Actions :
/healthz,api/a01/run).Ops artefacts :
ops/systemd/all-agentic.service(uvicorn, same-origin).ops/nginx/all-agentic.conf(reverse proxy + cache assets).backend/ops/env_templates/.env*.example+scripts/copy_env_templates.sh.Test local rapide