Las aplicaciones de inteligencia artificial creadas con Rust pasan gradualmente de los experimentos iniciales a modelos más prácticos, según una presentación en directo organizada por JetBrains en colaboración con la Rust Foundation. La primera sesión se centró en la biblioteca de código abierto Rig y en cómo utilizarla para construir aplicaciones basadas en modelos lingüísticos grandes y agentes capaces de invocar herramientas y ejecutar tareas dentro de la aplicación.
Orhun Parmaksız, Developer Advocate, mostró un pequeño agente de programación que construyó con Rig y Ratatui, mientras que Stephen Korzeniewski, responsable principal de Rig en 0xPlaygrounds, explicó la arquitectura interna del proyecto y las decisiones que sustentan sus interfaces de programación.
Una interfaz unificada para los proveedores de modelos
Rig aborda un problema práctico común en las aplicaciones de modelos lingüísticos: OpenAI, Anthropic, Gemini y otros tienen interfaces de programación diferentes, incluso cuando algunos servicios anuncian compatibilidad con la interfaz de OpenAI. En lugar de vincular directamente partes de la aplicación a la interfaz de un único proveedor, Rig ofrece una interfaz unificada de Rust que permite cambiar de proveedor sin reescribir las partes relacionadas con el modelo.
La biblioteca organiza la aplicación en torno a varios componentes básicos, entre ellos el cliente del proveedor, el modelo de finalización, el agente y las herramientas disponibles para él. El agente funciona como una capa superior a la solicitud directa al modelo; añade las instrucciones, los límites de tokens y las capacidades necesarias para ejecutar tareas que van más allá del flujo de texto de entrada y texto de salida.
Las instrucciones del agente se pasan en lo que Rig denomina preamble, unas instrucciones que cumplen el papel de una indicación del sistema y se incluyen al principio de cada solicitud. Las comunicaciones de red con los proveedores de modelos se gestionan mediante interfaces asíncronas, mientras que muchos detalles del trabajo asíncrono permanecen dentro de la biblioteca, para que el código de la aplicación se concentre en la configuración y el comportamiento requeridos.
Las herramientas convierten al agente en parte de la aplicación
Rig define una herramienta mediante la interfaz Tool trait de Rust. La definición de la herramienta incluye su nombre y los tipos de entrada, salida y error, además de la función que se ejecuta cuando se invoca. También describe los argumentos esperados mediante JSON Schema, de modo que el modelo recibe una descripción estructurada de los datos que puede proporcionar.
Después de registrar la herramienta en el agente, un modelo compatible con la invocación de herramientas puede determinar cuándo utilizarla e integrar su resultado en la respuesta. La función puede ejecutar una operación matemática, consultar una base de datos, recuperar información o conectarse a otro servicio. La herramienta también puede recibir un contexto que conserve estados como el número de invocaciones o los resultados almacenados en caché. La idea se extiende a los propios agentes, ya que un agente puede ponerse a disposición de otro como herramienta para delegar tareas entre ambos.
De la demostración experimental a una aplicación comprobable
El proyecto Rat Code reunió estos componentes en un pequeño agente de programación que funciona desde el terminal mediante Rig y Ratatui. El archivo main.rs inicializa el cliente del proveedor, el modelo y el agente, mientras que las capacidades para leer y escribir archivos y ejecutar comandos de shell se definen por separado y luego se registran en el agente mediante la interfaz de herramientas de Rig.
La aplicación también utiliza la interfaz de streaming de Rig para procesar la respuesta por partes y actualizar la interfaz del terminal mientras el modelo genera la respuesta. La presentación abordó asimismo el sistema de hooks, el mecanismo de recuperación ante invocaciones de herramientas y las decisiones de diseño que sustentan las abstracciones proporcionadas por la biblioteca. La demostración del código completo comienza en la grabación en el minuto 27:28.
RAG, modelos locales y pruebas
Rig no se limita a los proveedores de modelos alojados. Admite aplicaciones de generación aumentada mediante recuperación, en las que los documentos y las consultas de los usuarios se convierten en embeddings vectoriales y después se buscan los documentos semánticamente más cercanos para añadirlos al contexto del modelo. La biblioteca ofrece integraciones con bases de datos y abstracciones para almacenes vectoriales, con la posibilidad de implementar la interfaz de un almacén vectorial cuando se utiliza una base de datos que no es compatible directamente.
También se pueden ejecutar modelos locales mediante Ollama y llama.cpp, o utilizar la integración rig-candle para realizar la inferencia directamente dentro de una aplicación de Rust. Esta opción permite incluir los pesos del modelo en la aplicación y ejecutar modelos compatibles mediante WebAssembly, sin depender de una interfaz de modelo alojada ni de un servidor de inferencia local independiente.
La importancia de estas opciones se aprecia en el lugar donde se ejecutan los modelos y se almacenan los datos, pero al mismo tiempo plantean el desafío de probar las integraciones. Rig depende principalmente de un sistema de grabación: las pruebas se ejecutan con los proveedores reales y el tráfico HTTP se guarda en archivos YAML; después, un servidor simulado reproduce las solicitudes y respuestas dentro de las pruebas de integración continua. El proyecto incluye unas 1.700 interacciones grabadas, que se reproducen con cada solicitud de incorporación de cambios en pocos segundos.
Estas pruebas verifican que la integración de software siga funcionando, pero no miden la calidad de las salidas del modelo, que puede cambiar cuando el proveedor actualiza su modelo. Por ello, la presentación mencionó las pruebas programadas con modelos activos como un método separado para las aplicaciones que dependen de la calidad de la respuesta.
Lectura editorial: ¿qué les importa a los desarrolladores?
El valor práctico de Rig no reside únicamente en añadir un nuevo proveedor, sino en separar la capa de la aplicación de los detalles de las interfaces de los modelos, manteniendo las herramientas, la recuperación y la inferencia local dentro de una única arquitectura de Rust. Esto puede reducir el coste de cambiar de proveedor o de método de ejecución, pero no elimina las diferencias de comportamiento entre los modelos ni resuelve por sí solo el problema de evaluar la calidad de las salidas. El mecanismo de pruebas del proyecto muestra que garantizar que la conexión funcione es una cosa, y asegurarse de que el modelo produzca el resultado requerido es otra que necesita pruebas en vivo y criterios de evaluación independientes.