RAG ve veri · 2026-10-17
Türkçe semantik arama: EmbeddingMagibu ile adım adım
Türkçe dokümanları parçalayın, llmtr/embeddingmagibu-200m ile vektörleyin ve kosinüs benzerliğiyle en yakın parçaları bulun: tek dosyalık Python örneği.
Kısa yanıt: parçala, vektörle, karşılaştır
LLMTR (llmtr.com), Türkiye'de ve global sağlayıcılarda barındırılan dil modellerine tek, OpenAI uyumlu API'den erişim veren bir gateway'dir. Türkçe dokümanlarda semantik arama için metni parçalara bölüp her parçayı https://llmtr.com/v1 adresindeki POST /v1/embeddings uç noktasında llmtr/embeddingmagibu-200m modeliyle vektöre çevirir, sorguyu da aynı modelle vektörleyip kosinüs benzerliği en yüksek parçaları seçersiniz.
Semantik arama kelime eşleşmesine değil anlama bakar: iade kelimesi geçmeyen bir soru, iade koşullarını anlatan parçayı bulabilir. EmbeddingMagibu 200M Türkçe metin için eğitilmiş ve Türkiye'de barındırılan bir embedding modelidir; normalize edilmiş 768 boyutlu vektör döndürür ve metin başına 8.192 token kabul eder. Model Hugging Face'te alibayram/embeddingmagibu-200m adıyla MIT lisansıyla yayımlanmıştır.
Türkçe dokümanlarda semantik arama adım adım nasıl kurulur?
Aşağıdaki betik dört adımı tek dosyada yapar ve yalnızca openai paketine ihtiyaç duyar (pip install openai); numpy ya da vektör veritabanı gerekmez. Anahtarınızı LLMTR_API_KEY ortam değişkenine koyup betiği çalıştırdığınızda üç kısa Türkçe dokümanı parçalar, parçaları vektörler ve bir soruya en yakın üç parçayı benzerlik puanıyla yazdırır. Örnekteki üç dokümanın her biri tek parçaya sığar; kendi dokümanlarınızı documents sözlüğüne dosya adı ve metin olarak ekleyin.
Betik vektörleri bellekte tutar ve her soruda bütün parçalarla karşılaştırır. Derlem büyüdüğünde vektörleri bir vektör veritabanında saklayabilirsiniz; parçalama, vektörleme ve sıralama adımları aynı kalır.
| Adım | Nerede | Sınır |
|---|---|---|
| 1. Parçalama | İstemci tarafında | Metin başına en fazla 8.192 token; önerilen parça 256-512 token |
| 2. Doküman vektörleme | POST /v1/embeddings, prompt_name document | İstek başına 256 metin ve toplam 16.384 token |
| 3. Sorgu vektörleme | POST /v1/embeddings, prompt_name query | Metin başına en fazla 8.192 token |
| 4. Benzerlik ve sıralama | İstemci tarafında, kosinüs benzerliği | 768 boyutlu vektör (dimensions ile 512, 256 ya da 128 boyut) |
Tek dosyalık Türkçe semantik arama: parçalama, document ve query ile vektörleme, kosinüs benzerliği ve en yakın üç parça. Yalnızca openai paketi gerekir.
import math
import os
from openai import OpenAI
client = OpenAI(base_url="https://llmtr.com/v1", api_key=os.environ["LLMTR_API_KEY"], timeout=300)
MODEL = "llmtr/embeddingmagibu-200m"
BATCH = 32 # 32 chunks x 512 tokens = 16,384 tokens, the per-request limit
documents = {
"fatura.txt": "Faturalar her ayın ilk iş günü kesilir ve kayıtlı e-posta adresine gönderilir. "
"Kurumsal hesaplarda fatura bilgileri Ayarlar sayfasından değiştirilebilir.",
"iade.txt": "Ürünü teslim aldıktan sonra 14 gün içinde iade talebi oluşturabilirsiniz. "
"Kullanılmamış ürünlerde ücret, talep onaylandıktan sonra kartınıza geri yüklenir.",
"kargo.txt": "Hafta içi saat 16:00'ya kadar verilen siparişler aynı gün kargoya teslim edilir. "
"Kargo takip numarası sipariş özetinde yer alır.",
}
def chunk(text, max_words=200, overlap=40):
"""Split a text into overlapping windows of words."""
words = text.split()
step = max_words - overlap
return [" ".join(words[i:i + max_words]) for i in range(0, max(len(words) - overlap, 1), step)]
def embed(texts, prompt_name):
"""Embed texts in batches: prompt_name is document for chunks and query for questions."""
vectors = []
for start in range(0, len(texts), BATCH):
response = client.embeddings.create(
model=MODEL,
input=texts[start:start + BATCH],
extra_body={"prompt_name": prompt_name},
)
vectors.extend(item.embedding for item in sorted(response.data, key=lambda item: item.index))
return vectors
def cosine(a, b):
dot = sum(x * y for x, y in zip(a, b))
return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))
# Step 1: chunk every document and keep the file name next to each chunk.
chunks = [(name, part) for name, text in documents.items() for part in chunk(text)]
# Step 2: embed the chunks as documents.
chunk_vectors = embed([part for _, part in chunks], "document")
# Step 3: embed the question as a query.
question = "Aldığım ürünü geri gönderebilir miyim?"
query_vector = embed([question], "query")[0]
# Step 4: rank the chunks by cosine similarity and print the closest three.
scores = [(cosine(query_vector, vector), name, part) for (name, part), vector in zip(chunks, chunk_vectors)]
for score, name, part in sorted(scores, reverse=True)[:3]:
print(f"{score:.3f} {name} {part[:80]}")
Adım 1: Dokümanları parçalara bölmek
Arama sonucu olarak dokümanın tamamı yerine ilgili paragrafı döndürmek için dokümanları parçalara bölersiniz. Parçalama bir zorunluluktur da: EmbeddingMagibu metin başına en fazla 8.192 token kabul eder ve bu sınırı aşan bir metni kırpmaz, isteği 400 provider_error ile reddeder.
LLMTR dokümanı toplu indeksleme için 256 ile 512 token arası parçalar önerir. Betikteki chunk fonksiyonu metni kelimeye göre böler; 200 kelimelik pencere ve 40 kelimelik örtüşme bir başlangıç değeridir. Token'ı istemci tarafında saymanız gerekmez: her yanıtın usage.prompt_tokens alanı o istekteki toplam token sayısını verir, parça başına ortalamaya bakıp max_words değerini ayarlayın. Örtüşme sayesinde iki parçanın sınırına denk gelen ve 40 kelimeden kısa bir cümle parçalardan birinde bütün kalır.
Adım 2 ve 3: Parçaları document, soruyu query ile vektörlemek
embed fonksiyonu parçaları 32'lik gruplar halinde gönderir. Bir istek en fazla 256 metin ve toplam 16.384 token taşıyabilir; parça başına en fazla 512 token'la 32 x 512 = 16.384 eder, yani grup token sınırını aşmaz. Parçalar prompt_name değeri document ile, soru query ile gönderilir; prompt_name OpenAI SDK'da extra_body içinde yer alır. Yanıttaki öğeleri index alanına göre sıralamak her vektörün doğru parçaya eşlenmesini sağlar.
İstekler sırayla gider; LLMTR dokümanı toplu indekslemede paralel istek yerine sıralı istek önerir. Yoğun anlarda HTTP 503 ve model_busy tipi dönebilir; Retry-After süresi kadar bekleyip aynı isteği tekrar göndermeniz yeterlidir. OpenAI Python SDK 429 ve 5xx yanıtlarını varsayılan olarak iki kez kendisi yeniden dener. Betik, dokümanın büyük istekler için önerdiği gibi istemci zaman aşımını 300 saniyeye ayarlar.
Adım 4: Kosinüs benzerliği ve en yakın parçalar
Kosinüs benzerliği iki vektörün iç çarpımının, vektörlerin uzunluklarının çarpımına bölünmesidir. Sonuç -1 ile 1 arasındadır ve anlamca yakın metinlerde yükselir. EmbeddingMagibu vektörleri normalize edilmiş olarak, yani uzunluğu 1 olarak döndürdüğü için iç çarpım tek başına kosinüs benzerliğine eşittir. Betikteki cosine fonksiyonu uzunlukları yine de hesaplar; böylece vektörlerin normalize olup olmadığından bağımsız olarak doğru sonucu verir.
Betik her parça için puanı hesaplar, puana göre sıralar ve en yüksek üçünü dosya adıyla yazdırır. Puanın mutlak değeri derlemden derleme değişir; sonuçları bir eşikle süzecekseniz eşiği kendi soru ve doküman örneklerinizle belirleyin. Dosya adını parçanın yanında tutmak kullanıcıya kaynağı göstermenizi sağlar; RAG kuruyorsanız seçilen parçalar sohbet modeline bağlam olarak gider.
İndeksi saklamak, güncellemek ve maliyet
Parça vektörlerini bir kez üretip saklayın; sonraki her aramada yalnızca soru vektörlenir. İndeksi tek bir modelle, aynı prompt_name düzeniyle ve aynı dimensions değeriyle oluşturun; başka bir modelin vektörleriyle karıştırmayın. Depolamayı küçültmek için dimensions ile 512, 256 ya da 128 boyut seçebilirsiniz; bu durumda soruyu da aynı boyutla göndermeniz gerekir. Bir doküman değiştiğinde yalnızca onun parçalarını yeniden vektörleyip eski vektörlerin yerine koyun; dosya adını parçanın yanında tutmak bunu kolaylaştırır. Modeli değiştirirseniz indeksi baştan oluşturursunuz.
Fiyat tarihlidir: 15 Ekim 2026 00:00 ile 20 Ekim 2026 23:59 (TSİ) arasında 0 $, 21 Ekim 2026 00:00'dan (TSİ) itibaren 1 milyon girdi token'ı için 0,01 $. 20 Ekim 2026'da biten ücretsiz dönemde her hesabın günlük hakkı 500.000 girdi token'ıdır ve 00:00'da (TSİ) yenilenir; günlük kullanım bu sınıra ulaştıktan sonra gönderilen istekler HTTP 429 döner. Örnek: 400 token'lık 10.000 parça 4 milyon token eder ve 21 Ekim 2026'dan sonra bir kez vektörlemek 4 x 0,01 $ = 0,04 $ tutar.
Türkçe dokümanlarda semantik arama kurmak
Dokümanları parçalayın, llmtr/embeddingmagibu-200m ile https://llmtr.com/v1/embeddings üzerinden vektörleyin ve kosinüs benzerliğiyle en yakın parçaları seçin.
- Parçala. Dokümanları 256 ile 512 token arasındaki parçalara bölün ve her parçanın yanında kaynağını tutun.
- Vektörle. Parçaları prompt_name document ile, kullanıcı sorusunu prompt_name query ile model llmtr/embeddingmagibu-200m kullanarak POST /v1/embeddings ucuna gönderin.
- Sırala. Soru vektörüyle her parça vektörü arasındaki kosinüs benzerliğini hesaplayın ve en yüksek puanlı parçaları döndürün.
Sık sorulan sorular
Türkçe semantik arama için vektör veritabanı şart mı?
Hayır. Küçük bir derlemde vektörleri bellekte tutup her soruda kosinüs benzerliğini hesaplayabilirsiniz; bu yazıdaki betik böyle çalışır. Derlem büyüdüğünde vektörleri bir vektör veritabanına taşıyabilirsiniz; parçalama ve vektörleme adımları değişmez.
Dokümanları ve soruları aynı şekilde mi vektörlemeliyim?
Aynı modelle ve aynı dimensions değeriyle, ama farklı prompt_name ile: doküman parçaları document, kullanıcı soruları query ile gönderilir. İkisi de https://llmtr.com/v1 adresindeki POST /v1/embeddings ucuna gider.
EmbeddingMagibu ile 1 milyon token vektörlemek ne kadar tutar?
15 Ekim 2026 00:00 ile 20 Ekim 2026 23:59 (TSİ) arasında 0 $; bu dönemde hesap başına günlük hak 500.000 girdi token'ıdır. 21 Ekim 2026 00:00'dan (TSİ) itibaren 1 milyon girdi token'ı 0,01 $'dır.