En 2024, no faltarán aplicaciones basadas en LLM. Las principales empresas de tecnología como Microsoft y Google están impulsando versiones cada vez más potentes de sus modelos emblemáticos ChatGPT y Gemini, y jugadores especializados como Anthropic están impulsando ofertas competitivas con integraciones adicionales. En el mundo de los LLM aplicados, las empresas e incluso los gobiernos están experimentando con aplicaciones de chat para una variedad de contextos.
A pesar de la enorme energía empresarial invertida en los LLM, la mayoría de las aplicaciones de alto perfil todavía están limitadas por su enfoque en interfaces similares a chat que reciben y devuelven texto legible por humanos. Esto es comprensible; después de todo, uno de los desarrollos más interesantes de los LLM es la capacidad de comprender y generar el lenguaje humano, lo que permite una interfaz de usuario conversacional. Sin embargo, las interfaces de chat pasan por alto otro caso de uso muy importante para los LLM: el procesamiento de textos como paso intermedio en un proceso de datos más amplio.
Hoy exploraremos este caso de uso y veremos cómo los LLM pueden ser útiles como parte de una canalización de datos, no solo como un generador de lenguaje natural.
Para utilizar LLM como parte de una canalización de datos, necesitamos cambiar el formato de salida del LLM; en lugar de generar párrafos para que los lean los humanos, el modelo tiene que generar algo que las computadoras puedan leer. Por lo general, esto significa salida estructurada en un formato de datos como JSON o instrucciones en un lenguaje de programación como Python o SQL. Estos formatos de salida son mucho menos indulgentes que el lenguaje natural, ya que la falta de comillas o corchetes puede bloquear todo el proceso. Por lo tanto, necesitaremos confiar en métodos y funciones especializados que se hayan desarrollado para respaldar este caso de uso. Estas características se denominan colectivamente llamadas a funciones, ya que la salida tiende a llamar funciones o consumirse en llamadas a funciones.
Sin embargo, antes de profundizar en estos métodos, primero exploremos un poco más en profundidad por qué se desarrollaron las funciones de llamada a funciones en primer lugar.
Conexión a servicios externos
El caso de uso original y más sencillo para la llamada a funciones es la conexión a servicios externos. Cuando OpenAI lanzó originalmente GPT-4, también actualizó la API con una característica que permitía al usuario proporcionar al modelo un conjunto de funciones estilo Python que el modelo podía llamar para lograr sus objetivos. Por ejemplo, se podría decir al modelo que puede llamar a una función externa para calcular el precio de un valor complejo. Utilizando esta información, el modelo podría escribir un código que calcule el valor de una cartera compuesta por estos valores, sin necesidad de poseer conocimientos especializados en fijación de precios de valores.
Llamar a funciones estilo Python es sólo la punta del iceberg. Una vez que se demostró en el mercado la importancia de las llamadas a funciones, OpenAI y otros proveedores de LLM comenzaron a admitir otros formatos de salida, como JSON o SQL. Lo importante era que estos modelos generaban resultados legibles por máquina, que otros procesos podían leer de manera confiable.
Los lectores astutos podrían reconocer que hemos hecho algo similar en artículos anteriores, utilizando LLM para generar datos de entrenamiento , SQL o JSON . En estos artículos , logramos esto mediante ingeniería rápida y verificación de resultados, pero ahora que la llamada a funciones es una característica ampliamente admitida, podemos hacerlo más fácilmente confiando en estas características a nivel de modelo.
Encadenamiento de LLM
Las llamadas a funciones crearon nuevas posibilidades para aplicaciones de múltiples LLM y pronto los desarrolladores comenzaron a experimentar con el encadenamiento de LLM para crear sistemas sofisticados. Algunos de estos sistemas se conocieron como agentes , que podían buscar en la web de forma independiente, recopilar nuevos datos y llamar a otro LLM con la nueva información. Estos canales son capaces de alcanzar cantidades sorprendentes de autonomía y son capaces de resolver problemas sofisticados con muy poca información, aunque todavía existen limitaciones, como los costos de API y las salvaguardas de comportamiento, que impiden que los agentes obtengan una adopción generalizada.
Uso de LLM como insumo y procesamiento intermedio.
Otro caso de uso para los LLM de llamada de funciones es el procesamiento de datos intermedios y de entrada. Los LLM se pueden utilizar para analizar entradas no estructuradas en datos estructurados que se pueden utilizar para el procesamiento posterior. Si bien muchas de estas tareas tienden a quedar relegadas a tecnologías de PNL “tradicionales”, la naturaleza flexible de los modelos basados en transformadores significa que un modelo específicamente entrenado puede desempeñarse mucho mejor en estas tareas que otras tecnologías de PNL. Como resultado, muchos desarrolladores están intentando aprovechar estos modelos especializados en sus canales de datos.
Ahora que estamos familiarizados con la teoría detrás de la llamada a funciones, veamos la aplicación que crearemos hoy.
En un artículo anterior , creé una aplicación RAG sencilla para responder preguntas en lenguaje natural sobre el popular boletín informativo CB Insights. En el artículo de hoy, crearemos una aplicación similar para responder preguntas, pero en lugar de depender de la búsqueda integrada y GPT3.5, usaremos el reconocimiento de entidades como método de indexación principal. Además, usaremos DRAGON como motor de resumen para poder ejecutar la aplicación completa en nuestra computadora portátil, sin necesidad de servicios en la nube.
¿Por qué utilizar el reconocimiento de entidades?
Antes de profundizar en la implementación, primero exploremos las ventajas de utilizar NER como tecnología de recuperación en lugar de incorporar la búsqueda. Si bien en producción querremos utilizar cada técnica de acuerdo con las demandas de la situación específica, NER ofrece varias ventajas sobre un sistema que se basa en la búsqueda integrada.
Depuración: debido a que el reconocimiento de entidades es una tarea fácilmente verificable, todo el proceso es mucho más depurable. Es fácil comprobar si el modelo identifica correctamente todas las entidades y es fácil construir y mejorar un algoritmo de coincidencia basado en estas entidades. Comparativamente, es mucho más difícil verificar que el algoritmo de incrustación identifica adecuadamente las similitudes y diferencias en los pasajes.
Flexibilidad: al separar el reconocimiento y el filtrado, hacemos que el proceso sea mucho más flexible que un algoritmo de búsqueda basado en incrustaciones. Podemos agregar metadatos adicionales, cambiar los algoritmos de búsqueda según el tipo de entidad e incluso usar algoritmos de incrustación encima de los resultados de búsqueda basados en NER. Esto permite desarrollar funciones mucho más potentes basadas en combinaciones de tecnologías.
Por ejemplo, una canalización basada en NER puede utilizar la búsqueda basada en entidades para limitar un conjunto de documentos y luego utilizar un algoritmo de incrustación para limitar aún más el espacio de búsqueda. Esto tiende a hacer que la búsqueda sea mucho más rápida y eficiente.
Poder de identificación: debido al nivel de control manual que es posible, las canalizaciones NER son mucho más adecuadas para determinadas tareas de búsqueda y recuperación. Las búsquedas de incrustación se basan en la proximidad de pasajes dentro de los datos de entrenamiento, lo que calcula la probabilidad de que dos documentos provengan del mismo documento más grande. En algunos casos de uso, esto hará que la búsqueda integrada omita documentos importantes.
Ahora que entendemos los beneficios de usar NER dentro de una canalización RAG, echemos un vistazo más profundo a las tecnologías específicas que estamos usando en nuestra aplicación.
Reconocimiento de entidad LLM
El reconocimiento de entidades es una tecnología de PNL "tradicional" para extraer datos estructurados a partir de datos de lenguaje no estructurados. Los datos extraídos se pueden utilizar luego en el procesamiento posterior o como metadatos para el pasaje que se analiza.
Históricamente, esto se lograba utilizando pequeños algoritmos de aprendizaje automático especialmente diseñados que primero etiquetaban las partes del discurso, seguido de una segunda pasada que determina si los nombres propios identificados son entidades nombradas.
Con los LLM de llamada de funciones, podemos realizar la misma tarea, con varias ventajas adicionales.
Debido a que la arquitectura transformadora es capaz de comprender la estructura del lenguaje mejor que los modelos de PNL más pequeños, es probable que el rendimiento sea más sólido, por ejemplo en los casos en que el pasaje tiene un formato incorrecto.
Debido a que los LLM se actualizan con los datos de capacitación más recientes, es probable que el sistema de reconocimiento de entidades se mantenga más actualizado que otros modelos de reconocimiento de entidades de código abierto.
Se pueden utilizar técnicas de ingeniería rápidas para incorporar datos adicionales y dar instrucciones adicionales, lo que permite un comportamiento más flexible incluso en modelos disponibles en el mercado.
DRAGON Cubrimos Dragon en un artículo anterior donde destacamos su impresionante desempeño al resumir datos en lenguaje natural. Usaremos Dragon para realizar el paso final del análisis, donde resumiremos todos los artículos relevantes para las entidades seleccionadas.
SLIM Los SLIM son una nueva familia de modelos miniaturizados y ejecutables localmente de LLMWare (no es ningún secreto que soy fanático de su trabajo de miniaturización) que se especializa en llamadas de funciones. Estos modelos se han ajustado específicamente para generar resultados que puedan ser interpretados por máquinas, lo que permite a los usuarios aprovechar los desarrollos recientes en la arquitectura de llamada de funciones sin tener que depender de API externas.
Hoy utilizaremos el modelo SLIMs-NER, que realizará el reconocimiento de entidad nombrada en los artículos del boletín. Además de NER, también existen modelos SLIM para análisis de sentimientos, generación de SQL y agentes de varios pasos.
Ahora que entendemos la tecnología, ¡implementemos la aplicación!
Comencemos descargando los artículos de CB Insights. Importemos las dependencias:
import requests from bs4 import BeautifulSoup import os import pandas as pd import json import re
Y ahora el código para descargar el archivo del boletín:
res = requests.get('https://www.cbinsights.com/newsletter/') soup = BeautifulSoup(res.text) article_links = [[i.text, i['href']] for i in soup.find_all('a') if 'campaign-archive' in i['href'] ] article_soups = [BeautifulSoup(requests.get(link).text) for title, link in article_links]
Ahora que hemos descargado el archivo del boletín, procesémoslo en formato JSON.
result_json = {} for soup_meta, soup_art in zip(article_links, article_soups): article_tables = [] cur_article = [] for table in soup_art.find_all('table'): if table.attrs.get('mc:variant') == 'Section_Divider': article_tables.append(get_deduped_article_tables(cur_article)) cur_article = [] else: cur_article.append(table.text) article_tables.append(get_deduped_article_tables(cur_article)) result_json[soup_meta[0]] = article_tables articles_with_meta = [] for name, tables in result_json.items(): print(name, pd.to_datetime(tables[0][1].strip())) articles_with_meta.append({ 'name': name, 'date': pd.to_datetime(tables[0][1].strip()).strftime('%Y-%m-%d'), 'tables': tables }) df = pd.DataFrame(articles_with_meta)
Ahora estamos en el mismo lugar que estábamos en el artículo anterior. Sin embargo, en lugar de ir directamente a la construcción de RAG mediante la creación de incrustaciones, ejecutaremos un paso de reconocimiento de entidades.
Primero, importemos las dependencias para ejecutar SLIM, un nuevo conjunto de modelos de LLMWare que nos permite realizar el reconocimiento de entidades localmente en nuestra máquina:
from llmware.agents import LLMfx from llmware.parsers import WikiParser from collections import defaultdict # define a function for identifying all the named entities def run_ner(text): agent = LLMfx() agent.load_work(text) agent.load_tool("ner") named_entities = agent.ner() ner_dict= named_entities["llm_response"] return ner_dict
Ahora podemos ejecutar el reconocimiento de entidad nombrada en todos los artículos:
date_entities = defaultdict(dict) for _, row in df.iterrows(): for idx, t in enumerate(row['tables'][1:]): if 'Start Your Free Trial' in t: t = t[:t.index('Start Your Free Trial')] date_entities[row['date']][idx] = run_ner('\n'.join(t))
Es posible que el proceso NER tarde unos minutos en completarse, pero esto es todo lo que necesita para reconocer entidades utilizando un LLM miniaturizado de última generación.
Puede consultar el diccionario date_entities imprimiendo algunos elementos de prueba. Por ejemplo, el código:
date_entities[list(date_entities.keys())[0]]
Debería producir el siguiente resultado:
{0: {'people': ['Yahoo!'], 'place': [], 'company': ['Databricks', 'MosaicML'], 'misc': []}, 1: {'people': [], 'place': ['New York'], 'company': ['CB Insights'], 'misc': []}}
Que muestra todas las diversas entidades que han sido detectadas por el modelo SLIM.
Ahora que se han detectado las entidades, creemos un flujo de trabajo de respuesta a preguntas que demuestre el poder de esta técnica. Para nuestro ejemplo, usaremos la pregunta de prueba: ¿Qué papel juega OpenAI en la estrategia de IA de Microsoft?
Comencemos importando los paquetes adecuados para ejecutar DRAGON:
from llmware.prompts import Prompt query = "What role does OpenAI play in Microsoft's AI strategy?" model_name = "llmware/dragon-llama-7b-gguf" prompter = Prompt().load_model(model_name)
Ahora podemos construir la función que responde a la pregunta mediante el reconocimiento de entidades. Para aprovechar nuestros datos NER, querremos implementar el siguiente flujo de trabajo:
Así es como se ve el flujo de trabajo en forma de código:
def answer_question_with_ner(query): ner_results = run_ner(query) # run NER on the user query search_entities = [] for ent_type, ent_list in ner_results.items(): search_entities.extend(ent_list) # create a list of entities to search for search_entities = list(set(search_entities)) # now perform a lookup for articles that mention the identified entities, using set arithmetic. articles = set(entity_to_place_map[search_entities[0]]) for se in search_entities: articles &= set(entity_to_place_map[se]) # now process the corpus into a prompt and feed it to the question-answering LLM. article_content = [] for article in articles: article_content.extend(df[df['date'] == article[0]].iloc[0]['tables'][article[1]+1]) response = prompter.prompt_main(query, context='\n'.join(article_content), prompt_name="default_with_context", temperature=0.3) return response # return the response.
Ejecute la función, con la consulta del primer bloque de código, y debería ver el siguiente resultado:
Microsoft has poured billions of dollars into ChatGPT developer OpenAI. However, it's also placed a number of bets on other GenAI startups across computing, mapping, and gaming.
También puede ver en la sección "evidencia" del objeto de respuesta que, de hecho, se han recuperado los dos artículos del archivo de CB Insights que mencionan a Microsoft y OpenAI, y que la respuesta del LLM se basa directamente en la evidencia.
Tenga en cuenta que debido a que estamos haciendo un reconocimiento explícito de entidades, el proceso de recuperación es extremadamente transparente y depurable. Si alguna vez surge una pregunta sobre por qué el modelo recuperó estos datos específicos del corpus, todo lo que se necesita es una simple declaración impresa para ver que el modelo eligió el artículo porque la consulta menciona "Microsoft" y "OpenAI", y el dos secciones del boletín recuperadas son las únicas secciones que mencionan ambas entidades.
Además, en comparación con la búsqueda vectorial basada en incrustaciones, el método de búsqueda NER proporciona respuestas mucho más precisas. En mis pruebas, los artículos seleccionados estaban entre los 10 artículos más relevantes clasificados según el algoritmo ada de OpenAI, pero no fue el que se identificó como el que tenía la mayor proximidad a la pregunta en cuestión. Por lo tanto, es posible que una aplicación que utiliza la búsqueda incrustada no haya respondido correctamente a la pregunta y la falta de capacidad de depuración solo contribuiría a la confusión.
Y con eso, hemos creado una aplicación de respuesta a preguntas utilizando búsquedas NER, ¡mejorando la calidad del proceso en el proceso!
Hoy, creamos una aplicación utilizando llamadas a funciones, una nueva e interesante característica de LLM. Los modelos de llamada de funciones miniaturizados y ejecutables localmente son un desarrollo revolucionario que desbloquea una nueva clase de aplicaciones de IA, y solo estamos viendo la primera iteración de estas tecnologías. Será emocionante ver qué aplicaciones crearán los desarrolladores con estas tecnologías en los próximos meses.
Si tiene una idea en el espacio de la IA que desea que se implemente o simplemente desea conversar sobre tecnología, no dude en comunicarse con Github o LinkedIn .
Si desea obtener más información sobre LLMWare, la empresa detrás de SLIM y DRAGON, puede encontrarlos en HugginFace o Github .