이전 記事에서는 Ollama, LangChain, 以及 SingleStore를 사용しました. LangChain은 Ollama와 SingleStore를 통합하는 데 効果적이고 精巧한 솔루션을 제공했습니다. 그러나 LangChain을 제거하면 어떻게 될까요? 이 記事에서는 LangChain을 依存せず Ollama와 SingleStore를 사용하는 예를 보여드릴 것입니다. 이전 記事에 기술된 同等의 결과를 얻을 수 있지만, 코드의 수가 증가하며, LangChain이 일반적으로 처리하는 인스턴스 관리를 더 많이 해야 합니다.
이 記事에 사용된 노트북 파일은 GitHub에 托管되어 있습니다.
개요
이전 記事에서는 다음 섹션에 기술된 同样的한 과정을 통해 시험 환경을 설정합니다:
- 개요
venv
또는 仮想 머신을 사용합니다.
- SingleStoreDB クラウド アカウントを作成します
- 作成したWorkspace Group NameはOllama Demo Group、Workspace Nameはollama-demoとします。パスワードとホスト名を覚えておいてください。Firewallの設定を変更して、Ollama Demo Group > Firewallからのアクセスを一時的に許可してください。
- 데이터베이스 생성
CREATE DATABASE IF NOT EXISTS ollama_demo;
- Jupyter 설치
pip install notebook
- Ollama 설치
curl -fsSL https://ollama.com/install.sh | sh
- 환경 변수
export SINGLESTOREDB_URL="admin:<password>@<host>:3306/ollama_demo"
<password>
와<host>
를 환경에 맞는 값으로 바꿔치세요.
- Jupyter 시작
jupyter notebook
노트북을 작성하세요
먼저 몇 가지 패키지를 설치합니다:
!pip install ollama numpy pandas sqlalchemy-singlestoredb --quiet --no-warn-script-location
다음으로 몇 가지 라이브러리를 임포트합니다:
import ollama
import os
import numpy as np
import pandas as pd
from sqlalchemy import create_engine, text
all-minilm
을 사용하여 어미딩을 생성할 것입니다 (쓰는 시점에서 45 MB):
ollama.pull("all-minilm")
{'status': 'success'}
우리의 LLM에 대해서는 llama2
(쓰기 시점에 3.8 GB)를 사용하겠습니다.:
ollama.pull("llama2")
{'status': 'success'}
次に、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"])
이 텍스트의 嵌入(embeddings)를 all-minilm
로 설정하고、각 문서를 통해 Pandas DataFrame의 내용을 구성하며, 嵌入(embeddings)를 32位형식으로 변환합니다(이는 SingleStore의 VECTOR
자료형의 기본값입니다). 마지막으로, Pandas DataFrame의 첫 문서의 嵌入(embeddings) 维数를 결정합니다.
次に、SingleStore 인스턴스와 연결하겠습니다.:
connection_url = "singlestoredb://" + os.environ.get("SINGLESTOREDB_URL")
db_connection = create_engine(connection_url)
이전에 결정한 维数을 사용하여 vector
열로 테이블을 생성합니다.:
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})
이제 Pandas DataFrame를 테이블로 書き込みます:
df.to_sql(
"pandas_docs",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
예시 출력:
6
이제 이전 記事에서 생성한 인덱스와 같은 인덱스를 생성합니다:
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)
이제 다음과 같은 질문을 하겠습니다.:
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)
이 질문을 嵌入(embeddings)로 변환하고, 嵌入(embeddings)를 32位형식으로 변환하고, Euclidean Distance를 사용하는 SQL 질의를 실행합니다(이는 Euclidean Distance를 사용하는 infix 記法 <->
를 사용합니다).
예시 출력:
Llamas are members of the camelid family meaning they're pretty closely related to vicuñas and camels
次に LLM를 사용하겠습니다.:
output = ollama.generate(
model = "llama2",
prompt = f"Using this data: {data}. Respond to this prompt: {prompt}"
)
print(output["response"])
예시 출력:
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.
요약
이 기사에서는 이전 기사에서 따랐던 단계를 재현하여 비슷한 결과를 얻었습니다. 그러나 우리는 LangChain가 대신 처리해 줄 수 있는 여러 단계를 관리하고, 일련의 SQL 문을 작성해야 했습니다. 또한, LangChain 솔루션에 비해 코드 베이스를 장기적으로 유지하는 데 더 많은 시간과 비용이 들 수 있습니다.
LangChain을 사용하여 데이터베이스 액세스에 대한 사용자 정의 코드를 작성하는 것보다 여러 가지 장점이 있습니다. 예를 들어 효율성, 확장성, 신뢰성입니다.
LangChain은 데이터베이스 상호작용을 위한 사전 빌드된 모듈 라이브러리를 제공하여 개발 시간과 노력을 줄입니다. 개발자는 이러한 모듈을 사용하여 처음부터 시작하지 않고도 다양한 데이터베이스 작업을 빠르게 구현할 수 있습니다.
LangChain은 데이터베이스 관리에 포함된 복잡성을 추상화하여, 개발자가 저수준 구현 세부 사항에 대해 신경 쓰는 대신 고수준 태스크에 집중할 수 있게 합니다. 이는 데이터베이스 기반 애플리케이션의 생산성과 시장 진입 시간을 향상시킵니다.
LangChain은 대규모의 활발한 개발자 커뮤니티를 보유하고 있으며, GitHub에서 이용할 수 있으며, 광범위한 문서와 예제를 제공합니다.
요약하자면, LangChain은 개발자들에게 강력하고 효율적이며 신뢰할 수 있는 데이터베이스 기반 애플리케이션을 구축하는 플랫폼을 제공하여, 사용자 정의 코드로 휠을 재ivent하는 대신 고수준 추상을 사용하여 비즈니스 문제에 집중할 수 있게 합니다. 이 기사의 예제와 이전 기사에서 사용한 예제를 비교하면 이점을 볼 수 있습니다.
Source:
https://dzone.com/articles/ollama-plus-singlestore-minus-langchain