Application web Python monolythique avec :
- FastAPI pour le backend (routes REST + templates Jinja2)
- SQLAlchemy + SQLite pour la persistance
- Jinja2 + Bootstrap 5 pour le rendu côté serveur
- ChromaDB pour la recherche sémantique (RAG)
- opencode serve pour l'assistant IA (API HTTP)
id,nom,description- Relation 1→N avec
Legume
id,nom,nom_scientifique,famille_id(FK → Famille)description,conseils_culture,exposition,sol,arrosage- Relations 1→N :
varietes,calendrier,maladies
id,legume_id(FK → Legume),nom,description,particularites
id,legume_id(FK → Legume),type,mois_debut,semaine_debut,mois_fin,semaine_fin,detailstype:semis_serre_chaude,semis_serre_froide,semis_direct,semis_interieur,plantation,action,bouturage,recolte- Semaines : 1-4 par mois (précision à la semaine près)
- 48 semaines/an (12 mois × 4 semaines)
id,legume_id(FK → Legume),type(maladie/ravageur),nom,symptomes,traitement,prevention
id,annee,nom,active,notes,created_at- Relation 1→N avec
PotagerItem
id,potager_id(FK → Potager),legume_id(FK nullable → Legume),variete_id(FK nullable → Variete)type,nom_custom,quantite,emplacement,compagnons,notes,ordre
id,item_id(FK → PotagerItem),type,mois_debut,semaine_debut,mois_fin,semaine_fin,details- Copie du
Calendrierdu légume à l'ajout, modifiable ensuite individuellement par l'utilisateur
| Route | Template | Description |
|---|---|---|
GET / |
index.html |
Accueil : stats, familles, potagers |
GET /legumes |
legume_list.html |
Liste des légumes (filtrable par famille) |
GET /legume/{id} |
legume_detail.html |
Fiche : infos + onglets variétés/calendrier barres/maladies |
GET /legume/{id}/pdf |
legume_pdf.html |
Version imprimable |
GET /familles |
famille_list.html |
Liste des familles botaniques |
GET /recherche |
search.html |
Recherche plein texte |
| Route | Template | Description |
|---|---|---|
GET /potager |
potager_list.html |
Liste des potagers |
GET /potager/creer |
potager_form.html |
Formulaire création |
POST /potager/creer |
— | Création |
GET /potager/{id} |
potager_detail.html |
Calendrier barres + vue mensuelle |
POST /potager/{id}/ajouter |
— | Ajouter une culture à un potager |
| Route | Description |
|---|---|
GET /api/chat/health |
Vérifie/démarre opencode serve |
POST /api/chat/session |
Crée une session de chat |
POST /api/chat/send |
Envoie un message (avec contexte RAG) |
| Route | Description |
|---|---|
GET /admin |
Dashboard |
GET/POST /admin/legumes |
Liste + création légumes |
GET/POST /admin/legumes/{id}/editer |
Édition légume |
POST /admin/legumes/{id}/supprimer |
Suppression |
POST /admin/varietes/{id}/editer |
Édition variété |
POST /admin/legumes/{id}/varietes/ajouter |
Ajout variété |
POST /admin/calendrier/{id}/editer |
Édition calendrier |
POST /admin/legumes/{id}/calendrier/ajouter |
Ajout calendrier |
POST /admin/maladies/{id}/editer |
Édition maladie |
POST /admin/legumes/{id}/maladies/ajouter |
Ajout maladie |
GET/POST /admin/familles |
CRUD familles |
GET /admin/rag |
Upload/indexation PDFs |
POST /admin/rag/upload |
Import PDF → ChromaDB |
Le calendrier divise chaque mois en 4 semaines :
TOTAL_WEEKS = 48
def week_pos(mois, semaine):
return (mois - 1) * 4 + semaine
def bar_style(mois_debut, semaine_debut, mois_fin, semaine_fin):
start = week_pos(mois_debut, semaine_debut)
end = week_pos(mois_fin, semaine_fin)
left = (start - 1) / TOTAL_WEEKS * 100
width = (end - start + 1) / TOTAL_WEEKS * 100
return f"left:{left:.2f}%;width:{width:.2f}%;"Dans le template, les barres sont positionnées en absolute dans un conteneur relative avec la grille des 12 mois affichée en en-tête. Chaque type d'entrée a une couleur dédiée (TYPE_COLORS).
- L'agent est auto-démarré en subprocess si nécessaire (
opencode serve --port 4096) - Endpoints utilisés :
/global/health,/session(POST),/session/{id}/message(POST) - Un system prompt spécialisé jardinage est envoyé à chaque message
- Le contexte de la page en cours (
page_contextdans le template) est transmis au système
- Bulle fixée en bas à droite
- Input text + « Envoyer » dans la bulle ouverte
- Envoie
session_id,textetcontext(extrait de#chat-context) à/api/chat/send - L'historique s'affiche dans la bulle, chargé au clic
- Utilise ChromaDB PersistentClient avec collection
potager_docs - Embedding : modèle par défaut de ChromaDB (pas de sentence-transformers requis)
- Chunking : par mots, 800 mots par chunk, 150 de recouvrement
ingest_pdf(): extrait le texte viapypdf, découpe en chunks, indexe dans ChromaDBget_context(query, k=3): recherche les k chunks les plus proches et les formate pour le prompt
Dans POST /api/chat/send :
rag_engine.get_context(text, k=3)récupère les documents pertinents- S'ils existent, ils sont insérés dans
full_contextavec la mention « Documents de référence » full_contextest passé commesystemsupplémentaire à opencode
Quatre légumes réalistes (français) avec :
- Ail (Alliacées) : 6 variétés, 6 entrées calendrier, 5 maladies
- Poivron (Solanacées) : 6 variétés, 9 entrées calendrier, 6 maladies
- Potimarron (Cucurbitacées) : 6 variétés, 9 entrées calendrier, 6 maladies
- Épinard (Chénopodiacées) : 6 variétés, 8 entrées calendrier, 6 maladies
Chaque entrée calendrier est définie par (type, mois_debut, semaine_debut, mois_fin, semaine_fin, details).
potager-app/
├── run.py # uvicorn --reload
├── requirements.txt # fastapi, uvicorn, sqlalchemy, jinja2, python-multipart
├── README.md
├── PROJECT.md
├── data/
│ ├── potager.db # SQLite (auto-créé)
│ └── rag/ # ChromaDB + PDFs (auto-créé)
│ ├── chroma/
│ └── pdfs/
└── app/
├── __init__.py
├── main.py # FastAPI app, toutes les routes
├── models.py # SQLAlchemy models
├── database.py # Engine SQLite + get_db()
├── seed.py # Données seed (4 légumes)
├── ai_client.py # Client HTTP opencode serve
├── rag.py # RAG ChromaDB
├── static/
│ ├── style.css # Thème vert, cards, responsive
│ ├── chat.js # Chat flottant JS
│ └── chat.css # Styles de la bulle chat
└── templates/
├── base.html # Layout : navbar, footer, chat_bubble
├── index.html
├── legume_list.html
├── legume_detail.html
├── legume_pdf.html
├── famille_list.html
├── search.html
├── chat_bubble.html # Bulle flottante
├── potager_list.html
├── potager_form.html
├── potager_detail.html
├── admin.html
├── admin_legumes.html
├── admin_legume_edit.html
├── admin_familles.html
└── admin_rag.html
- Créer le projet FastAPI avec SQLAlchemy + SQLite
- Définir les 7 modèles (Famille, Legume, Variete, Calendrier, Maladie, Potager, PotagerItem, PotagerCalendrier)
- Implémenter le système de calendrier à 48 semaines avec
week_pos()etbar_style() - Créer les templates Bootstrap 5 avec héritage Jinja2
- Ajouter les routes CRUD admin
- Implémenter
ai_client.py: HTTP vers opencode serve avec auto-démarrage - Implémenter
rag.py: ChromaDB PersistentClient, chunking par mots,pypdfpour l'extraction - Intégrer RAG dans le chat :
get_context()→systemprompt enrichi - Ajouter la bulle chat flottante avec contexte de page