CoolFace
Datasetpublic

yoitsmeyusuf/turkce-tibbi-vektor-veri-seti

Turkce Tibbi Makale Vektor Veri Seti umutertugrul/turkish-hospital-medical-articles veri setinden secilen guven, medipol, florence hastane kaynaklarindan 402 makale parcalanip magibu/embeddingmagibu-200m ile vektorlestirildi. Toplam 3138 chunk. Sutunlar sutun tip aciklama chunk_id string Parcanin kimligi (hastane-makale-bolum-parca) url string Parcanin ait oldugu orijinal makalenin kaynak baglantisi chunk_text string Parcalanmis metin icerigi (ham;… See the full description on the dataset page: https://huggingface.co/datasets/yoitsmeyusuf/turkce-tibbi-vektor-veri-seti.

sourceHugging Facecc-by-4.0updated 2mo agoView on Hugging Face
0likes34downloads
Dataset Card

Turkce Tibbi Makale Vektor Veri Seti

umutertugrul/turkish-hospital-medical-articles veri setinden secilen guven, medipol, florence hastane kaynaklarindan 402 makale parcalanip `magibu/embeddingmagibu-200m` ile vektorlestirildi. Toplam 3138 chunk.

Sutunlar

sutuntipaciklama
chunk_idstringParcanin kimligi (hastane-makale-bolum-parca)
urlstringParcanin ait oldugu orijinal makalenin kaynak baglantisi
chunk_textstringParcalanmis metin icerigi (ham; baslik eklenmemis)
chunk_vectorlist[float]768 boyutlu, L2-normalize embedding
titlestringMakale basligi
bolum_basligistringParcanin ait oldugu bolumun basligi
parent_idstringAyni bolumden cikan chunk'lari baglar (parent-child)
__sourcestringKaynak hastane
token_sayisiintChunk'in token uzunlugu

1. Chunking stratejisi

Yontem: bolum tabanli (yapisal) parcalama.

1. metni \n ile bloklara ayir
2. baslik isaretle:  len<120 & basinda "- " yok & sonunda ":" yok
                     & ("?" ile bitiyor | "." ya da "!" ile bitmiyor)
3. icindekiler menusunu sil (govdede baslik olarak da gecen "- X" satirlari)
4. bolum = baslik + kendisinden sonraki icerik bloklari
5. chunk uret:
      bolum <= 320 token  ->  oldugu gibi                (~%89)
      bolum >  320 token  ->  blok sinirindan bol, 48 overlap
                              tek blok asiyorsa cumleden bol
      bolum <  48 token  ->  komsu bolume yapistir

Neden bu yontem secildi. Once sabit token + overlap denendi, olcum sonucu iki varsayim da cokdu:

  • —`\n\n` yok. Kaynak veri setinin 14 split'i olculdu; liv disinda hicbirinde cift newline gecmiyor. Ayrac tek \n. Ama metin duz blok da degil: makaleler "baslik + o basligin altindaki icerik" seklinde diziliyor. Baslik tespiti kurali 14 split'in hepsinde bolumlerin %84-94'unde isabet ediyor.
  • —350 token hedefi cok buyuktu. Modelin tokenizer'i Turkce'ye ozel oldugu icin 5,77 karakter/token veriyor (cok dilli modellerde ~3,2). Bolumlerin medyani sadece ~90 token, p99'u ~400. 350 token'lik hedef bolumlerin %99'undan buyuk oldugu icin 3-5 alakasiz bolumu tek chunk'a tikardi.

Sonucta chunk sinirini tokenizer degil, belgenin kendi yapisi belirliyor. Overlap chunk'larin yalnizca ~%11'inde devreye giriyor: overlap keyfi noktadan kesince anlamin ikiye bolunmesini telafi eden bir yamadir, biz keyfi noktadan degil baslik sinirindan kestigimiz icin sadece istisnai buyuk bolumlerde gerekiyor.

Neden 320 token tavan. Teknik zorunluluk degil - model 8192 token aliyor. Sebep arama kalitesi: bir chunk ne kadar cok konu icerirse vektoru o kadar ortalamaya kayar, pozitif ve negatif sorularin skorlari birbirine yaklasir, esik ayirt edemez hale gelir. Tavan konu safligini koruyan sinir.

Sonuc: 402 makale -> 3138 chunk, medyan 106 token, p90 244, max 320 (tavani asan: 0), %89'i baslik tasiyor.

2. Embedding modeli

`magibu/embeddingmagibu-200m`

Boyut (dimension)768, L2-normalize
Context window8.192 token
Parametre~200M (Gemma3 govdeli)
Poolingmean + 2 dense (768 -> 3072 -> 768)

Neden secildi: Turkce'ye ozel uyarlanmis (cross-lingual tokenizer surgery + offline distillation), 8K context uzun bolumleri kesmeden aliyor, 200M parametre 8 GB VRAM'e rahat sigiyor - 3138 chunk 18 saniyede gomuldu. Ciktilar L2-normalize oldugu icin kosinus benzerligi = nokta carpimi.

Model asimetrik - prompt kullanimi zorunlu. config_sentence_transformers.json:

"query":    "task: search result | query: "
"document": "title: none | text: "

Chunk'lar document, sorular query prompt'u ile gomuluyor. Bu atlanirsa model yine calisir ama skor dagilimi kayar ve esik analizi anlamsizlasir.

Baslik enjeksiyonu: document prompt'undaki title: none alanina gercek baslik konuyor. Hastane metinleri anafora dolu ("Bu hastalikta...", "Tedavi sureci..."); tek basina chunk cogu zaman neyden bahsettigini soylemiyor. chunk_text sutunu ham kaliyor - baslik yalnizca vektor uretiminde kullanildi.

float32 tercih edildi: model varsayilan olarak bfloat16 yukleniyor ve o hassasiyette L2 normlar 0,996-1,004 arasinda kayiyor. normalize_embeddings=True de cozmuyor (normalizasyon da bf16 icinde). float32'de normlar tam 1,0.

Kullanim

python
from datasets import load_dataset
import numpy as np
from sentence_transformers import SentenceTransformer

veri = load_dataset("yoitsmeyusuf/turkce-tibbi-vektor-veri-seti", split="train")
vektorler = np.array(veri["chunk_vector"], dtype=np.float32)

model = SentenceTransformer("magibu/embeddingmagibu-200m")
soru = model.encode(["safra kesesi tasi nasil tedavi edilir"], prompt_name="query")[0]

skorlar = vektorler @ soru          # L2-normalize -> nokta carpimi = kosinus
en_iyi = int(np.argmax(skorlar))
if skorlar[en_iyi] < 0.56:
    print("Bu sorunun cevabi dokumanlarimda yer almamaktadir.")
else:
    print(veri[en_iyi]["chunk_text"], veri[en_iyi]["url"])

3. Esik (threshold) analizi

Secilen esik: 0.56 — 30 soruluk test setinde 28/30 (20/20 pozitif, 8/10 negatif).

Esik bastan secilmedi, 0,30-0,90 arasi 0,01 adimla supuruldu. Her esik degeri iki hata turunu dengeliyor: esik cok yuksekse cevabi olan soruya "bilmiyorum" denir, cok dusukse alakasiz soruya uydurma cevap uretilir.

esikpozitifnegatiftoplam
0.4020/205/1025/30
0.5020/206/1026/30
0.5320/207/1027/30
0.5520/208/1028/30
0.5620/208/1028/30
0.5719/208/1027/30
0.6015/208/1023/30
0.6313/2010/1023/30
0.709/2010/1019/30

Test seti. 20 pozitif soru chunk'lardan turetildi (soru yazip cevabini aramak degil): her sorunun gold_chunk_id'si kayitli, boylece erisim goz karari degil olcum. 10 negatif soru bilerek uc gruba ayrildi - hepsi "Fenerbahce kac sampiyonluk aldi" tipinde olsaydi esik analizi sahte cikardi, 0,2 de 0,6 da ayni sonucu verirdi.

grupminmedyanmax0.56'da dogru
pozitif (20)0.56960.69200.794320/20
alan disi (3)0.18030.18920.21473/3
konu yok (3)0.36470.54380.62672/3
yakin-kacirma (4)0.39390.47710.60953/4

skor dagilimi esik supurmesi

Neden tam 0.56. Plato ortasi secildi; bu ayni zamanda karar bosluğunun ortasi:

en yuksek dogru elenen negatif : 0.5438
                        esik   : 0.5600
en dusuk pozitif               : 0.5696

Erisim (recall): gold chunk 20/20 soruda ilk 5 sonuc icinde (top-1'de 13/20). Olcut bilerek "ilk 5" - LLM'e ilk K chunk birden veriliyor ve ayni bolumun kardes chunk'lari cogu zaman gold kadar gecerli kaynak.

Vektor veritabani: ChromaDB, hnsw:space=cosine. Iki tuzak: Chroma'nin varsayilan mesafesi L2'dir (acikca cosine verilmeli) ve Chroma distance dondurur, benzerlik degil -> benzerlik = 1 - distance. HNSW yaklasik arama yaptigi icin 30 sorunun tamami numpy ile kesin kosinus hesabiyla karsilastirildi: sapma 0/30.

Esigin yapisal siniri

Esikle elenemeyen 2 negatif soru var ve sebepleri ogretici:

  • —"Sıtma hastalığı hangi sivrisinek türüyle bulaşır?" — 0.6267
  • —"Laparoskopik kolesistektomi ameliyatı Medipol'de kaç TL tutuyor?" — 0.6095

Birincisinde korpusta sitma yok ama "Sivrisinek Isirigina Ne Iyi Gelir?" makalesi var - vektor konu yakinligini goruyor. Ikincisinde kolesistektomi korpusta var, sadece fiyat bilgisi yok.

Yani esik konu yoklugunu filtreliyor, bilgi yoklugunu filtrelemiyor. Kosinus benzerligi "bu metin bu soruyla ayni konuda mi" sorusunu cevapliyor, "bu metin bu sorunun cevabini iceriyor mu" sorusunu degil. Bu vektor aramanin yapisal siniri, ayar hatasi degil; kapatmanin yolu ikinci bir kapi (LLM'e "verilen metinde cevap yoksa bilmiyorum de" talimati + ciktinin kaynaga karsi dogrulanmasi).

Kod

Veri setini ureten ve olcen kodlar bu reponun kod/ klasorunde:

dosyais
ayarlar.pymodel, hastane, esik, yol sabitleri
chunklama.pyparcalama mantigi (tek basina calisirsa ornek doker)
1_veri_hazirla.pyindir -> ornekle -> chunk'la
2_gom_ve_indeksle.pygom -> ChromaDB + parquet
3_push_dataset.pybu repoyu olusturur
4_esik_analizi.py30 soruyu kos -> esik supur -> gorseller
arama.py / ara.pyarama katmani + komut satiri arayuzu
sorular.json20 pozitif (goldchunkid'li) + 10 negatif
check_env.pypaket / erisim / cikti kontrolu
bash
python 1_veri_hazirla.py && python 2_gom_ve_indeksle.py && python 4_esik_analizi.py
python ara.py "safra kesesi tasi nasil tedavi edilir"

Kaynak veri seti gated: once dataset sayfasinda "Agree and access" tiklanmali.