Este servicio autonomo de temperatura y humedad utiliza un circuito autonomo de bajo costo para dar servicio independiente sin necesidad de supervision con paneles solares, baterias, microprocesadores y sensores. El esquema electrico es un prototipo testeado y funcionando correctamente.
Programa para trabajar con un LLM gratuito de HuggingFace tuilizando Space:
import gradio as gr
import pandas as pd
import io
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from huggingface_hub import InferenceClient
import os
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain.schema import Document
# Configuración del modelo de embeddings
embedding_model = "sentence-transformers/all-MiniLM-L6-v2"
embeddings = HuggingFaceEmbeddings(model_name=embedding_model)
# Configuración del cliente de inferencia en Hugging Face
hf_token = os.getenv("HF_API_TOKEN")
client = InferenceClient("microsoft/Phi-3-mini-4k-instruct", token=hf_token)
# Ruta al archivo JSON de credenciales de la cuenta de servicio de Google.
SERVICE_ACCOUNT_FILE = 'asistente-7687676-uzg675765uz.json'
# ID del archivo en Google Drive
file_id = '1tiuhihi_htioorhizohktfgizhjorizhjrkotfgokhjrt' # Reemplaza esto con el ID de tu archivo de Google Drive
# Autenticación y configuración de Google Drive API
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE,
scopes=["https://www.googleapis.com/auth/drive"]
)
drive_service = build('drive', 'v3', credentials=credentials)
def cargar_excel():
"""Descarga y carga el archivo de Google Sheets en formato Excel y lo procesa para construir una base de datos vectorial."""
try:
# Descargar el archivo de Google Sheets en formato .xlsx
request = drive_service.files().export_media(fileId=file_id, mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while not done:
status, done = downloader.next_chunk()
print(f"Descarga {int(status.progress() * 100)}% completada.")
fh.seek(0)
# Cargar el archivo Excel en un DataFrame
df = pd.read_excel(fh)
# Combina todas las celdas en un solo texto y crea objetos Document
data = [Document(page_content=" ".join(df.astype(str).values.flatten()))]
# Divide el contenido en fragmentos
text_splitter = RecursiveCharacterTextSplitter(chunk_size=7500, chunk_overlap=100)
chunks = text_splitter.split_documents(data)
# Crear la base de datos de vectores con embeddings
vector_db = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
collection_name="excel-rag"
)
return vector_db, "Archivo de Excel descargado y procesado exitosamente."
except Exception as e:
return None, f"Error al descargar o procesar el archivo: {str(e)}"
def responder(pregunta):
"""Genera una respuesta basada en la pregunta del usuario, reconstruyendo la base de datos de vectores para obtener los datos actualizados."""
# Borra y recarga la base de datos vectorial
global vector_db
vector_db, status_message = cargar_excel()
if not vector_db:
return status_message
try:
# Recuperar el contexto relevante desde la base de datos de vectores
retriever = vector_db.as_retriever()
retrieved_docs = retriever.get_relevant_documents(pregunta)
# Construir el contexto a partir de los documentos recuperados
context = "\n".join([doc.page_content for doc in retrieved_docs])
# Construir el prompt para el LLM, destacando la pregunta del usuario
prompt_text = f"Contexto relevante:\n{context}\n\nPregunta del usuario: {pregunta}\n\nPor favor responde considerando el contexto y la pregunta."
messages = [{"role": "user", "content": prompt_text}]
# Realizar la inferencia usando el cliente de Hugging Face
response = client.chat_completion(messages=messages, max_tokens=500)
# Extraer el texto generado
if hasattr(response, 'choices') and response.choices:
generated_text = response.choices[0].message.content
else:
generated_text = str(response)
return generated_text
except Exception as e:
return f"Error al procesar la pregunta: {str(e)}"
# Configuración de la interfaz de Gradio
with gr.Blocks() as demo:
gr.Markdown("# Asistente de IA con Datos de Google Sheets (Acceso Privado)")
# Cargar el archivo de Excel automáticamente
output_text = gr.Textbox(label="Estado", value=cargar_excel()[1], interactive=False)
with gr.Tab("Chat"):
question = gr.Textbox(label="Haz una pregunta")
chat_output = gr.Textbox(label="Respuesta")
question.submit(responder, inputs=question, outputs=chat_output)
demo.launch()
El archivo requirements.txt:
pandas
openpyxl
requests
gradio
langchain
langchain_community
langchain_text_splitters
chromadb
sentence-transformers
google-api-python-client
google-auth
google-auth-oauthlib
google-auth-httplib2
El codigo que esta trabajando en la placa ESP32:
#include <Arduino.h>
#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
// Configuración del Wi-Fi
const char* ssid = "nombreWifi";
const char* password = "claveWifi";
// URL del webhook en Make.com
const char* webhook_url = "https://hook.eu2.make.com/7tzjfzjztjfzjg546456ftrghjzujzuj";
// Configuración del sensor DHT11
#define DHTPIN 33 // Pin donde se conecta el DHT11
#define DHTTYPE DHT11 // Especifica el tipo de sensor (DHT11)
#define GPIO_OUTPUT_PIN 25 // Pin que se pondrá en HIGH
DHT dht(DHTPIN, DHTTYPE); // Inicializa el sensor DHT
void setup() {
Serial.begin(115200); // Inicia la comunicación serie
dht.begin(); // Inicia el sensor DHT
WiFi.begin(ssid, password); // Conecta al Wi-Fi
// Configura el pin 25 como salida
pinMode(GPIO_OUTPUT_PIN, OUTPUT);
digitalWrite(GPIO_OUTPUT_PIN, LOW); // Asegura que el pin esté inicialmente en LOW
// Espera a la conexión
Serial.print("Conectando a Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConectado a Wi-Fi");
}
void loop() {
// Lee la temperatura y la humedad del DHT11
float temperatura = dht.readTemperature();
float humedad = dht.readHumidity();
// Comprueba si las lecturas son correctas
if (isnan(temperatura) || isnan(humedad)) {
Serial.println("Error al leer el sensor DHT11");
} else {
// Muestra la temperatura y la humedad en el terminal
Serial.print("Temperatura: ");
Serial.print(temperatura);
Serial.println("°C");
Serial.print("Humedad: ");
Serial.print(humedad);
Serial.println("%");
// Enviar datos al webhook si estamos conectados a Wi-Fi
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(webhook_url); // Inicia la conexión con el webhook
http.addHeader("Content-Type", "application/json"); // Configura el tipo de contenido
// Crea el payload en formato JSON
String payload = "{\"temperatura\": " + String(temperatura, 2) + ", \"humedad\": " + String(humedad, 2) + "}";
// Envía una solicitud POST al webhook con el payload
int httpResponseCode = http.POST(payload);
// Verifica la respuesta
if (httpResponseCode > 0) {
String response = http.getString();
Serial.print("Respuesta del servidor: ");
Serial.println(response);
// Espera 3 segundos
delay(3000);
// Establece el pin 25 en HIGH
digitalWrite(GPIO_OUTPUT_PIN, HIGH);
Serial.println("Pin 25 en HIGH");
} else {
Serial.print("Error en la solicitud POST: ");
Serial.println(httpResponseCode);
}
http.end(); // Finaliza la conexión
} else {
Serial.println("No hay conexión a Wi-Fi.");
}
}
// Espera 10 segundos antes de la próxima lectura y envío de datos
delay(10000);
// Restablece el pin 25 a LOW después del intervalo
digitalWrite(GPIO_OUTPUT_PIN, LOW);
}
Archivo platformio de VSCode:
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
lib_deps =
adafruit/DHT sensor library @ ^1.4.2
adafruit/Adafruit Unified Sensor @ ^1.1.4
upload_speed = 115200
monitor_speed = 115200
Deja una respuesta Cancelar la respuesta