LangChain ile Chroma ve Pinecone Vektör Veritabanı Kullanımı
Yapay zeka uygulamaları geliştirirken en büyük zorluklardan biri, büyük dil modellerinin (LLM) kendi eğitim verilerinin ötesine geçememesidir. İşte burada vektör veritabanları devreye giriyor. LangChain ile Chroma ve Pinecone’u birlikte kullandığınızda, modellerinize uzun süreli hafıza kazandırıyor, kendi verilerinizi sorgulayabilir hale getiriyor ve gerçekten işe yarar RAG (Retrieval-Augmented Generation) pipeline’ları kurabiliyorsunuz. Bu yazıda her iki veritabanını da sıfırdan kurarak gerçek dünya senaryolarında nasıl kullanacağınızı göstereceğim.
Vektör Veritabanı Nedir, Neden Lazım?
Klasik veritabanlarında veriler satır ve sütunlar halinde saklanır, sorgular ise tam eşleşme ya da basit karşılaştırmalarla çalışır. Vektör veritabanları ise verileri matematiksel vektörler olarak saklar ve “anlamsal benzerlik” aramalarına olanak tanır. Bir belgeyi sorguladığınızda, kelimesi kelimesine eşleşme aramak yerine anlam olarak en yakın içerikleri bulabilirsiniz.
LangChain bu süreci şu adımlarla yönetir:
- Embedding: Metinler sayısal vektörlere dönüştürülür
- Indexing: Bu vektörler veritabanına kaydedilir
- Retrieval: Sorgu vektörüne en yakın sonuçlar getirilir
- Generation: Bulunan bağlam LLM’e iletilir, yanıt üretilir
Chroma yerel geliştirme ve küçük ölçekli projeler için mükemmelken, Pinecone production ortamlarında yüksek ölçeklenebilirlik gerektiren senaryolar için tercih edilir.
Ortam Kurulumu
Önce gerekli paketleri kuralım. Python 3.9 veya üstü kullanmanızı öneririm.
# Sanal ortam oluştur
python3 -m venv langchain-vector-env
source langchain-vector-env/bin/activate # Linux/macOS
# Windows için: langchain-vector-envScriptsactivate
# Temel paketleri kur
pip install langchain langchain-community langchain-openai
pip install chromadb
pip install pinecone-client
pip install tiktoken sentence-transformers
pip install python-dotenv pypdf
# Kurulumu doğrula
pip list | grep -E "langchain|chroma|pinecone"
Proje dizin yapısını oluşturalım:
mkdir -p ~/langchain-vector-project/{docs,scripts,notebooks}
cd ~/langchain-vector-project
# .env dosyası oluştur
cat > .env << 'EOF'
OPENAI_API_KEY=sk-your-openai-key-here
PINECONE_API_KEY=your-pinecone-key-here
PINECONE_ENVIRONMENT=us-east-1
PINECONE_INDEX_NAME=sysadmin-docs
EOF
# .gitignore ekle, API anahtarlarını commit etme!
echo ".env" >> .gitignore
echo "__pycache__/" >> .gitignore
echo "chroma_db/" >> .gitignore
Chroma ile Başlamak
Chroma, kurulum gerektirmeyen, Python içinde çalışan bir vektör veritabanıdır. Hem in-memory hem de kalıcı disk tabanlı mod desteği vardır.
Temel Chroma Kullanımı
# scripts/chroma_basic.py
import os
from dotenv import load_dotenv
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
load_dotenv()
# Örnek sysadmin dokümanı oluştur
sample_doc = """
Linux Sistem Yönetimi Rehberi
Disk Yönetimi:
LVM (Logical Volume Manager) ile disk yönetimi oldukça esnektir.
pvcreate komutu ile fiziksel volume oluşturulur.
vgcreate ile volume group tanımlanır.
lvcreate ile logical volume yaratılır.
Ağ Yapılandırması:
NetworkManager ile ağ ayarları yönetilir.
ip addr show komutu mevcut ağ arayüzlerini listeler.
nmcli con add komutu yeni bağlantı ekler.
Firewalld ile güvenlik duvarı kuralları oluşturulur.
Log Yönetimi:
journalctl sistem loglarını görüntüler.
/var/log dizini altında servis logları yer alır.
logrotate ile log dosyaları döndürülür ve sıkıştırılır.
"""
with open("/tmp/sysadmin_guide.txt", "w") as f:
f.write(sample_doc)
# Dökümanı yükle ve böl
loader = TextLoader("/tmp/sysadmin_guide.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
length_function=len
)
chunks = text_splitter.split_documents(documents)
print(f"Toplam chunk sayısı: {len(chunks)}")
# Embedding modeli ve Chroma veritabanı oluştur
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db",
collection_name="sysadmin_docs"
)
# Benzerlik araması yap
query = "Disk yönetimi nasıl yapılır?"
results = vectorstore.similarity_search(query, k=3)
for i, doc in enumerate(results):
print(f"n--- Sonuç {i+1} ---")
print(doc.page_content)
Chroma ile Kalıcı Depolama ve Metadata Filtreleme
Gerçek dünyada dökümanlarınıza metadata eklemek ve bu metadata üzerinden filtreleme yapmak çok işe yarar. Örneğin bir IT departmanında farklı kategorilerdeki belgelerinizi tek bir Chroma instance’ında tutabilirsiniz:
# scripts/chroma_metadata.py
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.schema import Document
from dotenv import load_dotenv
load_dotenv()
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Metadata ile döküman oluştur
documents = [
Document(
page_content="Nginx web sunucusu kurulumu: apt install nginx komutu ile kurulur. "
"Konfigürasyon dosyası /etc/nginx/nginx.conf altındadır.",
metadata={"category": "web-server", "os": "ubuntu", "difficulty": "beginner"}
),
Document(
page_content="PostgreSQL veritabanı backup alma: pg_dump -U postgres dbname > backup.sql "
"komutu ile veritabanı yedeği alınır. Restore için psql komutu kullanılır.",
metadata={"category": "database", "os": "linux", "difficulty": "intermediate"}
),
Document(
page_content="Kubernetes pod yönetimi: kubectl get pods komutu tüm podları listeler. "
"kubectl describe pod pod-name ile pod detayları görüntülenir.",
metadata={"category": "kubernetes", "os": "linux", "difficulty": "advanced"}
),
Document(
page_content="Windows Server IIS kurulumu: Server Manager üzerinden Web Server rolü eklenir. "
"Konfigürasyon IIS Manager arayüzünden yapılır.",
metadata={"category": "web-server", "os": "windows", "difficulty": "beginner"}
),
]
# Chroma'ya yükle
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory="./chroma_db",
collection_name="it_knowledge_base"
)
# Sadece Ubuntu ile ilgili web sunucu belgelerini getir
results = vectorstore.similarity_search(
query="web sunucusu nasıl kurulur",
k=2,
filter={"os": "ubuntu"} # Metadata filtresi
)
print("Ubuntu web sunucu sonuçları:")
for doc in results:
print(f"İçerik: {doc.page_content[:100]}...")
print(f"Metadata: {doc.metadata}n")
Pinecone Kurulumu ve Yapılandırması
Pinecone, bulut tabanlı bir vektör veritabanıdır. Ücretsiz katmanı ile başlayabilir, ihtiyacınıza göre ölçeklendirebilirsiniz. Önce pinecone.io’dan hesap açın ve API anahtarınızı alın.
# scripts/pinecone_setup.py
import os
from dotenv import load_dotenv
from pinecone import Pinecone, ServerlessSpec
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Pinecone as LangchainPinecone
load_dotenv()
# Pinecone istemcisini başlat
pc = Pinecone(api_key=os.getenv("PINECONE_API_KEY"))
index_name = os.getenv("PINECONE_INDEX_NAME", "sysadmin-docs")
# Index yoksa oluştur
existing_indexes = [idx.name for idx in pc.list_indexes()]
if index_name not in existing_indexes:
print(f"'{index_name}' index'i oluşturuluyor...")
pc.create_index(
name=index_name,
dimension=1536, # text-embedding-3-small için 1536
metric="cosine",
spec=ServerlessSpec(
cloud="aws",
region="us-east-1"
)
)
print("Index oluşturuldu!")
else:
print(f"'{index_name}' index'i zaten mevcut.")
# Index istatistiklerini kontrol et
index = pc.Index(index_name)
stats = index.describe_index_stats()
print(f"Toplam vektör sayısı: {stats['total_vector_count']}")
print(f"Dimension: {stats['dimension']}")
Pinecone’a Döküman Yükleme
# scripts/pinecone_ingest.py
import os
from dotenv import load_dotenv
from pinecone import Pinecone
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Pinecone as LangchainPinecone
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
load_dotenv()
def ingest_documents(docs_path: str, index_name: str):
"""
Belirtilen dizindeki tüm PDF ve TXT dosyalarını
Pinecone'a yükler.
"""
pc = Pinecone(api_key=os.getenv("PINECONE_API_KEY"))
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Dökümanları yükle
print(f"'{docs_path}' dizini taranıyor...")
loader = DirectoryLoader(
docs_path,
glob="**/*.txt",
loader_cls=TextLoader,
show_progress=True
)
documents = loader.load()
print(f"{len(documents)} döküman yüklendi.")
# Chunk'lara böl
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=100,
separators=["nn", "n", ".", " ", ""]
)
chunks = splitter.split_documents(documents)
print(f"Toplam {len(chunks)} chunk oluşturuldu.")
# Pinecone'a yükle (batch olarak)
batch_size = 100
for i in range(0, len(chunks), batch_size):
batch = chunks[i:i + batch_size]
LangchainPinecone.from_documents(
documents=batch,
embedding=embeddings,
index_name=index_name
)
print(f"Batch {i//batch_size + 1} yüklendi ({len(batch)} chunk)")
print("Tüm dökümanlar başarıyla Pinecone'a yüklendi!")
if __name__ == "__main__":
from langchain_community.document_loaders import TextLoader
ingest_documents("./docs", os.getenv("PINECONE_INDEX_NAME"))
RAG Pipeline Kurulumu
Asıl güç, vektör veritabanlarını LLM ile birleştirdiğinizde ortaya çıkıyor. Aşağıda hem Chroma hem de Pinecone ile çalışan, modüler bir RAG sistemi kuruyoruz:
# scripts/rag_pipeline.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain.callbacks import StdOutCallbackHandler
load_dotenv()
def create_rag_chain(vectorstore, model_name="gpt-3.5-turbo"):
"""
Verilen vectorstore ile RAG chain oluşturur.
Chroma veya Pinecone vectorstore kabul eder.
"""
# Özel prompt şablonu - Türkçe sysadmin asistanı için
prompt_template = """Sen deneyimli bir sistem yöneticisi asistanısın.
Aşağıdaki bağlam bilgisini kullanarak soruyu yanıtla.
Bağlamda cevap yoksa, bilmediğini söyle, uydurma.
Yanıtlarını pratik ve anlaşılır tut.
Bağlam:
{context}
Soru: {question}
Yanıt:"""
PROMPT = PromptTemplate(
template=prompt_template,
input_variables=["context", "question"]
)
llm = ChatOpenAI(
model_name=model_name,
temperature=0, # Sysadmin cevapları için deterministik olsun
max_tokens=1000
)
# Retriever yapılandır
retriever = vectorstore.as_retriever(
search_type="mmr", # Maximum Marginal Relevance - çeşitlilik için
search_kwargs={
"k": 5, # 5 sonuç getir
"fetch_k": 20, # MMR için 20 aday değerlendir
"lambda_mult": 0.7 # Çeşitlilik/relevance dengesi
}
)
# RetrievalQA chain oluştur
chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": PROMPT},
return_source_documents=True,
verbose=False
)
return chain
# Chroma ile kullan
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
chroma_store = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings,
collection_name="sysadmin_docs"
)
rag_chain = create_rag_chain(chroma_store)
# Sorgu çalıştır
questions = [
"LVM ile nasıl disk yönetimi yapılır?",
"Nginx ve IIS arasındaki fark nedir?",
"Log dosyaları nasıl yönetilir?"
]
for question in questions:
print(f"nSoru: {question}")
print("-" * 50)
result = rag_chain({"query": question})
print(f"Yanıt: {result['result']}")
print(f"nKullanılan kaynak sayısı: {len(result['source_documents'])}")
Gerçek Dünya Senaryosu: Şirket İç Wiki Asistanı
Diyelim ki şirketinizde yüzlerce sayfa teknik dokümantasyon var ve sysadminler sürekli “Bu şeyi nasıl yapıyorduk?” diye soruyor. İşte tam kullanım senaryosu:
# Doküman dizini yapısını oluştur
mkdir -p ~/company-wiki-bot/{docs/{networking,servers,databases,security},scripts}
# Örnek dökümanlar ekle
cat > ~/company-wiki-bot/docs/networking/vpn-setup.txt << 'EOF'
VPN Kurulum Prosedürü
OpenVPN Sunucu Kurulumu:
1. apt install openvpn easy-rsa
2. /usr/share/easy-rsa dizinini kopyala
3. CA sertifikası oluştur: ./easyrsa build-ca
4. Sunucu sertifikası: ./easyrsa build-server-full server nopass
5. Servis başlat: systemctl enable --now openvpn@server
Sorun Giderme:
- Bağlantı kurulamıyorsa: journalctl -u openvpn@server -f
- Port kontrolü: ss -ulnp | grep 1194
- Firewall kuralı: firewall-cmd --add-service=openvpn --permanent
EOF
cat > ~/company-wiki-bot/docs/databases/mysql-backup.txt << 'EOF'
MySQL Yedekleme Prosedürleri
Günlük Tam Yedek:
mysqldump -u root -p --all-databases --single-transaction > /backup/full_$(date +%Y%m%d).sql
Sıkıştırılmış Yedek:
mysqldump -u root -p dbname | gzip > /backup/dbname_$(date +%Y%m%d).sql.gz
Yedek Doğrulama:
mysqlcheck -u root -p --all-databases
gunzip -c /backup/dbname_backup.sql.gz | mysql -u root -p test_restore
Otomatik Temizlik:
find /backup -name "*.sql.gz" -mtime +30 -delete
EOF
echo "Örnek dökümanlar oluşturuldu!"
Bu senaryoda dökümanları yüklemek ve sorgulamak için production-ready bir script:
# scripts/wiki_bot.py
import os
import sys
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferWindowMemory
load_dotenv()
class CompanyWikiBot:
def __init__(self, docs_path: str, db_path: str = "./chroma_db"):
self.docs_path = docs_path
self.db_path = db_path
self.embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
self.vectorstore = None
self.chain = None
def load_and_index(self):
"""Dökümanları yükle ve index'le"""
loader = DirectoryLoader(
self.docs_path,
glob="**/*.txt",
loader_cls=TextLoader,
loader_kwargs={"encoding": "utf-8"}
)
docs = loader.load()
# Dosya adını metadata olarak ekle
for doc in docs:
filename = os.path.basename(doc.metadata.get("source", ""))
category = doc.metadata.get("source", "").split("/")[-2]
doc.metadata["filename"] = filename
doc.metadata["category"] = category
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=80
)
chunks = splitter.split_documents(docs)
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings,
persist_directory=self.db_path,
collection_name="company_wiki"
)
print(f"{len(chunks)} chunk index'lendi.")
def setup_chain(self):
"""Konuşma geçmişini destekleyen chain kur"""
llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)
memory = ConversationBufferWindowMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer",
k=5 # Son 5 konuşmayı hatırla
)
self.chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=self.vectorstore.as_retriever(search_kwargs={"k": 4}),
memory=memory,
return_source_documents=True,
verbose=False
)
def ask(self, question: str) -> dict:
"""Soru sor ve yanıtı döndür"""
result = self.chain({"question": question})
sources = list(set([
doc.metadata.get("filename", "Bilinmiyor")
for doc in result["source_documents"]
]))
return {
"answer": result["answer"],
"sources": sources
}
# Kullanım
if __name__ == "__main__":
bot = CompanyWikiBot(docs_path="./docs")
print("Dökümanlar yükleniyor...")
bot.load_and_index()
bot.setup_chain()
print("nŞirket Wiki Asistanı hazır! Çıkmak için 'quit' yazın.n")
while True:
question = input("Sorunuz: ").strip()
if question.lower() in ["quit", "exit", "çıkış"]:
break
if not question:
continue
response = bot.ask(question)
print(f"nYanıt: {response['answer']}")
print(f"Kaynaklar: {', '.join(response['sources'])}n")
Chroma vs Pinecone: Hangisini Seçmeli?
Her iki çözümün avantaj ve dezavantajlarını şu şekilde özetleyebiliriz:
Chroma için uygun senaryolar:
- Yerel geliştirme ve prototipleme: Kurulum gerekmez, anında çalışır
- Küçük ölçekli uygulamalar: Birkaç bin ila yüz bin vektöre kadar rahat çalışır
- Veri gizliliği kritikse: Tüm veriler kendi sunucunuzda kalır
- Düşük bütçe: Tamamen ücretsiz ve açık kaynak
- Offline ortamlar: İnternet bağlantısı gerektirmez
Pinecone için uygun senaryolar:
- Production yükü: Milyonlarca vektörde bile düşük gecikme
- Yüksek eşzamanlı sorgu: Otomatik ölçekleme sağlar
- Yönetilen altyapı: Backup, replikasyon, monitoring dahil
- Ekip ortamları: Merkezi vektör deposu, herkes aynı index’e erişir
- SLA gereksinimleri: %99.99 uptime garantisi
Performans Optimizasyonu İpuçları
Chroma için performansı artırmak adına bazı pratik ayarlar:
# Chroma'yı HTTP server modunda çalıştır (client-server mimari için)
pip install chromadb[server]
# Server başlat
chroma run --path /data/chroma_db --port 8000 --host 0.0.0.0
# Systemd servisi oluştur
sudo tee /etc/systemd/system/chroma.service << 'EOF'
[Unit]
Description=Chroma Vector Database Server
After=network.target
[Service]
Type=simple
User=chroma
WorkingDirectory=/opt/chroma
ExecStart=/opt/chroma/venv/bin/chroma run --path /data/chroma_db --port 8000
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now chroma
sudo systemctl status chroma
Büyük veri setlerinde embedding maliyetini düşürmek için caching mekanizması ekleyin. OpenAI embedding API’si gereksiz yere tekrar tekrar çağrılmasın diye aynı metin için sonuçları cache’leyin. CacheBackedEmbeddings sınıfı tam da bu iş için: yerel dosya sistemi veya Redis cache ile desteklenebilir.
Sonuç
LangChain ile Chroma ve Pinecone’u birlikte kullanmak, yapay zeka uygulamalarınıza ciddi bir güç katıyor. Geliştirme sürecinizde Chroma ile hızlıca prototip oluşturun, production’a geçerken Pinecone’a taşıyın. LangChain’in soyutlama katmanı sayesinde bu geçiş yalnızca birkaç satır kod değişikliğiyle oluyor.
Özellikle sysadmin ekipleri için iç wiki asistanı, runbook sorgulama sistemi veya incident response yardımcısı gibi araçlar, bu teknoloji stack’i ile gerçekten kısa sürede hayata geçirilebilir. Şirketimdeki deneyimimden söyleyebilirim ki “Bu sorunu daha önce nasıl çözmüştük?” sorusuna saniyeler içinde doğru cevap verebilen bir sistem, ekip verimliliğini gözle görülür şekilde artırıyor.
Bir sonraki adım olarak LangChain Agents konusunu incelemenizi öneririm. Vektör veritabanı aramasını, komut çalıştırma ve web erişimiyle birleştirdiğinizde, gerçekten otonom davranan sysadmin asistanları oluşturabilirsiniz.
