API para Detectar Texto con Inteligencia Artificial 🔍

¿Alguna vez has necesitado detectar automáticamente cuando alguien menciona ciertas frases clave en un texto? En este artículo, te presento mi más reciente proyecto: una API inteligente que utiliza la potencia de OpenAI para detectar frases específicas en textos, incluso cuando estas no aparecen exactamente igual.

Descripción del Proyecto

Esta API implementa un sistema que detecta frases clave predefinidas dentro de mensajes de texto. Su función principal es analizar si un texto contiene ciertas frases específicas, incluso cuando estas no aparecen exactamente igual (reconoce variaciones y similitudes). Utiliza FastAPI como framework backend y OpenAI GPT para el análisis inteligente de texto.

Esencialmente, es un "disparador" que se activa cuando encuentra coincidencias entre las frases que estás buscando y el texto que envía un usuario.

Características principales ✨

Tecnologías utilizadas 🛠️

¿Cómo funciona? 🔍

Definición de frases clave
Envío de texto a analizar
Análisis con OpenAI
Respuesta con coincidencia

Flujo de operación detallado:

  1. El administrador define una lista de frases clave a detectar
  2. Un usuario envía un texto a través de la API
  3. El sistema normaliza tanto las frases clave como el texto del usuario
  4. Se configura OpenAI con las frases clave como posibles respuestas
  5. Se envía el texto del usuario al modelo de OpenAI
  6. El modelo analiza si alguna frase clave está presente en el texto
  7. Se devuelve el resultado indicando si se detectó alguna coincidencia

Estructura del código 📁

Vamos a revisar los componentes principales del proyecto:

Esquema de datos (schemas.py)

schemas.py
from pydantic import BaseModel
from typing import List

class TriggerRequest(BaseModel):
    frases_clave: List[str]  # Lista de frases clave proporcionadas por el ADMIN
    user_prompt: str  # Texto enviado por el cliente

Punto de entrada principal (main.py)

main.py
import uvicorn
from fastapi import FastAPI, status
from schemas import TriggerRequest
from scrips import get_tools, get_weather_completion

app = FastAPI()

@app.get("/")
def root():
    return {"Bienvendos al actuvador de texto", status.HTTP_200_OK }

@app.post("/activate-trigger/")
async def activate_text(request: TriggerRequest):
    # Normalizar las frases clave para comparación (minúsculas y sin espacios extra)
    frases_clave_normalizadas = [frase.lower().strip() for frase in request.frases_clave]
    # Normalizar el texto del usuario para comparación
    texto_usuario = request.user_prompt.lower().strip() 

    # 1. Pasamos las frases clave al sistema de OpenAI y esperamos la respuesta
    response_get = await get_tools(frases_clave_normalizadas)

    # si no se obtiene respuesta de OpenAI se retorna un error y un status 500
    if not response_get:
        return {
            "error": "No se pudo obtener la respuesta de OpenAI",
            "status": status.HTTP_500_INTERNAL_SERVER_ERROR
        }
    
    # 2. Si se obtiene una respuesta de la configuracion de OpenAI, se envia la respuesta 
    # al model de openai con el texto del usuario, para detectar el disparador
    response = await get_weather_completion(texto_usuario, response_get)

    return {
        "frases_claves": frases_clave_normalizadas,
        "texto_del_usuario": request.user_prompt,
        "respuesta": response,
        "status": status.HTTP_200_OK
    }

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.2", port=8000)

Interacción con OpenAI (scrips.py)

scrips.py
import openai, json, os
from dotenv import load_dotenv

load_dotenv('.env.dev')
openai.api_key = os.getenv("API_KEY_OPENAI")

# Definir herramientas/funciones con descripción precisa
async def get_tools(arguments): # los argumentos son las frases clave
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_confirmation",
                "description": "Confirmación explícita de comparar usando frases específicas",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "confirmation": {
                            "type": "string",
                            "enum": arguments, # Lista de frases clave enviadas por el ADMIN
                            "description": "Frase exacta de confirmación"
                        },
                    },
                    "required": ["confirmation"],
                }
            }
        }
    ]
    return tools

# Función para verificar confirmaciones de compra
def get_confirmation(confirmation, enum):
    """Validar y procesar confirmación de compra."""
    if confirmation.lower() in enum:
        return f"🎉 Frase encontrada  👱🏽‍♂️ ' {confirmation} ' 👱🏽‍♂️, estado {True}"
    else:
        return "❌ Confirmación no válida"

# Función asíncrona para manejar la solicitud de OpenAI
async def get_weather_completion(texto_usuario, config_get_tools):
    datos = config_get_tools[0]['function']['parameters']['properties']['confirmation']['enum']
    
    message = """Eres un asistente especializado en identificar intenciones basadas en frases clave. 
    Tu tarea es: 1. Analizar si las frases clave están presentes en el mensaje del usuario 2. Realizar una búsqueda flexible que contemple: 
    - Coincidencia parcial de palabras 
    - Contexto de la frase 
    Instrucciones específicas: 
    - Si encuentras una coincidencia, confirma la detección
    - Ignora tildes y diferencias menores en la escritura 
    - Busca la intención aunque la frase no sea exactamente igual
    - Si la frase no coincide, indica que no se detectó la intención
    Ejemplo:
    - Frases clave: {datos} - Casos válidos: * "hoy quiero sopa" * "tengo ganas de una sopa" * "Sopa, por favor" * "Sopa", Responde de manera concisa, indicando si detectaste o no la intención.')"""

    try:
        # Crear solicitud a OpenAI
        completion = await openai.ChatCompletion.acreate(
            model="gpt-3.5-turbo-0125",
            messages=[
                {
                "role": "system",
                "content":  message
                }, 
                {
                "role": "user",
                "content": texto_usuario
            }],

            functions=[config_get_tools[0]['function']],
            function_call="auto", # Let the model decide
            max_tokens=250,
        )
        
        response = completion.choices[0].message

        # Verificar si se llamó a la función
        if response.get("function_call"):
            tool_call = response["function_call"]

            if tool_call["name"] == "get_confirmation":
                args = json.loads(tool_call["arguments"])
                # estos argumentos son los que se pasan a la función get_confirmation
                confirmation = args.get("confirmation")
                
                if confirmation:
                    # pasamos los argumentos que ya estaban en la función get_confirmation
                    valid_confirmations = config_get_tools[0]['function']['parameters']['properties']['confirmation']['enum']
                    result = get_confirmation(confirmation, valid_confirmations)
                    return result
                else:
                    return "❌ No se proporcionaron argumentos válidos."

        return False
    except Exception as e:
        return None

Ejemplo de uso 📝

Solicitud:

ejemplo_solicitud.py
import requests
import json

url = "http://127.0.0.2:8000/activate-trigger/"

payload = json.dumps({
  "frases_clave": ["que sea sopa", "que feo arroz", "hoy no trabaje"],
  "user_prompt": "Hoy quiero que sea sopa para el almuerzo"
})
headers = {
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

Respuesta:

resultado.json
{
  "frases_claves": ["que sea sopa", "que feo arroz", "hoy no trabaje"],
  "texto_del_usuario": "Hoy quiero que sea sopa para el almuerzo",
  "respuesta": "🎉 Frase encontrada 👱🏽‍♂️ 'que sea sopa' 👱🏽‍♂️, estado True",
  "status": 200
}

Aplicaciones prácticas 💼

Esta API puede ser utilizada en diversos escenarios:

Mejoras potenciales 🚀

Algunas mejoras que planeo implementar en el futuro:

  1. Caché de respuestas: Implementar un sistema de caché para frases frecuentes y mejorar el rendimiento
  2. Análisis de sentimiento: Añadir detección de tono y emoción en el texto
  3. Personalización avanzada: Permitir configurar la sensibilidad de la detección
  4. Soporte multilingüe: Añadir detección en otros idiomas además del español
  5. Dashboard de análisis: Crear una interfaz para visualizar patrones de uso y estadísticas

Conclusión

Esta API representa una solución elegante para la detección de frases clave en textos, aprovechando la potencia de la inteligencia artificial de OpenAI. La combinación de FastAPI y GPT permite crear un sistema robusto y flexible que puede adaptarse a diversas necesidades.

Si estás interesado en implementar esta solución o tienes preguntas sobre el proyecto, no dudes en contactarme a través de mi GitHub o LinkedIn.

"La verdadera inteligencia no está en encontrar respuestas exactas, sino en entender la intención detrás de las palabras." — Jhordan Solis