¿Cómo construir un chatbot PDF sin Langchain?

Crear chatbot PDF sin Langchain

Introducción

Desde el lanzamiento de Chatgpt, el ritmo de progreso en el espacio de la IA no muestra signos de desaceleración, cada día se están desarrollando nuevas herramientas y tecnologías. Seguro, es algo genial para las empresas y el espacio de la IA en general, pero como programador, ¿necesitas aprender todas ellas para construir algo? Bueno, la respuesta es No. Un enfoque bastante pragmático sería aprender sobre las cosas que necesitas. Hay muchas herramientas y tecnologías que prometen hacer las cosas más fáciles, y hasta cierto punto lo hacen. Pero también a veces no las necesitamos en absoluto. El uso de grandes frameworks para casos de uso simples solo termina haciendo que tu código sea un desorden inflado. Entonces, en este artículo, vamos a explorar construyendo un chatbot de PDF CLI sin langchain y entender por qué no siempre necesitamos frameworks de IA.

Objetivos de Aprendizaje

  • Por qué no necesitas frameworks de IA como Langchain y Llama Index.
  • Cuándo necesitas frameworks.
  • Aprender sobre Bases de Datos de Vectores e Indexación.
  • Construir un chatbot de preguntas y respuestas (Q&A) en línea de comandos desde cero en Python.

Este artículo fue publicado como parte del Data Science Blogathon.

¿Puedes prescindir de Langchain?

En los últimos meses, frameworks como Langchain y LLama Index han experimentado un aumento notable en popularidad, principalmente debido a su excepcional capacidad para facilitar el desarrollo conveniente de aplicaciones LLM por parte de los desarrolladores. Pero para muchos casos de uso, estos frameworks pueden ser excesivos. Es como llevar un lanzacohetes a una pelea de pistolas.

Vienen con cosas que pueden no ser necesarias en tu proyecto. Python ya es famoso por ser inflado. Además, agregar dependencias que apenas necesitas solo hará que tu entorno sea más desordenado. Un caso de uso como este es la consulta de documentos. Si tu proyecto no involucra a un agente de IA u otras cosas complicadas similares, puedes prescindir de Langchain y crear el flujo de trabajo desde cero, reduciendo así el bloat innecesario. Además, los frameworks como Langchain o Llama Index están en desarrollo rápido; cualquier refactorización de código podría romper tu compilación.

¿Cuándo necesitas Langchain?

Si tienes una necesidad de alto nivel, como construir un agente para automatizar software complicado, o proyectos que requieren horas de ingeniería más largas para construir desde cero, tiene sentido utilizar soluciones preconstruidas. Nunca reinventes la rueda, a menos que necesites una rueda mejor. Hay muchos otros ejemplos donde usar soluciones prefabricadas con pequeños ajustes tiene mucho sentido.

Construyendo un Chatbot de Preguntas y Respuestas (Q&A)

Uno de los casos de uso más buscados de los LLMs ha sido la pregunta y respuesta de documentos. Y después de que OpenAI hizo públicos sus puntos finales de ChatGPT, se ha vuelto mucho más fácil construir un bot conversacional interactivo con cualquier fuente de datos de texto. En este artículo, construiremos una aplicación CLI de Q&A LLM desde cero. Entonces, ¿cómo abordamos el problema? Antes de construirlo, entendamos lo que necesitamos hacer.

Un flujo de trabajo típico implicará

  • Procesar el archivo PDF proporcionado para extraer los textos.
  • También debemos tener cuidado con la ventana de contexto del LLM. Entonces, necesitamos dividir esos textos en fragmentos.
  • Para consultar fragmentos relevantes de texto, necesitamos obtener embeddings de esos fragmentos de texto. Para esto, necesitamos un modelo de embedding. Para este proyecto, utilizaremos el modelo Huggingface MiniLM-L6-V2, puedes usar cualquier modelo que desees, como OpenAI, Cohere o Google Palm.
  • Para almacenar y recuperar embeddings, utilizaremos una base de datos de vectores como Chroma. Hay muchas bases de datos de vectores diferentes entre las que puedes optar, como Qdrant, Weaviate, Milvus y muchas más.
  • Cuando un usuario envía una consulta, se convertirá en embeddings por el mismo modelo, y se buscarán los fragmentos con un significado similar a la consulta.
  • Los fragmentos recuperados se concatenarán con la consulta al final y se enviarán al LLM a través de una API.
  • La respuesta obtenida del modelo se devolverá al usuario.

Todas estas cosas requerirán una interfaz de usuario. Para este artículo, construiremos una simple Interfaz de Línea de Comandos (CLI) con Python Argparse.

Aquí hay un diagrama de flujo de nuestro chatbot CLI:

Antes de entrar en la parte de programación, vamos a entender un par de cosas sobre las bases de datos y los índices vectoriales.

¿Qué son las bases de datos y los índices vectoriales?

Como su nombre indica, las bases de datos vectoriales almacenan vectores o embeddings. Entonces, ¿por qué necesitamos bases de datos vectoriales? Construir cualquier aplicación de IA requiere embeddings de datos del mundo real, ya que los modelos de aprendizaje automático no pueden procesar directamente estos datos en bruto, como textos, imágenes o audio. Cuando estás lidiando con una gran cantidad de estos datos que se utilizarán repetidamente, necesitarán ser almacenados en algún lugar. Entonces, ¿por qué no podemos usar una base de datos tradicional para esto? Bueno, puedes usar bases de datos tradicionales para tus necesidades de búsqueda, pero las bases de datos vectoriales ofrecen una ventaja significativa: pueden realizar una búsqueda de similitud vectorial además de la búsqueda léxica.

En nuestro caso, cada vez que un usuario envíe una consulta, la base de datos vectorial realizará una búsqueda de similitud vectorial en todos los embeddings y buscará los K vecinos más cercanos. El mecanismo de búsqueda es súper rápido, ya que utiliza un algoritmo llamado HNSW.

HNSW significa Hierarchical Navigable Small World. Es un algoritmo basado en gráficos y un método de indexación para la búsqueda del vecino más cercano aproximado (ANN). ANN es un tipo de búsqueda que encuentra los k elementos más similares a un elemento dado.

HNSW funciona construyendo un grafo de los puntos de datos. Los nodos en el grafo representan los puntos de datos, y las aristas en el grafo representan la similitud entre los puntos de datos. Luego, el grafo se recorre para encontrar los k elementos más similares al elemento dado.

El algoritmo HNSW es rápido, confiable y escalable. La mayoría de las bases de datos vectoriales utilizan HNSW como el algoritmo de búsqueda predeterminado.

Ahora, estamos listos para sumergirnos en los códigos.

Construir el Entorno del Proyecto

Como con cualquier proyecto de Python, comienza creando un entorno virtual. Esto mantiene el entorno de desarrollo limpio y ordenado. Consulta este artículo para elegir el entorno de Python adecuado para tu proyecto.

La estructura de archivos del proyecto es simple, tendremos dos archivos Python, uno para definir la CLI y otro para procesar, almacenar y consultar datos. Además, crea un archivo .env para almacenar tu clave de API de OpenAI.

Este es el archivo requirements.txt, instálalo antes de comenzar.

#requiremnets.txt
openai
chromadb
PyPDF2
dotenv

Ahora, importa las clases y funciones necesarias.

import os
import openai
import PyPDF2
import re
from chromadb import Client, Settings
from chromadb.utils import embedding_functions
from PyPDF2 import PdfReader
from typing import List, Dict
from dotenv import load_dotenv

Carga la clave de API de OpenAI desde el archivo .env.

load_dotenv()
key = os.environ.get('OPENAI_API_KEY')
openai.api_key = key

Funciones de Utilidad para la CLI del Chatbot

Para almacenar embeddings de texto y sus metadatos, crearemos una colección con ChromaDB.

ef = embedding_functions.ONNXMiniLM_L6_V2()
client = Client(settings = Settings(persist_directory="./", is_persistent=True))
collection_ = client.get_or_create_collection(name="test", embedding_function=ef)

Como modelo de embedding, estamos utilizando MiniLM-L6-V2 con ONNX runtime. Es pequeño pero capaz y, además, de código abierto.

A continuación, definiremos una función para verificar si una ruta de archivo proporcionada pertenece a un archivo PDF válido.

def verify_pdf_path(file_path):
    try:
        # Intenta abrir el archivo PDF en modo de lectura binaria
        with open(file_path, "rb") as pdf_file:
            # Crea un objeto lector de PDF utilizando PyPDF2
            pdf_reader = PyPDF2.PdfReader(pdf_file)
            
            # Verifica si el PDF tiene al menos una página
            if len(pdf_reader.pages) > 0:
                # Si tiene páginas, el PDF no está vacío, así que no hagas nada (pasa)
                pass
            else:
                # Si no tiene páginas, genera una excepción que indica que el PDF está vacío
                raise ValueError("El archivo PDF está vacío")
    except PyPDF2.errors.PdfReadError:
        # Maneja el caso en el que no se puede leer el PDF (por ejemplo, está corrupto o no es un PDF válido)
        raise PyPDF2.errors.PdfReadError("Archivo PDF no válido")
    except FileNotFoundError:
        # Maneja el caso en el que el archivo especificado no existe
        raise FileNotFoundError("Archivo no encontrado, verifica la dirección del archivo nuevamente")
    except Exception as e:
        # Maneja otras excepciones inesperadas y muestra el mensaje de error
        raise Exception(f"Error: {e}")

Una de las partes principales de una aplicación de preguntas y respuestas en PDF es obtener fragmentos de texto. Por lo tanto, necesitamos definir una función que nos proporcione los fragmentos de texto requeridos.

def get_text_chunks(texto: str, limite_palabras: int) -> List[str]:
    """
    Divide un texto en fragmentos con un límite de palabras especificado
    asegurando que cada fragmento contenga oraciones completas.
    
    Parámetros:
        texto (str): El texto completo que se dividirá en fragmentos.
        limite_palabras (int): El límite de palabras deseado para cada fragmento.
    
    Devuelve:
        List[str]: Una lista que contiene los fragmentos de texto con
        el límite de palabras especificado y oraciones completas.
    """
    oraciones = re.split(r'(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s', texto)
    fragmentos = []
    fragmento_actual = []

    for oracion in oraciones:
        palabras = oracion.split()
        if len(" ".join(fragmento_actual + palabras)) <= limite_palabras:
            fragmento_actual.extend(palabras)
        else:
            fragmentos.append(" ".join(fragmento_actual))
            fragmento_actual = palabras

    if fragmento_actual:
        fragmentos.append(" ".join(fragmento_actual))

    return fragmentos

Hemos definido un algoritmo básico para obtener fragmentos. La idea es permitir a los usuarios crear tantas palabras como deseen en un solo fragmento de texto. Y cada fragmento de texto terminará con una oración completa, aunque exceda el límite. Este es un algoritmo simple. Puedes crear algo por tu cuenta.

Crear un Diccionario

Ahora, necesitamos una función para cargar textos de archivos PDF y crear un diccionario para hacer un seguimiento de los fragmentos de texto pertenecientes a una sola página.

def load_pdf(archivo: str, palabra: int) -> Dict[int, List[str]]:
    # Crear un objeto PdfReader a partir del archivo PDF especificado
    lector = PdfReader(archivo)
    
    # Inicializar un diccionario vacío para almacenar los fragmentos de texto extraídos
    documentos = {}
    
    # Iterar a través de cada página en el PDF
    for num_pagina in range(len(lector.pages)):
        # Obtener la página actual
        pagina = lector.pages[num_pagina]
        
        # Extraer texto de la página actual
        textos = pagina.extract_text()
        
        # Utilizar la función get_text_chunks para dividir el texto extraído en fragmentos de longitud 'palabra'
        fragmentos_texto = get_text_chunks(textos, palabra)
        
        # Almacenar los fragmentos de texto en el diccionario documentos con el número de página como clave
        documentos[num_pagina] = fragmentos_texto
    
    # Devolver el diccionario que contiene números de página como claves y fragmentos de texto como valores
    return documentos

Colección ChromaDB

Ahora, necesitamos almacenar los datos en una colección de ChromaDB.

def add_text_to_collection(archivo: str, palabra: int = 200) -> None:
    # Cargar el archivo PDF y extraer fragmentos de texto
    docs = load_pdf(archivo, palabra)
    
    # Inicializar listas vacías para almacenar datos
    textos_docs = []  # Lista para almacenar fragmentos de texto
    ids = []  # Lista para almacenar IDs únicos
    metadatos = []  # Lista para almacenar metadatos para cada fragmento de texto
    id = 0  # Inicializar ID
    
    # Iterar a través de cada página y fragmento de texto en el PDF cargado
    for num_pagina in docs.keys():
        for doc in docs[num_pagina]:
            # Agregar el fragmento de texto a la lista textos_docs
            textos_docs.append(doc)
            
            # Agregar metadatos para el fragmento de texto, incluido el número de página
            metadatos.append({'num_pagina': num_pagina})
            
            # Agregar un ID único para el fragmento de texto
            ids.append(id)
            
            # Incrementar el ID
            id += 1

    # Agregar los datos recolectados a una colección
    collection_.add(
        ids=[str(id) for id in ids],  # Convertir IDs a cadenas
        documentos=textos_docs,  # Fragmentos de texto
        metadatos=metadatos,  # Metadatos
    )
    
    # Devolver un mensaje de éxito
    return "Se agregaron correctamente los embeddings PDF a la colección"

En Chromadb, el campo de metadatos almacena información adicional sobre los documentos. En este caso, el número de página de un fragmento de texto es su metadato. Después de extraer los metadatos de cada fragmento de texto, podemos almacenarlos en la colección que creamos anteriormente. Esto es necesario solo cuando el usuario proporciona una ruta de archivo válida a un archivo PDF.

Ahora definiremos una función que procese las consultas de los usuarios para obtener datos de la base de datos.

def query_collection(texts: str, n: int) -> List[str]:
    result = collection_.query(
                  query_texts = texts,
                  n_results = n,
                 )
    documents = result["documents"][0]
    metadatas = result["metadatas"][0]
    resulting_strings = []
    for page_no, text_chunk in zip(metadatas, documents):
        resulting_strings.append(f"Página {page_no['page_no']}: {text_chunk}")
    return resulting_strings

La función anterior utiliza un método de consulta para recuperar “n” datos relevantes de la base de datos. Luego creamos una cadena formateada que comienza con el número de página del fragmento de texto.

Ahora, lo único importante que queda es alimentar el LLM con información.

def get_response(queried_texts: List[str],) -> List[Dict]:
    global messages
    messages = [
                {"role": "sistema", "content": "Eres un asistente útil. \
                 Y siempre responderás la pregunta formulada en 'ques:' y \
                 citarás el número de página al responder cualquier pregunta, \
                 Siempre está al comienzo de la indicación en el formato 'página n'."},
                {"role": "usuario", "content": ''.join(queried_texts)}
          ]

    response = openai.ChatCompletion.create(
                            model = "gpt-3.5-turbo",
                            messages = messages,
                            temperature=0.2,               
                     )
    response_msg = response.choices[0].message.content
    messages = messages + [{"role":'asistente', 'content': response_msg}]
    return response_msg

La variable global messages almacena el contexto de la conversación. Hemos definido un mensaje del sistema para imprimir el número de página desde donde el LLM obtiene la respuesta.

Por último, la función de utilidad final combina los fragmentos de texto obtenidos con la consulta del usuario, los alimenta en la función get_response() y devuelve la cadena de respuesta resultante.

def get_answer(query: str, n: int):
    queried_texts = query_collection(texts = query, n = n)
    queried_string = [''.join(text) for text in queried_texts]
    queried_string = queried_string[0] + f"ques: {query}"
    answer = get_response(queried_texts = queried_string,)
    return answer

Hemos terminado con nuestras funciones de utilidad. Pasemos a construir la CLI.

CLI del Chatbot

Para usar el chatbot a pedido, necesitamos una interfaz. Esto podría ser una aplicación web, una aplicación móvil o una CLI. En este artículo, construiremos una CLI para nuestro chatbot. Si desea construir una aplicación web de demostración con una apariencia agradable, puede utilizar herramientas como Gradio o Streamlit. Consulte este artículo sobre la construcción de un chatbot para PDF.

Construye un ChatGPT para PDF con Langchain

Para construir una CLI, necesitaremos la biblioteca Argparse. Argparse es una biblioteca potente que le permite crear CLIs en Python. Tiene una sintaxis simple y fácil para crear comandos, subcomandos y banderas. Entonces, antes de adentrarnos en ello, aquí hay una breve introducción a Argparse.

Argparse de Python

El módulo Argparse se lanzó por primera vez en Python 3.2, proporcionando una forma rápida y conveniente de construir aplicaciones CLI con Python sin depender de instalaciones de terceros. Nos permite analizar argumentos de línea de comandos, crear subcomandos en CLIs y muchas más características, lo que lo convierte en una herramienta confiable para construir CLIs.

Aquí hay un pequeño ejemplo de Argparse en acción:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-f", "--filename", help="El nombre del archivo para leer.")
parser.add_argument("-n", "--number", help="El número de líneas para imprimir.", type=int)
parser.add_argument("-s", "--sort", help="Ordenar las líneas en el archivo.", action="store_true")

args = parser.parse_args()

with open(args.filename) as f:
    lines = f.readlines()

if args.sort:
    lines.sort()

for line in lines:
    print(line)

El método add_argument nos permite definir subcomandos con comprobaciones y equilibrios. Podemos definir el tipo de argumento o la acción que debe realizar cuando se proporciona una bandera y un parámetro de ayuda que explique el caso de uso de un subcomando en particular. El subcomando de ayuda mostrará todas las banderas y sus casos de uso.

En una nota similar, definiremos subcomandos para la CLI del chatbot.

Construyendo la CLI

Importar Argparse y las funciones de utilidad necesarias.

import argparse
from utils import (
    add_text_to_collection, 
    get_answer, 
    verify_pdf_path, 
    clear_coll
  )

Definir el analizador de argumentos y agregar los argumentos.

def main():
    # Crear un analizador de argumentos de línea de comandos con una descripción
    parser = argparse.ArgumentParser(description="Herramienta de procesamiento de PDF en línea de comandos")
    
    # Definir los argumentos de línea de comandos
    parser.add_argument("-f", "--file", help="Ruta al archivo PDF de entrada")
    
    parser.add_argument(
        "-c", "--count",
        default=200, 
        type=int, 
        help="Valor entero opcional para el número de palabras en un fragmento de texto"
    )
    
    parser.add_argument(
        "-q", "--question", 
        type=str,
        help="Hacer una pregunta"
    )
    
    parser.add_argument(
        "-cl", "--clear", 
        type=bool, 
        help="Borrar los datos de la colección existente"
    )
    
    parser.add_argument(
        "-n", "--number", 
        type=int, 
        default=1, 
        help="Número de resultados a obtener de la colección"
    )

    # Analizar los argumentos de línea de comandos
    args = parser.parse_args()

Hemos definido algunos subcomandos, como –file, –value, –question, etc.

  • –file: La ruta de cadena del archivo PDF.
  • –value: Un valor opcional que define el número de palabras en un fragmento de texto.
  • –question: Toma una consulta del usuario como parámetro.
  • — number: Número de fragmentos similares a obtener.
  • –clear: Borra la colección actual de Chromadb.

Ahora, procesamos los argumentos;

 if args.file is not None:
        verify_pdf_path(args.file)
        confirmation = add_text_to_collection(file = args.file, word = args.value)
        print(confirmation)

 if args.question is not None:
        if args.number:
            n = args.number
        answer = get_answer(args.question, n = n)
        print("Respuesta:", answer)

 if args.clear:
        clear_coll()
        return "Colección actual borrada exitosamente"

Uniendo todo.

import argparse
from app import (
    add_text_to_collection, 
    get_answer, 
    verify_pdf_path, 
    clear_coll
)

def main():
    # Crear un analizador de argumentos de línea de comandos con una descripción
    parser = argparse.ArgumentParser(description="Herramienta de procesamiento de PDF en línea de comandos")
    
    # Definir los argumentos de línea de comandos
    parser.add_argument("-f", "--file", help="Ruta al archivo PDF de entrada")
    
    parser.add_argument(
        "-c", "--count",
        default=200, 
        type=int, 
        help="Valor entero opcional para el número de palabras en un fragmento de texto"
    )
    
    parser.add_argument(
        "-q", "--question", 
        type=str,
        help="Hacer una pregunta"
    )
    
    parser.add_argument(
        "-cl", "--clear", 
        type=bool, 
        help="Borrar los datos de la colección existente"
    )
    
    parser.add_argument(
        "-n", "--number", 
        type=int, 
        default=1, 
        help="Número de resultados a obtener de la colección"
    )

    # Analizar los argumentos de línea de comandos
    args = parser.parse_args()
    
    # Verificar si se proporciona el argumento '--file'
    if args.file is not None:
        # Verificar la ruta del archivo PDF y agregar su texto a la colección
        verify_pdf_path(args.file)
        confirmation = add_text_to_collection(file=args.file, word=args.count)
        print(confirmation)

    # Verificar si se proporciona el argumento '--question'
    if args.question is not None:
        n = args.number if args.number else 1  # Establecer 'n' al número especificado o al valor predeterminado 1
        answer = get_answer(args.question, n=n)
        print("Respuesta:", answer)

    # Verificar si se proporciona el argumento '--clear'
    if args.clear:
        clear_coll()
        print("Colección actual borrada exitosamente")

if __name__ == "__main__":
    main()

Ahora abre tu terminal y ejecuta el siguiente script.

 python cli.py -f "ruta/al/archivo.pdf" -v 1000 -n 1  -q "consulta"

Para eliminar la colección, escribe

python cli.py -cl True

Si la ruta de archivo proporcionada no pertenece a un PDF, se generará un FileNotFoundError.

El repositorio de GitHub: https://github.com/sunilkumardash9/pdf-cli-chatbot

Casos de uso del mundo real

Un chatbot que se ejecuta como una herramienta de línea de comandos se puede utilizar en muchas aplicaciones del mundo real, como

Investigación académica: Los investigadores a menudo trabajan con numerosos artículos y documentos de investigación en formato PDF. Un chatbot de línea de comandos podría ayudarles a extraer información relevante, crear bibliografías y organizar sus referencias de manera eficiente.

Traducción de idiomas: Los profesionales del lenguaje pueden utilizar el chatbot para extraer texto de los PDF, traducirlo y generar documentos traducidos, todo desde la línea de comandos.

Instituciones educativas: Los profesores y educadores pueden extraer contenido de recursos educativos para crear materiales de aprendizaje personalizados o preparar contenido de cursos. Los estudiantes pueden extraer información útil de grandes PDF desde la línea de comandos del chatbot.

Gestión de proyectos de código abierto: Los chatbots de línea de comandos pueden ayudar a los proyectos de software de código abierto a gestionar la documentación, extraer fragmentos de código y generar notas de lanzamiento a partir de manuales en PDF.

Conclusión

Entonces, esto fue todo sobre la construcción de un chatbot de preguntas y respuestas en PDF con una interfaz de línea de comandos construida sin usar frameworks como Langchain y Llama Index. Aquí tienes un resumen rápido de las cosas que cubrimos.

  • Langchain y otros frameworks de IA pueden ser una excelente manera de comenzar con el desarrollo de IA. Sin embargo, es importante recordar que no son una solución milagrosa. Pueden hacer que tu código sea más complejo y pueden causar inflado, así que úsalos solo cuando los necesites.
  • El uso de frameworks tiene sentido cuando la complejidad de los proyectos requiere más horas de ingeniería si se hace desde cero.
  • Se puede diseñar un flujo de trabajo de preguntas y respuestas de documentos desde cero sin un framework como Langchain desde el primer principio.

Entonces, eso es todo. Espero que te haya gustado el artículo.

Pregunta frecuente

Los medios mostrados en este artículo no son propiedad de Analytics Vidhya y se utilizan a discreción del autor.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

La función de detección de suplantación de identidad protege a las marcas y personalidades de las cuentas falsas en las redes sociales

Una empresa canadiense ha incorporado una función de protección contra la suplantación de identidad en su plataforma ...

Inteligencia Artificial

Rastreador web de OpenAI y errores de la FTC

OpenAI lanza un rastreador predeterminado de opt-in para raspar Internet, mientras que la FTC lleva a cabo una invest...

Inteligencia Artificial

Conoce GPT Crawler una herramienta de IA que puede rastrear un sitio para generar archivos de conocimiento y crear un GPT personalizado a partir de una o varias URL.

Qué maravilloso sería construir modelos únicos de GPT extrayendo conocimiento de páginas web. Conoce GPT Crawler: una...

Inteligencia Artificial

¿Realmente se expondrán o perderán 300 millones de empleos debido a la sustitución por IA?

Los autores del informe de Goldman Sachs sugieren que 300 millones de empleos podrían verse afectados por la sustituc...

Ciencia de Datos

Celebrando el impacto de IDSS

Una conferencia de dos días en MIT reflexionó sobre el impacto del Instituto de Datos, Sistemas y Sociedad desde su l...

Inteligencia Artificial

El gemelo malévolo de ChatGPT, 'WormGPT', está entrando silenciosamente en correos electrónicos y saqueando bancos.

SlashNext dice que WormGPT es un ejemplo de la amenaza que representan los modelos de IA generadores de lenguaje.