Skip to content

About

Asistente de IA de SmartPot: sistema experto, lógica difusa, ML y agente reactivo

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

SmartPot-AI

Estado del Proyecto

Python CI CodeQL Advanced Publish Docker Images

Descripción

SmartPot-AI es el asistente inteligente de SmartPot. Recibe la última lectura de un cultivo, su historial reciente, los actuadores disponibles, dónde está y el clima de afuera, y devuelve un diagnóstico completo que combina estas técnicas de inteligencia artificial:

Técnica Qué resuelve Dónde vive
Sistema experto Diagnóstico por variable y conclusiones encadenadas (estrés térmico, riesgo de hongos, bloqueo de nutrientes, falla de sensor…) con su explicación app/engine/diagnosis.py, expert_system.py, rules.py
Lógica difusa Índice de salud de 0 a 100 que tolera la incertidumbre de los sensores app/engine/fuzzy.py
Aprendizaje automático Regresión logística (ventilación), red neuronal MLP (corrección de pH) e Isolation Forest (lecturas atípicas) app/engine/models.py
Agente reactivo Convierte el diagnóstico en acciones sobre los actuadores que el cultivo sí tiene app/engine/agent.py
Pronóstico Tendencia de cada variable (Theil-Sen) y horas hasta salir del rango ideal app/engine/forecast.py
Análisis de flota Ranking, problemas compartidos del entorno, grupos K-Means y acciones en bloque app/engine/fleet.py
Consejo de lugar Compara la luz que pide la especie con la que recibe el cultivo y sube el tono solo cuando el lugar ya afecta la salud
Aprendizaje continuo Aprende de las lecturas reales: supervisado (¿se secará?, ¿habrá calor?, humedad en 1 h) y no supervisado (estados de operación y lecturas atípicas), con reentrenamiento cuando llegan datos nuevos app/learning/
Aceleración C++ Nativa Cómputo numérico directo en C++20 (Theil-Sen $O(M)$ lineal, lógica difusa Sugeno, control de calidad IQR, normalización) con C ABI y fallback src/native/, app/engine/native_bridge.py

Es un servicio interno: solo SmartPot-API lo consulta, con un token compartido, y nunca se publica en Internet.

flowchart LR
  req["Lectura + historial<br/>+ actuadores"] --> diag["Diagnóstico<br/>por variable"]
  diag --> ml["Modelos de ML"]
  diag --> es["Sistema experto<br/>(encadenamiento)"]
  ml --> es
  diag --> fz["Lógica difusa<br/>índice de salud"]
  es --> ag["Agente reactivo"]
  ml --> ag
  fz --> out["Respuesta"]
  es --> out
  ag --> out
  api["Lecturas reales<br/>(lotes de la API)"] --> lr["Aprendizaje continuo"]
  lr --> es
  lr --> ag
  lr --> out
Loading

Base de Conocimiento

app/knowledge/profiles.py guarda los rangos ideales de seis especies en la escala de los sensores del dispositivo: temperatura (°C), humedad del aire (%), luz (lux relativos, 0 a 2000), pH, nutrientes (ppm, EC × 700) y humedad del sustrato (%).

Especie Temperatura Humedad pH TDS (ppm) Sustrato
Lechuga (LETTUCE) 15–22 50–70 5.5–6.5 560–840 60–80
Tomate (TOMATO) 20–28 60–80 5.5–6.5 1400–2800 55–75
Fresa (STRAWBERRY) 18–26 60–75 5.5–6.2 700–980 60–80
Albahaca (BASIL) 20–30 40–60 5.5–6.5 700–1120 50–70
Espinaca (SPINACH) 15–24 50–70 6.0–7.0 1260–1610 60–80
Pimentón (PEPPER) 21–29 50–70 5.8–6.5 1400–2100 55–75

Una variable fuera de rango se mide en tolerancias (5 °C, 15 %, 300 lux, 0.8 de pH, 400 ppm, 15 %). Desde una tolerancia completa el hallazgo es crítico.

Cómo razona

  1. Diagnóstico: cada variable queda LOW, OPTIMAL o HIGH, con severidad WARNING o CRITICAL y una recomendación en español. Entre las 22:00 y las 6:00 (hora local enviada en localHour) la luz baja queda como REST: es el periodo de oscuridad de la planta y no resta salud.
  2. Modelos: las variables se normalizan respecto al perfil (0 = mínimo ideal, 1 = máximo ideal), así un mismo modelo sirve para todas las especies. Se entrenan al arrancar con 4000 muestras sintéticas y semilla fija, por lo que los resultados son reproducibles. GET /v1/models informa su exactitud.
  3. Sistema experto: un motor de encadenamiento hacia adelante dispara reglas por prioridad (cada regla una sola vez). Las conclusiones de primer nivel —por ejemplo heat_stress o nutrient_lockout— alimentan reglas de segundo nivel como compound_stress o critical_state. Si el Isolation Forest y el historial indican una lectura imposible, sensor_fault bloquea las acciones.
  4. Lógica difusa: cada desviación pertenece en distinto grado a los conjuntos «ideal», «aceptable», «desviada» y «crítica». La inferencia Sugeno de orden cero da la salud de cada variable, el índice global las pondera (el pH y la temperatura pesan más) y una regla de peor caso limita la salud cuando algo es crítico.
  5. Pronóstico: con el historial y la hora de cada lectura, el estimador de Theil-Sen (mediana de las pendientes entre pares, resistente a lecturas atípicas) calcula la pendiente por hora, el valor esperado en 3 h y en cuántas horas la variable saldría de su rango. Alimenta las reglas drying_trend y heat_building.
  6. Agente: propone acciones solo para los actuadores del cultivo: riego si el sustrato está seco (salvo que llueva sobre un cultivo al aire libre), luz ultravioleta si falta de día (y apagarla de noche), ventilación si hay calor, humedad alta o el modelo lo predice, humidificador, dosificador de pH y de nutrientes. Si el pronóstico indica que el sustrato llegará al mínimo o la temperatura al máximo en menos de 1 h, actúa antes (riego o ventilación preventivos). La API aplica el enfriamiento y solo ejecuta con el modo automático activo.
  7. Aprendizaje: lo aprendido de las lecturas reales de la especie (ver abajo) entra al sistema experto ( learned_drying, learned_heat, unusual_pattern) y, con probabilidad de 85 % o más, al agente como riego o ventilación preventivos.
  8. Lugar y clima: con placement (bajo techo o al aire libre y cuánto sol recibe) y weather (el clima de afuera que la API pide al simulador), la evaluación devuelve placement: OK si el lugar le sirve a la especie, UNKNOWN si no se sabe dónde está, TIP si no es el ideal pero la planta está bien y MOVE si el lugar ya se nota en las lecturas. Al aire libre suma dos reglas: rain_outside (con 0,5 mm o más de lluvia no hace falta regar) y sensor_vs_outside (el sensor se aleja 8 °C o más del clima de afuera).
  9. Flota: POST /v1/fleet recibe todos los cultivos de una cuenta y devuelve el ranking por salud, los problemas que se repiten en la mitad o más de los cultivos (señal de que el problema es el entorno), grupos por condiciones similares con K-Means (la cantidad de grupos se elige por silueta) y las acciones del agente reunidas por actuador para aplicarlas en bloque.

Aprendizaje Continuo

Los modelos base se entrenan con datos sintéticos; el aprendizaje continuo los complementa con lo que de verdad pasa en los cultivos reales. La API envía por lotes cada lectura de un cultivo real que llega por MQTT (las de los cultivos virtuales son sintéticas y no se envían) (POST /v1/learning/readings) y el servicio las guarda en SQLite dentro del volumen /data, con el id del cultivo seudonimizado (SHA-256): aprende de la serie de cada cultivo sin saber a quién pertenece.

Paso Qué hace Dónde
1. Calidad de datos Completitud, validez física y atípicos por rango intercuartílico (k = 3), que se excluyen; da un puntaje DQS quality.py
2. Variables Posición de cada variable en su rango ideal, hora del día circular (seno y coseno) y tendencia de la última media hora features.py
3. Etiquetas autosupervisadas Lo que pasó en la hora siguiente: ¿el sustrato bajó del mínimo?, ¿la temperatura pasó del máximo?, ¿cuánto cambió la humedad? features.py
4. Comparación de modelos Línea base, regresión logística, K vecinos, árbol de decisión, bosque aleatorio, gradient boosting y red neuronal, con validación cruzada temporal (TimeSeriesSplit, 4 cortes) y F1 macro o error medio trainer.py
5. Ajuste GridSearchCV sobre el mejor candidato trainer.py
6. Campeón y retador Se evalúa en el 20 % de lecturas más recientes; el modelo nuevo reemplaza al vigente solo si lo mejora y si supera a la línea base trainer.py
7. No supervisado Estados de operación con K-Means (k de 2 a 6 por silueta, con nombre legible) e Isolation Forest entrenado con lecturas reales trainer.py

Cada especie se entrena por separado desde 200 lecturas etiquetadas y se reentrena cada 300 lecturas nuevas. En modo autónomo puede ejecutarse en un proceso local secundario, mientras que en arquitecturas desacopladas de producción el entrenamiento se delega enteramente a SmartPot-Trainer (http://trainer-smartpot:8001), operando SmartPot-AI como un motor puro de inferencia sub-milisegundo que recarga los modelos en caliente (POST /v1/learning/reload) en < 5 ms sin interrupción de servicio.

POST /v1/insights responde además learning: el estado de operación actual, si la lectura es atípica para la especie, la probabilidad de necesitar riego o ventilación en la próxima hora y la humedad esperada del sustrato en 1 h, cada una con el modelo y su puntaje.

Optimización de Alto Rendimiento y Aceleración Nativa (C++20 / Cython / Polars / LoRA)

SmartPot-AI incorpora una arquitectura computacional híbrida de alto rendimiento diseñada para operar a nivel sub-milisegundo y eliminar los cuellos de botella de memoria y contención de CPU en producción:

  1. Jerarquía de Carga de 3 Niveles (3-Tier Engine Bridge):

    • Tier 1 (Cython Extension nogil): Carga smartpot_cy_core (.so/.pyd) vinculando directamente la cabecera C ABI capi.h. Emplea Memoryviews (double[::1]) para paso zero-copy sin asignación de objetos Python y ejecuta los bucles intensivos bajo bloques with nogil: para paralelismo multihilo real en CPU.
    • Tier 2 (ctypes DLL/SO): Carga dinámica del núcleo compilado smartpot_core.dll o libsmartpot_core.so con vectorización SIMD AVX2.
    • Tier 3 (Pure Python Fallback): Degradación elegante transparente en NumPy/Python estándar si no se dispone de extensiones compiladas en el entorno local.
  2. Cero Cold-Start con Modelos Base Pre-horneados:

    • Eliminación del retraso de inicialización sintética (de ~5.500 ms a < 60 ms) mediante el artefacto comprimido app/resources/base_models.joblib (601 KB), pre-entrenado con semilla fija 42 vía scripts/prebake_models.py.
    • Carga instantánea de ventilation (regresión logística), ph_correction (MLPClassifier) y anomaly (IsolationForest de 150 árboles).
  3. Pipeline de Series Temporales con Polars:

    • ReadingStore.load_df: Ingesta directa desde SQLite a pl.DataFrame mediante pl.read_database, eliminando la creación de tuplas intermedias en memoria de Python.
    • quality.assess_polars: Expresiones pl.LazyFrame vectorizadas para verificación física IQR en paralelo sobre miles de registros.
    • Vectorización de cálculo de pendientes temporales (_slopes) para ventanas móviles de 30 minutos.
  4. Adaptación de Bajo Rango (LoRA) por Especie en NumPy:

    • Implementación de LowRankCropAdapter ($W = W_0 + \frac{\alpha}{r} B \cdot A$ con rango $r \in [2, 4]$) para actualización reactiva en memoria por especie en $&lt; 0.2\text{ ms}$, reservando GridSearchCV únicamente para ventanas offline periódicas de baja frecuencia.

Resumen de Benchmarks de Rendimiento

Mediciones auditadas en entorno de producción local mediante scripts/benchmark_performance.py:

Componente / Métrica Implementación Anterior (Python puro) Implementación Optimizada (C++20 / Cython / LoRA) Mejora / Factor
Núcleo C++20 / Cython ($p_{99}$) 2.50 ms 47.2 µs (0.047 ms) 53x más rápido
Arranque en Frío (Cold-Start) 5,537 ms 57.5 ms 96x más rápido (-98.9%)
Control de Calidad DQS (20,000 filas) 185 ms 4.31 ms (C++20) / 36.4 ms (Polars) 43x más rápido
Adaptación Online LoRA ($p_{99}$) 15,000–35,000 ms (GridSearch) 0.189 ms (188 µs) > 100,000x más rápido
Throughput de Inferencia Global ~18 req/s 87 req/s 4.8x mayor rendimiento

Contrato

Todas las rutas /v1 exigen Authorization: Bearer <SMARTPOT_AI_TOKEN>.

Método Ruta Descripción
GET /health Público. {"status":"UP","models":"READY","learning":"PERSISTENT"}
POST /v1/insights Evalúa una lectura
POST /v1/fleet Analiza todos los cultivos de una cuenta
GET /v1/crop-profiles Base de conocimiento por especie
GET /v1/models Exactitud de los modelos base
GET /v1/engine Telemetría, versión y optimizaciones SIMD del motor nativo en C++20
POST /v1/learning/readings Recibe hasta 2000 lecturas reales por lote
GET /v1/learning/status Lecturas, calidad, comparación de modelos, estados y detector de atípicos por especie
POST /v1/learning/train Entrena ya una especie ({"cropType":"LETTUCE"}) o las que tienen datos nuevos
DELETE /v1/learning/crops/{cropId} Olvida las lecturas de un cultivo eliminado
{
  "cropType": "TOMATO",
  "measures": {"temperature": 31, "humidity": 55, "ph": 6.1, "tds": 1600, "soilMoisture": 45, "brightness": 700},
  "history": [],
  "actuators": ["WATER_PUMP", "FAN", "UV_LIGHT"],
  "localHour": 14,
  "placement": {"setting": "OUTDOOR", "exposure": "FULL_SUN"},
  "weather": {"temperature": 24.4, "humidity": 63, "radiation": 520, "precipitation": 0, "isDay": true}
}

Cada elemento de history puede traer measuredAt (ISO 8601); con al menos 6 lecturas que abarquen 20 minutos se calculan los pronósticos.

{"forecasts": [{"parameter": "soilMoisture", "trend": "FALLING", "slopePerHour": -6.0, "hoursToLimit": 0.7, "limit": "MIN",
  "message": "La humedad del sustrato baja 6 % por hora: llegará al mínimo (60 %) en unos 40 minutos."}]}

La respuesta trae health (index, level, label y byParameter, la salud de cada variable que explica el índice), forecasts, diagnosis, conclusions (con su certeza), predictions, placement (el consejo de lugar), actions (actuator, action, durationSeconds, reason) y un summary como: «Tu tomate está en estado "Saludable" (79/100). Revisa la humedad del sustrato y la temperatura. El asistente propone 2 acciones.»

Motor Nativo de Alto Rendimiento en C++20

SmartPot-AI incorpora un motor de aceleración numérica directa en C++20 (src/native/) diseñado para maximizar el rendimiento, reducir el consumo de memoria y garantizar latencia sub-milisegundo:

  • Estimador Theil-Sen Optimizado ($O(M)$ lineal): sustituye la ordenación completa y matrices temporales de NumPy (np.triu_indices) por selección lineal mediante std::nth_element, logrando entre 3.6x y 50x de aceleración con huella de memoria nula.
  • Inferencia Difusa Sugeno Vectorizada: funciones de pertenencia trapezoidal sin saltos condicionales (branchless), evaluación de grado de verdad y ponderación agronómica con constantes en tiempo de compilación (constexpr).
  • Control de Calidad de Datos (IQR): análisis de completitud, validez física y descarte de espigas atípicas mediante percentiles en tiempo lineal sobre lotes de hasta 20 000 lecturas.
  • Transformación de Características y Codificación Circular: normalización vectorial y cálculo trigonométrico continuo de hora solar ($\sin$, $\cos$).
  • Arquitectura de C ABI y Fallback Resiliente: enlace dinámico mediante ctypes (app/engine/native_bridge.py) con tipos estructurados y degradación elegante a Python estándar en entornos sin compilador.
  • Observabilidad: consulta de estado en GET /v1/engine.

Compilación del Motor Nativo

  • Linux / Docker: make -C src/native (genera app/native/libsmartpot_core.so con -O3 -fPIC -std=c++20).
  • Windows (MSVC): ejecutar src\native\build.bat (genera app\native\smartpot_core.dll con /std:c++20 /O2 /LD).
  • Multiplataforma (CMake):
    cmake -B src/native/build src/native
    cmake --build src/native/build --config Release

Guía de Instalación

Despliegue en un comando

La imagen es pública: ghcr.io/smartpottech/smartpot-ai. La plataforma completa, con este servicio incluido, se levanta con un solo comando y sin descargar el código:

curl -fsSL https://raw.githubusercontent.com/SmartPotTech/.github/main/docker/demo/compose.yaml | docker compose -f - up -d --wait

Abre http://localhost:5173 e ingresa con demo@smartpot.app / SmartPot2026. Se detiene con docker compose -p smartpot-demo down (con -v borra también los datos). Más detalle en la demo. El mismo servicio corre en la demo beta del stack nuevo: cambia demo por demo-beta en la URL y en el nombre del proyecto.

Requisitos Previos

  • uv (instala Python 3.13 si hace falta)

Desarrollo

cp .env.example .env    # define SMARTPOT_AI_TOKEN (mínimo 24 caracteres)
uv sync
uv run uvicorn app.main:app --reload --port 8000

Con DOCS_ENABLED=true la documentación interactiva queda en http://localhost:8000/docs.

Pruebas

uv run ruff check .
uv run pytest

Cubren la base de conocimiento, el encadenamiento de reglas, la monotonía del índice difuso, la exactitud mínima de los modelos, las decisiones del agente, la lluvia y el sensor frente al clima, el consejo de lugar, el contrato HTTP y el aprendizaje continuo: seudonimización, poda, calidad de datos, etiquetas, modelos que superan a la línea base, campeón y retador, persistencia y la respuesta learning.

Imagen Docker

docker build -t smartpot-ai .
docker pull ghcr.io/smartpottech/smartpot-ai:latest

La imagen instala las dependencias con uv en una etapa aparte, corre como el usuario 1000 y admite sistema de archivos de solo lectura. Monta un volumen en /data para conservar lo aprendido; sin él, el aprendizaje funciona en memoria y se pierde al reiniciar.

Cada cambio en main pasa por el CI, publica la imagen en GHCR (y en Docker Hub como réplica cuando el repositorio tiene credenciales) y pide el despliegue al workflow central de SmartPotTech/.github, que actualiza producción de a uno y verifica /health.

Documentación

El asistente es un servicio interno: la API le pregunta y aplica sus respuestas. Su documentación propia está en docs/ (también en DOCX y PDF), con sus diagramas en docs/diagrams: el general del componente y los de la evaluación, el aprendizaje continuo y el análisis de flota. La documentación técnica explica la base de conocimiento, las 21 reglas, el consejo de lugar, el índice difuso, el pronóstico, el análisis de flota y el aprendizaje continuo. Los diagramas generales muestran la plataforma completa en una sola imagen ampliable:

  • Decisión de la IA: de la lectura a la orden: diagnóstico, pronóstico, modelos, reglas, índice difuso y agente
  • Linaje de los datos: cómo llegan las lecturas de los cultivos reales al aprendizaje y qué se guarda
  • Máquinas de estado: los estados del aprendizaje de cada especie

Hoja de Ruta Industrial: Migración In-Place a Rust 2024 Edition

Como parte del Plan Maestro de Maximización del Stack B (demo-beta), SmartPot-AI evoluciona in-place hacia un binario 100% nativo en Rust 2024 Edition con #![forbid(unsafe_code)] en la lógica de negocio y mimalloc como allocator global:

  1. Servidor HTTP y gRPC Dual:
    • axum 0.8: Preserva la compatibilidad 1:1 con todas las rutas REST JSON públicas (/health, /v1/insights, /v1/fleet, /v1/crop-profiles, /v1/models, /v1/engine).
    • tonic: Servidor gRPC de alto rendimiento sobre socket UNIX /var/run/smartpot/ai.sock (mononodo / demo-beta) con fallback transparente a TCP interno.
  2. Núcleo Físico-Agronómico SIMD (core::simd / wide):
    • VPD Foliar Psicrométrico: Ecuación de Tetens/Buck con offset radiativo foliar ($\Delta T_{\text{leaf}} = -1.5^\circ\text{C}$).
    • EKF 1D: Filtro de Kalman Extendido unidimensional para desacoplar el ruido electromagnético de relés y bombas en pH, TDS y temperatura.
    • Theil-Sen $O(M)$ y Sugeno Branchless: Portados a registros f64x4 con paralelismo a nivel de instrucción.
  3. Sistema Experto Compilado en Bitsets u64:
    • Codificación de hechos agronómicos en máscaras de bits (TempHigh, VpdCritical, PhAcidicDrift, MoistureDepleting).
    • Evaluación atómica de las 21 reglas mediante (facts & rule.mask) == rule.mask en $&lt; 200\text{ ns}$.
  4. Motor ML Zero-Copy y Hot-Reload Atómico:
    • Evaluación de árboles con tract-onnx puro (eliminando dlopen de bibliotecas C dinámicas, Treelite y deserialización pickle).
    • Tensores LoRA y centroides mapeados en memoria mediante rkyv (memmap2).
    • Hot-reload atómico lock-free con arc_swap::ArcSwap<ModelBundle> previa verificación de hash BLAKE3 y firma Ed25519 ante eventos Valkey Pub/Sub (smartpot:ai:reload).
    • Control Predictivo Basado en Modelos (MPC) para el cálculo de duración de actuación.

Licencia

Este proyecto está bajo la licencia MIT. Consulta el archivo LICENSE para más detalles.

About

Asistente de IA de SmartPot: sistema experto, lógica difusa, ML y agente reactivo

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages