Em um artigo anterior, nós usamos o Ollama com a LangChain e o SingleStore. A LangChain forneceu uma solução eficiente e compacta para integrar o Ollama com o SingleStore. No entanto, e se nós removermos a LangChain? Neste artigo, vamos demonstrar um exemplo de uso do Ollama com o SingleStore sem depender da LangChain. Vamos ver que, embora consigamos os mesmos resultados descritos no artigo anterior, o número de código aumenta, sendo necessário gerenciar mais das partes de instalação que a LangChain normalmente trata.
O arquivo de notebook usado neste artigo está disponível no GitHub.
Introdução
Do artigo anterior, nós seguiremos os mesmos passos para configurar o nosso ambiente de teste, como descrito nas seções seguintes:
- Introdução
- Use uma Máquina Virtual ou
venv
.
- Use uma Máquina Virtual ou
- Crie uma conta do SingleStoreDB Cloud
- Use Grupo de Demonstração do Ollama como o Nome do Grupo de Workspace e ollama-demo como o Nome do Workspace. Note o senha e o nome do host. Permitir acesso de qualquer lugar temporariamente, configurando a firewall em Grupo de Demonstração do Ollama > Firewall.
- Criar um Banco de Dados
CREATE DATABASE IF NOT EXISTS ollama_demo;
- Instalar Jupyter
pip install notebook
- Instalar Ollama
curl -fsSL https://ollama.com/install.sh | sh
- Variável de Ambiente
export SINGLESTOREDB_URL="admin:<password>@<host>:3306/ollama_demo"
Substituir<password>
e<host>
pelos valores do seu ambiente.
- Iniciar Jupyter
jupyter notebook
Preencha o Notebook
Primeiro, algumas pacotes:
!pip install ollama numpy pandas sqlalchemy-singlestoredb --quiet --no-warn-script-location
Em seguida, importaremos algumas bibliotecas:
import ollama
import os
import numpy as np
import pandas as pd
from sqlalchemy import create_engine, text
Criaremos embeddings usando all-minilm
(45 MB no momento de escrita):
ollama.pull("all-minilm")
Saída do exemplo:
{'status': 'success'}
Para nossa LLM, usaremos llama2
(3,8 GB no momento da escrita):
ollama.pull("llama2")
Saída do exemplo:
{'status': 'success'}
Em seguida, usaremos o texto de exemplo da website Ollama:
documents = [
"Llamas are members of the camelid family meaning they're pretty closely related to vicuñas and camels",
"Llamas were first domesticated and used as pack animals 4,000 to 5,000 years ago in the Peruvian highlands",
"Llamas can grow as much as 6 feet tall though the average llama between 5 feet 6 inches and 5 feet 9 inches tall",
"Llamas weigh between 280 and 450 pounds and can carry 25 to 30 percent of their body weight",
"Llamas are vegetarians and have very efficient digestive systems",
"Llamas live to be about 20 years old, though some only live for 15 years and others live to be 30 years old"
]
df_data = []
for doc in documents:
response = ollama.embeddings(
model = "all-minilm",
prompt = doc
)
embedding = response["embedding"]
embedding_array = np.array(embedding).astype(np.float32)
df_data.append({"content": doc, "vector": embedding_array})
df = pd.DataFrame(df_data)
dimensions = len(df.at[0, "vector"])
Definiremos as embeddings para all-minilm
e iteraremos por cada documento para construir o conteúdo para um DataFrame do Pandas. Além disso, convertiremos as embeddings para um formato de 32 bits, pois este é o padrão do SingleStore para o tipo de dados VECTOR
. Por fim, determinaremos o número de dimensões de embedding para o primeiro documento no DataFrame do Pandas.
Em seguida, criaremos uma conexão com nossa instância do SingleStore:
connection_url = "singlestoredb://" + os.environ.get("SINGLESTOREDB_URL")
db_connection = create_engine(connection_url)
Agora, criaremos uma tabela com a coluna vector
usando as dimensões que determinamos anteriormente:
query = text("""
CREATE TABLE IF NOT EXISTS pandas_docs (
id BIGINT AUTO_INCREMENT NOT NULL,
content LONGTEXT,
vector VECTOR(:dimensions) NOT NULL,
PRIMARY KEY(id)
);
""")
with db_connection.connect() as conn:
conn.execute(query, {"dimensions": dimensions})
Agora, escreveremos o DataFrame do Pandas na tabela:
df.to_sql(
"pandas_docs",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
Saída do exemplo:
6
Agora, criaremos um índice para corresponder ao que criamos no artigo anterior:
query = text("""
ALTER TABLE pandas_docs ADD VECTOR INDEX (vector)
INDEX_OPTIONS '{
"metric_type": "EUCLIDEAN_DISTANCE"
}';
""")
with db_connection.connect() as conn:
conn.execute(query)
Pediremos uma pergunta, da seguinte forma:
prompt = "What animals are llamas related to?"
response = ollama.embeddings(
prompt = prompt,
model = "all-minilm"
)
embedding = response["embedding"]
embedding_array = np.array(embedding).astype(np.float32)
query = text("""
SELECT content
FROM pandas_docs
ORDER BY vector <-> :embedding_array ASC
LIMIT 1;
""")
with db_connection.connect() as conn:
results = conn.execute(query, {"embedding_array": embedding_array})
row = results.fetchone()
data = row[0]
print(data)
Convertiremos a prompt para embeddings, garantiremos que as embeddings sejam convertidas para um formato de 32 bits e, em seguida, executaremos a consulta SQL que usa a notação infixa <->
para a Distância Euclidiana.
Saída do exemplo:
Llamas are members of the camelid family meaning they're pretty closely related to vicuñas and camels
Em seguida, usaremos a LLM, da seguinte forma:
output = ollama.generate(
model = "llama2",
prompt = f"Using this data: {data}. Respond to this prompt: {prompt}"
)
print(output["response"])
Saída do exemplo:
Llamas are members of the camelid family, which means they are closely related to other animals such as:
1. Vicuñas: Vicuñas are small, wild camelids that are native to South America. They are known for their soft, woolly coats and are considered an endangered species due to habitat loss and poaching.
2. Camels: Camels are large, even-toed ungulates that are native to Africa and the Middle East. They are known for their distinctive humps on their backs, which store water and food for long periods of time.
Both llamas and vicuñas are classified as members of the family Camelidae, while camels are classified as belonging to the family Dromedaryae. Despite their differences in size and habitat, all three species share many similarities in terms of their physical characteristics and behavior.
Resumo
Neste artigo, nós replicamos os passos seguidos no artigo anterior e obtivemos resultados semelhantes. No entanto, tivemos de escrever uma série de instruções SQL e gerenciar vários passos que o LangChain teria feito por nós. Além disso, pode haver mais tempo e custo envolvidos no manutenção do código base a longo prazo em comparação com a solução LangChain.
Usar o LangChain, em vez de escrever código personalizado para acesso ao banco de dados, oferece várias vantagens, como eficiência, escalabilidade e confiabilidade.
O LangChain oferece uma biblioteca de módulos pré-construídos para interação com o banco de dados, reduzindo o tempo de desenvolvimento e o esforço. Os desenvolvedores podem usar esses módulos para implementar rapidamente várias operações de banco de dados sem começar do zero.
O LangChain abstrai muitas das complexidades envolvidas na gerencia de banco de dados, permitindo que os desenvolvedores se concentrem em tarefas de alto nível em vez de detalhes de implementação de baixo nível. Isso melhora a produtividade e o tempo de mercado para aplicações baseadas em banco de dados.
O LangChain tem uma comunidade de desenvolvedores grande, ativa e crescente, está disponível no GitHub e fornece documentação extensa e exemplos.
Em resumo, o LangChain oferece aos desenvolvedores uma plataforma poderosa, eficiente e confiável para construir aplicações baseadas em banco de dados, permitindo-lhes se concentrar em problemas de negócios usando abstrações de nível superior em vez de reinventar a roda com código personalizado. Comparando o exemplo neste artigo com o exemplo usado no artigo anterior, podemos ver os benefícios.
Source:
https://dzone.com/articles/ollama-plus-singlestore-minus-langchain