import os import openai import sqlite3 from fastapi import FastAPI from dotenv import load_dotenv from pydantic import BaseModel from llama_index.llms.openai import OpenAI from llama_cloud import ChatMessage, MessageRole from llama_index.core.tools import FunctionTool from llama_index.agent.openai import OpenAIAgent from fastapi.middleware.cors import CORSMiddleware load_dotenv() # Configuración de la API Key de OpenAI y base_url API_KEY = os.getenv("OPENAI_API_KEY") MODEL = os.getenv("OPENAI_MODEL") BASE_URL = os.getenv("OPENAI_BASE_URL") DB_PATH = "./anhelados.db" # Crear una instancia de cliente ajustada para usar OpenAI openai.api_key = API_KEY client = openai.OpenAI(api_key=API_KEY, base_url=BASE_URL) class ArithmeticOperations: @staticmethod def multiply(a: int, b: int) -> int: return a * b @staticmethod def add(a: int, b: int) -> int: return a + b @staticmethod def subtract(a: int, b: int) -> int: return a - b @staticmethod def divide(a: int, b: int) -> int: return a / b class SQLExecutor: @staticmethod def query(sql_query: str): """ Ejecuta una consulta SQL y devuelve los resultados. # Cualquier consulta SQL que generes debe resumir tu solicitud en una sola consulta, ejemplo, si deseas saber la cantidad de insumos que tienes en tu almacén debes hacer un conteo de los insumos, en el caso de produccion de las maquinas debes resumir de igual manera la consulta todo con el fin de que la respuesta sea precisa. """ with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() cursor.execute(sql_query) return cursor.fetchall() # Creación del Agente utilizando la API de OpenAI multiply_tool = FunctionTool.from_defaults(fn=ArithmeticOperations.multiply) add_tool = FunctionTool.from_defaults(fn=ArithmeticOperations.add) subtract_tool = FunctionTool.from_defaults(fn=ArithmeticOperations.subtract) divide_tool = FunctionTool.from_defaults(fn=ArithmeticOperations.divide) sql_tool = FunctionTool.from_defaults(fn=SQLExecutor.query) estructura_base_de_datos = ChatMessage( role=MessageRole.USER, content="La base de datos tiene esta estructura SQLite: 1. almacen: ID_Almacen, ID_Insumo, Cantidad_Actual, Cantidad_Minima, Referencia: insumos (ID_Insumo), 2. clientes: ID_Proveedor, Nombre, Contacto, Direccion, 3. detalle_pedidos: ID_Pedido, ID_Insumo, Cantidad, Costo_Unitario, Referencias: pedidos_proveedor (ID_Pedido), insumos (ID_Insumo), 4. detalle_ventas: ID_Venta, ID_Producto, Cantidad, Precio_Unitario, Referencias: ventas (ID_Venta), productos (ID_Producto), 5. empleados: ID_Empleado, Nombre, Apellido, Sueldo, Fecha_Inicio, 6. gastos: ID_Gasto, Tipo, Monto, Fecha, 7. gastos_imprevistos: ID_Gasto_Imprevisto, Descripcion, Monto, Fecha,8. insumos: ID_Insumo, Descripcion, Tipo, Costo, Cantidad, 9. maquinas: ID_Maquina, Tipo, Capacidad, Consumo_Energetico, 10. pedidos_proveedor: ID_Pedido, ID_Proveedor, Fecha, Total, Referencia: clientes (ID_Proveedor), 11. produccion: ID_Produccion, ID_Maquina, Fecha, Cantidad_Producida, Referencia: maquinas (ID_Maquina), 12. productos: ID_Producto, Nombre, Precio, 13. registro_energetico: ID_Registro, ID_Maquina, Fecha, Consumo, Referencia: maquinas (ID_Maquina), 14. ventas: ID_Venta, Fecha, ID_Empleado, Total, Referencia: empleados (ID_Empleado)", additional_kwargs={"tool": "sql_tool"}, ) llm = OpenAI(model=MODEL, api_client=client) agent = OpenAIAgent.from_tools( [sql_tool, multiply_tool, add_tool, subtract_tool, divide_tool], llm=llm, verbose=True, chat_history=[estructura_base_de_datos], system_prompt="Eres un asistente super amable te llamas Chispitas y asistes a la empresa Anhelados, siempre saludas, brindas información puntual y aqui te brindo datos para solucionar consultas del usuario, Ubicaciones en Lima, Perú: San Isidro, Miraflores, Surco y La Molina con horarios de Atencion de 9 AM a 10 PM. Ofrece helados artesanales, milkshakes, postres y bebidas. Promociones regulares y servicio de delivery disponible. Locales Específicos: San Isidro: Av. Javier Prado Este 1234, Tel: (01) 123-4567. Miraflores: Calle Alcanfores 567, Tel: (01) 234-5678. Surco: Av. Caminos del Inca 890, Tel: (01) 345-6789. La Molina: Av. La Molina 345, Tel: (01) 456-7890. Productos Destacados: Helados clásicos como vainilla, chocolate y fresa. Especialidades como lúcuma, maracuyá y chirimoya. Opciones veganas y gourmet. Promociones: 2x1 en helados clásicos los martes. Descuentos en helados gourmet al comprar 3 litros. Servicios Adicionales: Delivery y pedidos personalizados para eventos. Reservas para cumpleaños y reuniones. Siempre termina con un mensaje de agradecimiento por la preferencia.", ) def ask_agent(question): response = agent.chat(question) print(response) return str(response) app = FastAPI( title="API de la heladería Anhelados", description="Esta es la API de ChatBot de la microempresa Anhelados, que ofrece helados artesanales, milkshakes, postres y bebidas.", version="3.2.8", openapi_url="/anhelados-openapi.json", docs_url="/anhelados-docs", redoc_url="/anhelados-redoc", contact={ "name": "Anhelados", "url": "https://www.anhelados.com", "email": "contacto@anhelados.com", }, license_info={"name": "MIT", "url": "https://opensource.org/licenses/MIT"}, ) # CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) class Item(BaseModel): question: str @app.post("/chat/") async def chat(item: Item): response = ask_agent(item.question) return {"response": response} # uvicorn main:app --host localhost --port 7860 --reload