LangChain4j: potenciando tus aplicaciones Java con Inteligencia Artificial (IA) y Modelos de Lenguaje de Gran Escala (LLM). Integración con Ollama.

0
333

LangChain4j se presenta como un aliado indispensable para integrar en nuestras aplicaciones Java, de manera muy sencilla, capacidades de Inteligencia Artificial y Modelos de Lenguaje a Gran Escala (LLM). Ya dimos unos primeros pasos con LangChain4j y en este segundo tutorial vamos probar a cambiar de LLM para demostrar la versatilidad de esa capa de abstracción que proporciona sobre la complejidad de usar el api de distintos servicios de NPLs.

Contenido.

1. Introducción.

Tras unos primeros pasos con LangChain4j el objetivo de este nuevo tutorial es demostrar el impacto mínimo que tiene a nivel de código, en nuestra prueba de concepto, cambiar de LLM usando las capacidades de configuración de la librería y los starters que proporciona para Spring Boot.

En el tutorial anterior usamos GPT-3.5, Generative Pre-trained Transformer, haciendo uso del api de OpenAI quienes también proporcionan el servicio de ChatGPT a través de una interfaz que utiliza la potencia y la capacidad de GPT-3.5 para interactuar con los usuarios a través de conversaciones en lenguaje natural. Si bien, el servicio de ChatGPT con la versión de GPT-3.5 es gratuito, la versión mejorada de GPT-4 es de pago y, para hacer uso del api de ambas versiones, necesitas tener una subscripción y pagar por el procesamiento en base a tokens (aunque durante las pruebas que llevo realizadas no he gastado más de 0,10$).

A día de hoy, existen alternativas que nos permiten instalarnos localmente un servicio de NPL, descargar y ejecutar una serie de LLMs distribuidos bajo diversas licencias. Entre las alternativas disponibles podemos destacar:

  • LocalAI: es la alternativa gratuita y de código abierto a OpenAI, sigue las especificaciones del API REST de OpenAI y es totalmente compatible, permitiendo su ejecución local. Permite ejecutar LLMs, generar imágenes y audio localmente o en nuestros propios sistemas, soportando múltiples familias de modelos y arquitecturas. No requiere GPU aunque se puede activar su aceleración.
  • Ollama: es una herramienta optimizada para ejecutar localmente LLMs de código abierto, incluidos Mistral, Llama-2, CodeLLaMA,… y características similares a LocalAI.

No solo pensando en el ahorro de céntimos, sino por dejar de preocuparnos por la conectividad o por la privacidad, vamos a explorar cómo instalar y ejecutar Ollama localmente.

También la idea es buscar una alternativa a la ejecución de tests de integración de nuestros prompts en un entorno controlado, no dependiente de un servicio externo.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 16′ (Apple M1 Pro, 32GB DDR4).
  • Sistema Operativo: Mac OS Sonoma 14.2.1

3.Ollama

Vamos a explorar dos alternativas distintas de instalación.

3.1. Instalación local

Los pasos a seguir para una instalación local son como los de cualquier otro software, accedemos a la página de descargas de Ollama y seleccionamos el sistema operativo para realizar la descarga.

Y una vez descargado, seguimos los pasos del propio instalador, en nuestro caso hemos seleccionado la instalación para Mac, descomprimimos y movemos el ejecutable a la carpeta de aplicaciones.

 

Aparecerá un icono en la barra superior indicando que está arrancado y, si accedemos a través de un navegador a la url del servicio veremos que este está disponible.

 

Podemos consultar los modelos instalados a través del api http://localhost:11434/api/tags.

Lo siguiente es acceder a un terminal y ejecutar un comando de arranque:

ollama run mistral:7b

 

Donde mistral es el modelo que queremos descargar y ejecutar por consola y 7b hace referencia a número de parámetros con el que ha sido entrenado el modelo y también al tamaño de la descarga del mismo, los modelos entrenados con 7 billones de parámetros suelen rondar los 4Gb.

Una vez descargado, puedes interactuar directamente con el modelo a través del terminal.

3.2. Ollama dockerizado?

Existe una imagen oficial de docker para ejecutar el servicio de Ollama en local a la que podemos añadirle una interfaz de usuario, bastante interesante, para ejecutar no solo un chat conversacional con el modelo que descarguemos, sino una parte de administración de los modelos (modelfiles), los prompts y los propios usuarios que pueden tanto acceder, como administrar el servicio.

Para ejecutar el servicio de Ollama dockerizado podemos usar el siguiente fichero de docker-compose.yml

version: '3.8'
services:

  ollama:
    image: ollama/ollama:latest
    ports:
      - 11434:11434
    volumes:
      - .:/code
      - ./ollama/ollama:/root/.ollama
    container_name: ollama
    # pull_policy: always
    # tty: true
    restart: unless-stopped
    networks:
      - ollama-docker

  llama-webui:
    image: ghcr.io/ollama-webui/ollama-webui:main
    container_name: ollama-webui
    volumes:
      - ./ollama/ollama-webui:/app/backend/data
    depends_on:
      - ollama
    ports:
      - 3000:8080
    environment:
      - 'OLLAMA_API_BASE_URL=http://ollama:11434/api'
    extra_hosts:
      - host.docker.internal:host-gateway
    restart: unless-stopped
    networks:
      - ollama-docker

networks:
  ollama-docker:
    external: false

 

Ejecutamos un «docker-compose up».

 

Tras la descarga de las imágenes de docker, tendremos tanto el servicio accesible como la ui, a través de http://localhost:3000

Pulsamos sobre «Sign up» y damos de alta un usuario:

Una vez tenemos el usuario, podemos acceder al portal:

 

Pulsando sobre el icono del usuario en la parte inferior izquierda podemos acceder a la administración:

 

En la que podemos modificar la configuración de acceso pulsando sobre «Admin settings»

y cambiando «Default User Role» a User:

 

Pero vamos al lío, ahora podemos importar o crear un modelfile:

Seleccionando el nombre del modelo, un tag, una descripción y un contenido en el que realmente seleccionamos el modelo a descargar y los parámetros de configuración, dentro de los cuáles podemos configurar un mensaje de sistema por defecto que condicionará el comportamiento de nuestro LLM.

También podemos añadir una plantilla de prompt por defecto y debemos seleccionar las categorías que definen el modelo.

 

Una vez tenemos importado un modelo podemos empezar a chatear

seleccionando entre uno de los que tengamos instalados:

y dependiendo del mensaje del sistema que hayamos configurado nos contestará de una forma u otra:

Ya en el primer mensaje de respuesta vemos que incurre en algún error gramatical y mezcla las respuestas entre el castellano y el inglés; y es que estamos usando Mistral, generado a partir de Llama-2; un modelo entrenado en base a 7 billones de parámetros, cuando GPT-3.5 está entrenado en base a 170 billones.

Pero tiene buena pinta, ¿verdad?, pues sino fuese porque en el día en el que escribo este tutorial la versión dockerizada de Ollama corriendo en un Mac va extremadamente lenta porque docker no hace uso de la aceleración de la GPU 🙁

Podéis verlo en las trazas:

ollama        | time=2024-03-06T21:17:16.629Z level=INFO source=llm.go:77 msg="GPU not available, falling back to CPU"

Más info aquí -> https://chariotsolutions.com/blog/post/apple-silicon-gpus-docker-and-ollama-pick-two

4. Configuración de langChain4j para Ollama.

Vamos a volver a LangChain4j y para hacer uso de Ollama tanto dockerizado como instalado en tu SO, disponemos del siguiente starter configurable en nuestro pom.xml.

<dependency>
  <groupId>dev.langchain4j</groupId>
  <artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
  <version>0.27.1</version>
</dependency>

 

Y, una vez añadida la dependencia, no tenemos más que configurar las siguientes propiedades, en sustitución de las que teníamos con open-ai:

langchain4j:
  ollama:
    chat-model:
      base-url: http://localhost:11434
      model-name: mistral:instruct
      temperature: 0.0
      timeout: PT60S

El modelo que vamos a usar es la variante instruct de Mistral, más info en huggingface.

En nuestra primera prueba de concepto no teníamos más configuración específica de OpenAI que el tokenizador, no he encontrado algo equivalente en la librería de Ollama, pero podemos solventarlo de la siguiente forma.

Definimos el tokenizador como un bean dependiente de las propiedades de OpenAI:

    @Bean
    @ConditionalOnProperty("langchain4j.open-ai.chat-model.model-name")
    Tokenizer openAiTokenizer() {
        return new OpenAiTokenizer(OpenAiModelName.GPT_3_5_TURBO);
    }

Y condicionamos su inyección con un Optional

    ...

    @Autowired
    private Optional<Tokenizer> tokenizer;

    private void ingestUrl(String url) {
        log.info("ingesting {} ", url);
        final Document document = UrlDocumentLoader.load(url, new TextDocumentParser());
        final HtmlTextExtractor transformer = new HtmlTextExtractor(".td-container", Map.of("title", "h1.entry-title", "author", ".td-post-author-name", "date", ".td-post-date", "visits", ".td-post-views"), true);

        DocumentSplitter splitter = DocumentSplitters.recursive(600, 5);
        if (tokenizer.isPresent()){
            splitter = DocumentSplitters.recursive(600, 5, tokenizer.get());
        }
        final EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .documentSplitter(splitter)
                .embeddingModel(embeddingModel)
                .embeddingStore(embeddingStore)
                .documentTransformer(transformer)
                .build();
        ingestor.ingest(document);
    }

    ...

 

Con ello, la ingesta se realizará con el tokenizador por defecto y también he probado a aumentar el tamaño de los segmentos de los tokens.

 

5. Algunos prompts.

Vamos a probar con las mismas preguntas que le hicimos a GPT-3.5:

User: hola, quién eres?
Agent: Hola! Soy un asistente informático especializado en los tutoriales publicados en el sitio web líder en tecnología en español llamado "adictos al trabajo", disponible en la URL "<https://www.adictosaltrabajo.com/>". 

Aunque no tengo conciencia de mi propia existencia, soy capaz de procesar y entender el texto proporcionado a mí, incluyendo los tutoriales publicados en tu sitio favorito en el día 7 de marzo de 2024. 

En este momento, estoy capacitado para responder preguntas relacionadas con el contenido de esos tutoriales. Por lo tanto, soy "Ahora lo procesamos con NLTK": una herramienta inteligente diseñada para entender y responder a consultas basadas en los textos de los tutoriales publicados en "adictos al trabajo".

La respuesta no está nada mal, además como incluimos la fecha actual en el prompt de system, nos informa del día en curso ;), aunque es cierto que está tomando una parte de uno de los tutoriales para tomar consciencia de si mismo.

Vamos con la siguiente:

User: cuáles son los últimos tutoriales publicados en adictos al trabajo?
Agent:  Based on the information provided in the text you've given me, it appears that the last tutorials published on "adictos al trabajo" may not be directly mentioned. However, I can tell you that the text discusses a tutorial related to using OpenAI Códex and its API or ChatGPT for text generation tasks. The tutorial requires creating an account on OpenAI Códex and choosing the API option, which is a paid service. An alternative is offered in the form of using ChatGPT for more conversational text generation.

Therefore, I cannot provide you with specific titles or topics of the latest tutorials published on "adictos al trabajo," but I can confirm that there are tutorials related to using OpenAI's services for text processing and generation.

A esto se le llama tirarse un triple desde la esquina 😉

Obviando el hecho de que nos está contestando en inglés cuando estamos preguntando en castellano,… vamos con la siguiente:

User: qué información tienes sobre mlops?
Agent:  MLOps (Machine Learning Operations) is a practice for collaboration and communication between data scientists and operations professionals to deploy machine learning models into production environments. It combines DevOps practices with machine learning workflows to streamline the development, deployment, and management of ML models.

In the context of MLOps, concepts like Continuous Integration (CI) and Continuous Delivery (CD) are also applied. CI refers to the frequent integration of changes in the source code, with the goal of detecting errors early on. Practices such as continuous integration of code and working together on a shared repository are used for this purpose.

MLOps aims to automate and streamline the entire machine learning lifecycle, from data preparation and model training to deployment and monitoring in production environments. It also focuses on ensuring that models remain up-to-date and performant over time, as well as maintaining security and compliance with relevant regulations.

 

A ver si podemos forzar a que se haga referencia a la fuente desde la que obtiene información:

User: donde puedo leer más sobre mlops?
Agent:  To learn more about MLOps, you can visit the following resources mentioned in the text:

1. The link to a blog post on "adictos al trabajo" website: <https://www.adictosaltrabajo.com/2023/08/21/devops-eso-es-cosa-del-pasado-conoce-mlops/>
2. The author of the blog post, whose name is Luis (<https://www.adictosaltrabajo.com/author/luis-merino-ulizarna/>).

In the blog post titled "¿DevOps? Eso es cosa del pasado, conoce MLOps", the author discusses how DevOps practices have become outdated and introduces MLOps as a new approach to managing machine learning models in production environments. The post covers various aspects of MLOps, including its benefits, challenges, and tools used for implementing it.

Ni tan mal,… nos ha proporcionado hasta la página del autor.

6. Referencias.

7. Conclusiones.

En este tutorial hemos visto como tener tu propio servicio de NPL y chat local, basado en otros modelos de LLMs con Ollama, como alternativa a ChatGPT y a los servicios de OpenAI.

Hemos usado un modelo «ligero», por regla general, para ejecutar un modelo necesitamos estos requisitos:

  • 7b:  requiere al menos 8GB de RAM
  • 13b: requiere al menos 16GB de RAM
  • 70b: requiere al menos 64GB de RAM

Debemos ser conscientes también de las limitaciones de nuestra propia máquina a la hora de ejecutar un LLM localmente.

Con el background que tenemos nosotros en cuanto a metodología de desarrollo, donde localmente somos capaces de simular cualquier servicio del que dependemos (bases de datos, colas de mensajería, servicios de terceros,…) para lanzar tanto pruebas de integración como pruebas de aceptación en caja negra, hemos intentando trasladar ese concepto cuando trabajamos en una IA, para disponer de un entorno local de pruebas. Sin mucho éxito para que esté totalmente integrado dentro del ciclo de desarrollo, al menos por ahora trabajando en Mac; pero os dejo también aquí una lectura relacionada sobre el concepto de MLOps, la que nos recomendó Mistral 😉

Stay tuned, again!

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad