OpenAI vs Ollama Usando el SQLDatabaseToolkit de LangChain

Descargo de responsabilidad

Los datos bursátiles utilizados en este artículo son completamente ficticios. Son únicamente para fines de demostración. Por favor, no utilice estos datos para tomar decisiones financieras.

En un artículo anterior, vimos los beneficios de usar Ollama localmente para una aplicación RAG. En este artículo, ampliaremos nuestra evaluación de Ollama probando consultas en lenguaje natural (NL) contra un sistema de base de datos, utilizando el SQLDatabaseToolkit de LangChain. SQL servirá como el sistema de referencia para la comparación mientras exploramos la calidad de los resultados proporcionados por OpenAI y Ollama.

Los archivos de notebook utilizados en este artículo están disponibles en GitHub.

Introducción

El SQLDatabaseToolkit de LangChain es una herramienta poderosa diseñada para integrar capacidades de procesamiento de NL con sistemas de bases de datos relacionales. Permite a los usuarios consultar bases de datos utilizando entradas de NL, empleando las capacidades de grandes modelos de lenguaje (LLMs) para generar consultas SQL de manera dinámica. Esto lo hace especialmente útil para aplicaciones donde usuarios no técnicos o sistemas automatizados necesitan interactuar con datos estructurados. 

Varios LLMs son bien soportados por LangChain. LangChain también proporciona soporte para Ollama. En este artículo, evaluaremos qué tan bien se integra LangChain con Ollama y la viabilidad de usar el SQLDatabaseToolkit en una configuración local.

Crear una cuenta en SingleStore Cloud

Un artículo anterior mostró los pasos para crear una cuenta gratuita en SingleStore Cloud. Usaremos el Nivel Compartido Gratuito.

Seleccionar el Espacio de Trabajo de Inicio > Conectar > Cliente CLI nos dará los detalles que necesitaremos más tarde, como nombre de usuario, contraseña, host, puerto y base de datos.

Crear Tablas de Base de Datos

Para nuestro entorno de prueba, usaremos SingleStore ejecutándose en la nube como nuestro sistema de base de datos objetivo, y nos conectaremos de forma segura a este entorno utilizando cuadernos Jupyter ejecutándose en un sistema local.

Desde el panel de navegación izquierdo en el portal de la nube de SingleStore, seleccionaremos DESARROLLAR > Estudio de Datos > Abrir Editor SQL. Crearemos tres tablas, de la siguiente manera:

SQL

 

CREATE TABLE IF NOT EXISTS tick (
    symbol VARCHAR(10),
    ts     DATETIME SERIES TIMESTAMP,
    open   NUMERIC(18, 2),
    high   NUMERIC(18, 2),
    low    NUMERIC(18, 2),
    price  NUMERIC(18, 2),
    volume INT,
    KEY(ts)
);

CREATE TABLE IF NOT EXISTS portfolio (
    symbol         VARCHAR(10),
    shares_held    INT,
    purchase_date  DATE,
    purchase_price NUMERIC(18, 2)
);

CREATE TABLE IF NOT EXISTS stock_sentiment (
    headline  VARCHAR(250),
    positive  FLOAT,
    negative  FLOAT,
    neutral   FLOAT,
    url       TEXT,
    publisher VARCHAR(30),
    ts        DATETIME,
    symbol    VARCHAR(10)
);

Cargaremos la tabla portafolio con los siguientes datos ficticios:

SQL

 

INSERT INTO portfolio (symbol, shares_held, purchase_date, purchase_price) VALUES
('AAPL', 100, '2022-01-15',  150.25),
('MSFT',  50, '2021-12-10',  305.50),
('GOOGL', 25, '2021-11-05', 2800.75),
('AMZN',  10, '2020-07-20', 3200.00),
('TSLA',  40, '2022-02-18',  900.60),
('NFLX',  15, '2021-09-01',  550.00);

Para la tabla sentimiento_de_acciones, descargaremos el archivo stock_sentiment.sql.zip y lo descomprimiremos. Cargaremos los datos en la tabla utilizando un cliente MySQL, de la siguiente manera:

Shell

 

mysql -u "<username>" -p"<password>" -h "<host>" -P <port> -D <database> < stock_sentiment.sql

Utilizaremos los valores para <nombre de usuario>, <contraseña>, <host>, <puerto> y <base de datos> que guardamos anteriormente.

Finalmente, para la tabla tick, crearemos un pipeline:

SQL

 

CREATE PIPELINE tick
AS LOAD DATA KAFKA 'public-kafka.memcompute.com:9092/stockticker'
BATCH_INTERVAL 45000
INTO TABLE tick
FIELDS TERMINATED BY ','
(symbol,ts,open,high,low,price,volume);

Ajustaremos para obtener los datos más tempranos:

SQL

 

ALTER PIPELINE tick SET OFFSETS EARLIEST;

Y probaremos el pipeline:

SQL

 

TEST PIPELINE tick LIMIT 1;

Ejemplo de salida:

Plain Text

 

+--------+---------------------+--------+--------+--------+--------+--------+
| symbol | ts                  | open   | high   | low    | price  | volume |
+--------+---------------------+--------+--------+--------+--------+--------+
| MMM    | 2025-01-23 21:40:32 | 178.34 | 178.43 | 178.17 | 178.24 |  38299 |
+--------+---------------------+--------+--------+--------+--------+--------+

Y luego comenzaremos el pipeline:

SQL

 

START PIPELINE tick;

Después de unos minutos, verificaremos la cantidad de datos cargados hasta ahora:

SQL

 

SELECT COUNT(*)
FROM tick;

Entorno de prueba local

De un artículo anterior, seguiremos los mismos pasos para configurar nuestro entorno de prueba local como se describe en estas secciones:

  • Introducción. Utilice una máquina virtual o venv.
  • Crear una cuenta de SingleStore Cloud. Este paso se completó arriba.
  • Crear una base de datos. El nivel gratuito compartido ya proporciona una base de datos y solo necesitamos anotar el nombre de la base de datos.
  • Instalar Jupyter.
    Texto plano

     

    pip install notebook
  • Instalar Ollama.
    Texto sin formato

    curl -fsSL https://ollama.com/install.sh | sh
  • Variables de entorno.
    Texto sin formato

     

    :@:/“” data-lang=”text/plain”>

    export SINGLESTOREDB_URL="<username>:<password>@<host>:<port>/<database>"

    Reemplace <username>, <password>, <host>, <port> y <database> con los valores para su entorno.

    Texto sin formato

     

    “” data-lang=”text/plain”>

    export OPENAI_API_KEY="<OpenAI API Key>"

    Reemplace <OpenAI API Key> con su clave.

  • Iniciar Jupyter.
    Texto sin formato

    jupyter notebook

Vamos a utilizar los cuadernos de Jupyter desde GitHub. Estos cuadernos están configurados para usar OpenAI y Ollama. Para Ollama, utilizaremos uno de los LLMs listados con Soporte de herramientas. Probaremos las siguientes cuatro consultas.

Primera Consulta

SQL

SQL

 

SELECT symbol, (MAX(high) - MIN(low)) AS volatility
FROM tick
GROUP BY symbol
ORDER BY volatility ASC
LIMIT 1;

Lenguaje Natural

Plain Text

 

"For each stock symbol, calculate the volatility as the difference\n"
"between the highest recorded price and the lowest recorded price over time.\n"
"Which stock symbol has the least volatility?"

Resultados

SQL

Plain Text

 

+--------+------------+
| symbol | volatility |
+--------+------------+
| FTR    |       0.55 |
+--------+------------+

OpenAI

Plain Text

 

The stock symbol with the least volatility is FTR, with a volatility of 0.55.

Ollama

Plain Text

 

To find the stock with the highest price, we need to compare the prices of all the given stocks and find the maximum value. However, I don't have real-time access to financial data or the ability to execute code that interacts with external APIs. Therefore, I can't directly calculate the highest price from this list.

However, if you provide me with a specific date or time range, I can help you find the stock with the highest price during that period. For example, if you want to know the stock with the highest price on a particular day in the past, I can assist you with that.

If you're looking for the current highest-priced stock, I recommend checking a financial news website or an API that provides real-time stock data, such as Yahoo Finance, Google Finance, or a service like Alpha Vantage or Finnhub.io. These platforms can give you the most up-to-date information on stock prices.`
For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/OUTPUT_PARSING_FAILURE

Segunda Consulta

SQL

SQL

 

SELECT COUNT(*)
FROM tick;

Lenguaje Natural

Plain Text

 

"How many rows are in the tick table?"

Resultados

SQL

Plain Text

 

+----------+
| COUNT(*) |
+----------+
| 22367162 |
+----------+

OpenAI

Plain Text

 

There are 22,367,162 rows in the tick table.

Ollama

Plain Text

 

The "tick" table has 3 rows.

Tercera Consulta

SQL

SQL

 

-- Paso 1: Obtener el último precio de cada símbolo
WITH latest_prices AS (
    SELECT symbol, price
    FROM tick t1
    WHERE ts = (
        SELECT MAX(ts)
        FROM tick t2
        WHERE t2.symbol = t1.symbol
    )
)

-- Paso 2: Calcular el valor total de la cartera
SELECT SUM(p.shares_held * lp.price) AS total_portfolio_value
FROM portfolio p, latest_prices lp
WHERE p.symbol = lp.symbol;

Lenguaje Natural

Plain Text

 

"Taking all the stock symbols from the portfolio table,\n"
"and using the latest value for each stock symbol from the tick table,\n"
"calculate the grand total value of all the shares listed in the portfolio table."

Resultados

SQL

Plain Text

 

+-----------------------+
| total_portfolio_value |
+-----------------------+
|              44540.60 |
+-----------------------+

OpenAI

Plain Text

 

$44,540.60

Ollama

Plain Text

 

I don't know. The provided SQL query does not contain any of the common mistakes listed. It uses the correct join conditions, functions, and data types. The query also properly quotes identifiers and uses the correct number of arguments for functions. Therefore, no changes are needed. However, without access to the actual database schema and table data, I cannot provide a specific answer to the question.

Cuarta Consulta

SQL

SQL

 

SELECT
    (
        SELECT ts
        FROM stock_sentiment
        WHERE symbol = 'AAPL'
        ORDER BY positive DESC
        LIMIT 1
    ) AS sentiment_date,
    (
        SELECT positive
        FROM stock_sentiment
        WHERE symbol = 'AAPL'
        ORDER BY positive DESC
        LIMIT 1
    ) AS most_positive_sentiment,
    (
        SELECT price
        FROM tick
        WHERE symbol = 'AAPL'
        ORDER BY ts DESC
        LIMIT 1
    ) AS current_best_price;

Lenguaje Natural

Plain Text

 

"Using the symbol AAPL, show me the date and the most\n"
"positive sentiment in the stock sentiment table and the\n"
"current best price for this symbol from the tick table."

Resultados

SQL

Plain Text

 

+---------------------+-------------------------+--------------------+
| sentiment_date      | most_positive_sentiment | current_best_price |
+---------------------+-------------------------+--------------------+
| 2020-05-28 00:00:00 |                0.331509 |             116.27 |
+---------------------+-------------------------+--------------------+

OpenAI

Plain Text

 

On 2020-05-28, the most positive sentiment for AAPL was 0.331509, and the current best price for AAPL is 116.27.

Ollama

Plain Text

 

The provided list contains decimal numbers, which appear to be the results of some kind of experiment or analysis. Without additional context, it's difficult to determine the exact nature of these results. However, we can observe that the majority of the numbers are between 116.85 and 117.27, with a few outliers at 115.99 and 117.30. The smallest number in the list is 115.99, and the largest is 117.30.`
For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/OUTPUT_PARSING_FAILURE

Resumen

Al analizar los resultados, vemos que SQL y OpenAI producen salidas consistentes en las cuatro consultas. Sin embargo, Ollama presenta problemas evidentes. Un hilo de discusión en GitHub destaca que mientras un modelo LLM debería admitir la llamada de herramientas, esta funcionalidad no está disponible nativamente en Ollama.

Si logras que esta funcionalidad de LangChain funcione con Ollama en uno de los LLM admitidos, por favor envíame un mensaje, y actualizaré el artículo y reconoceré tu ayuda.

Source:
https://dzone.com/articles/openai-vs-ollama-langchain-sqldatabasetoolkit