Spaces:
Sleeping
Sleeping
| import argparse | |
| import json | |
| import math | |
| import os | |
| import time | |
| import logging | |
| from datetime import datetime | |
| from collections import defaultdict | |
| from typing import Dict, List, Tuple, Any | |
| # Kendi modüllerimizden import | |
| from retriever import LegalRetriever, detect_kanun, extract_madde | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s [%(levelname)s] %(name)s — %(message)s", | |
| datefmt="%H:%M:%S", | |
| ) | |
| log = logging.getLogger("LawAgent.Evaluator") | |
| # ═══════════════════════════════════════════════════════════════════════════════ | |
| # HİBRİT BENCHMARK SETİ (Mevzuat + İçtihat) | |
| # Sorgu, Beklenen Kanun, Beklenen Madde Listesi, Beklenen Karar ID (Opsiyonel) | |
| # ═══════════════════════════════════════════════════════════════════════════════ | |
| BENCHMARK = [ | |
| # ───────────────────────────────────────────── | |
| # TBK — Türk Borçlar Kanunu (6098) | |
| # ───────────────────────────────────────────── | |
| # Sözleşmenin Kurulması & İrade Sakatlıkları | |
| ( | |
| "Sözleşmenin esaslı noktalarında irade uyuşması olmadan sözleşme kurulmuş sayılır mı?", | |
| "TBK", | |
| ["1", "2"], | |
| None, | |
| ), | |
| ( | |
| "Aldatma (hile) durumunda karşı tarafın sözleşmeyi iptal etme hakkının kullanım süresi nedir?", | |
| "TBK", | |
| ["36", "39"], | |
| None, | |
| ), | |
| ( | |
| "Aşırı yararlanma (gabin) şartları nelerdir ve hâkimin sözleşmeyi değiştirme yetkisi var mıdır?", | |
| "TBK", | |
| ["28"], | |
| None, | |
| ), | |
| # Haksız Fiil Sorumluluğu | |
| ( | |
| "Haksız fiil sorumluluğunun dört temel unsuru nedir ve ispat yükü kime aittir?", | |
| "TBK", | |
| ["49", "50"], | |
| None, | |
| ), | |
| ( | |
| "Haksız fiilden doğan tazminat davasında zamanaşımı süreleri nelerdir?", | |
| "TBK", | |
| ["72"], | |
| None, | |
| ), | |
| ( | |
| "Tehlike sorumluluğunda zarar görenin tazminat talep edebilmesinin koşulları nelerdir?", | |
| "TBK", | |
| ["71"], | |
| None, | |
| ), | |
| ( | |
| "Adam çalıştıranın sorumluluğunda kurtuluş beyyinesi nasıl işler?", | |
| "TBK", | |
| ["66"], | |
| None, | |
| ), | |
| ( | |
| "Kişilik hakkı ihlalinde manevi tazminatın takdirinde hâkim hangi ölçütleri gözetir?", | |
| "TBK", | |
| ["58"], | |
| None, | |
| ), | |
| # Borçların İfası & Temerrüt | |
| ( | |
| "Muaccel bir borcun borçlusu hangi şartla temerrüde düşer ve ihtar gerekmediği haller nelerdir?", | |
| "TBK", | |
| ["117"], | |
| None, | |
| ), | |
| ( | |
| "Temerrüde düşen borçlunun beklenmedik halden (mücbir sebepten) doğan sorumluluğu nedir?", | |
| "TBK", | |
| ["119"], | |
| None, | |
| ), | |
| ( | |
| "Alacaklı temerrüdünün şartları ve borçlunun ifa etmeksizin serbest kalma hakkı nedir?", | |
| "TBK", | |
| ["106", "107"], | |
| None, | |
| ), | |
| ( | |
| "Karşılıklı borç yükleyen sözleşmelerde süre verilmeksizin sözleşmeden dönülebilecek haller nelerdir?", | |
| "TBK", | |
| ["124"], | |
| None, | |
| ), | |
| # Sözleşmenin Sona Ermesi & Zamanaşımı | |
| ( | |
| "Borçlunun ikrarının zamanaşımını keseceği ve yeni sürenin nasıl başlayacağı hükmü nedir?", | |
| "TBK", | |
| ["154"], | |
| None, | |
| ), | |
| ( | |
| "Zamanaşımının durmasına yol açan haller nelerdir?", | |
| "TBK", | |
| ["153"], | |
| None, | |
| ), | |
| # Çeşitli Sözleşme Türleri | |
| ( | |
| "Satım sözleşmesinde ayıbın gizlenmesi (hile ile saklama) durumunda satıcının sorumluluğu sınırlanabilir mi?", | |
| "TBK", | |
| ["221"], | |
| None, | |
| ), | |
| ( | |
| "Kira sözleşmesinde kiraya verenin ayıba karşı tekeffül borcu ve kiracının seçimlik hakları nelerdir?", | |
| "TBK", | |
| ["305", "306"], | |
| None, | |
| ), | |
| ( | |
| "Kiracının kira bedelini ödememesi hâlinde kiraya verenin yazılı bildirim yaparak tahliye isteme süreci nasıl işler?", | |
| "TBK", | |
| ["315"], | |
| None, | |
| ), | |
| ( | |
| "Konut ve çatılı işyeri kiralarında kiracı aleyhine düzenleme yasağının kapsamı nedir?", | |
| "TBK", | |
| ["346"], | |
| None, | |
| ), | |
| ( | |
| "Eser sözleşmesinde yaklaşık bedelin aşılması hâlinde iş sahibinin dönme hakkı ne zaman doğar?", | |
| "TBK", | |
| ["482"], | |
| None, | |
| ), | |
| ( | |
| "Vekâletin sona ermesinde vekâlet verenin ölümü hâlinde vekilin yükümlülükleri nelerdir?", | |
| "TBK", | |
| ["513"], | |
| None, | |
| ), | |
| ( | |
| "Kefalet sözleşmesinin geçerliliği için aranan yazılı şekil ve eşin rızasına ilişkin kurallar nelerdir?", | |
| "TBK", | |
| ["583", "584"], | |
| None, | |
| ), | |
| # Borç İlişkilerinin Çeşitli Konuları | |
| ( | |
| "Alacağın devri (temlik) sözleşmesinin geçerlilik şartları ve borçlunun bilgilendirilmesinin sonuçları nelerdir?", | |
| "TBK", | |
| ["184", "186"], | |
| None, | |
| ), | |
| ( | |
| "Müteselsil borçlulukta borçlulardan birinin ödeme yapması diğer borçluların borcunu nasıl etkiler?", | |
| "TBK", | |
| ["166", "167"], | |
| None, | |
| ), | |
| ( | |
| "Sebepsiz zenginleşen kişinin iyiniyetli olması hâlinde geri verme yükümlülüğünün kapsamı nasıl daralır?", | |
| "TBK", | |
| ["79", "80"], | |
| None, | |
| ), | |
| ( | |
| "Borcun bizzat borçlu tarafından ifa edilmesinde alacaklının menfaatinin varlığı hangi ölçütle belirlenir?", | |
| "TBK", | |
| ["83"], | |
| None, | |
| ), | |
| # ───────────────────────────────────────────── | |
| # TKHK — Tüketicinin Korunması Hakkında Kanun (6502) | |
| # ───────────────────────────────────────────── | |
| # Ayıplı Mal & Hizmet | |
| ( | |
| "Ayıplı malın tespitinde 'teslim tarihinden itibaren altı ay' içinde ortaya çıkan ayıplara ilişkin ispat karinesi nasıl işler?", | |
| "TKHK", | |
| ["10"], | |
| None, | |
| ), | |
| ( | |
| "Ayıplı mal durumunda tüketicinin dört seçimlik hakkı nelerdir ve satıcı, üretici, ithalatçının müteselsil sorumluluğu nasıl düzenlenir?", | |
| "TKHK", | |
| ["11"], | |
| None, | |
| ), | |
| ( | |
| "Ayıplı hizmet hâlinde tüketicinin seçimlik hakları ve sağlayıcının ücretsiz yeniden ifa yükümlülüğünün azami süresi nedir?", | |
| "TKHK", | |
| ["15"], | |
| None, | |
| ), | |
| ( | |
| "Tüketici sözleşmelerinde haksız şartların kesin hükümsüzlüğü ve sözleşmenin geri kalanının geçerliliği nasıl korunur?", | |
| "TKHK", | |
| ["5"], | |
| None, | |
| ), | |
| # Mesafeli & İşyeri Dışı Sözleşmeler | |
| ( | |
| "Mesafeli sözleşmelerde tüketicinin 14 günlük cayma hakkına getirilen istisnalar nelerdir?", | |
| "TKHK", | |
| ["48"], | |
| None, | |
| ), | |
| ( | |
| "İşyeri dışında kurulan sözleşmelerde satıcının tüketiciyi bilgilendirme yükümlülüğü ve cayma süresi nedir?", | |
| "TKHK", | |
| ["47"], | |
| None, | |
| ), | |
| # Tüketici Kredisi & Finansman | |
| ( | |
| "Tüketici kredisi sözleşmesinin geçerlilik şartları ve kredi verenin geçersizliği tüketici aleyhine ileri süremeyeceği kuralı nedir?", | |
| "TKHK", | |
| ["23"], | |
| None, | |
| ), | |
| ( | |
| "Tüketici kredisinde belirsiz süreli sözleşmelerde faiz artışının tüketiciye bildirim yükümlülüğü ve tüketicinin sözleşmeden çıkma hakkı nasıl işler?", | |
| "TKHK", | |
| ["26"], | |
| None, | |
| ), | |
| ( | |
| "Tüketici kredisinin erken kapatılması hâlinde tüketicinin faiz ve masraf indiriminden yararlanma hakkı nedir?", | |
| "TKHK", | |
| ["27"], | |
| None, | |
| ), | |
| ( | |
| "Konut finansmanı sözleşmelerinde tüketicinin temerrüdü hâlinde kalan borcun tamamının muaccel kılınabilmesinin şartları nelerdir?", | |
| "TKHK", | |
| ["33"], | |
| None, | |
| ), | |
| # Tüketici Hakem Heyeti & Uyuşmazlık Çözümü | |
| ( | |
| "Tüketici hakem heyetine başvuru parasal sınırları nelerdir ve verilen kararların bağlayıcılık rejimi nasıl işler?", | |
| "TKHK", | |
| ["68", "70"], | |
| None, | |
| ), | |
| ( | |
| "Tüketicinin konut alımından kaynaklanan uyuşmazlıklarda yetkili mahkeme hangisidir?", | |
| "TKHK", | |
| ["73"], | |
| None, | |
| ), | |
| # Özel Sözleşme Türleri (TKHK) | |
| ( | |
| "Devre tatil sözleşmelerinde tüketicinin cayma hakkı süresi ve sözleşmeden dönme bedeline ilişkin yasak nedir?", | |
| "TKHK", | |
| ["50"], | |
| None, | |
| ), | |
| ( | |
| "Paket tur sözleşmesinde düzenleyicinin seyahat öncesi esaslı değişiklik yapması hâlinde tüketicinin hakları nelerdir?", | |
| "TKHK", | |
| ["51"], | |
| None, | |
| ), | |
| ( | |
| "Abonelik sözleşmelerinin tüketici tarafından feshedilmesi hâlinde sağlayıcının depozito iade yükümlülüğü ve süresi nedir?", | |
| "TKHK", | |
| ["52"], | |
| None, | |
| ), | |
| ( | |
| "Garanti belgesi düzenleme yükümlülüğüne aykırılık hâlinde tüketiciye tanınan ek haklar nelerdir?", | |
| "TKHK", | |
| ["56"], | |
| None, | |
| ), | |
| ( | |
| "Sipariş edilmeyen mal veya hizmet gönderilmesi durumunda satıcı tüketiciden herhangi bir bedel talep edebilir mi?", | |
| "TKHK", | |
| ["7"], | |
| None, | |
| ), | |
| # ───────────────────────────────────────────── | |
| # TTK — Türk Ticaret Kanunu (6102) | |
| # ───────────────────────────────────────────── | |
| # Ticari İşletme & Tacir | |
| ( | |
| "Tacir sıfatının kazanılması ve tacire özgü yükümlülükler (basiretli işletme, ticaret unvanı, tescil) nelerdir?", | |
| "TTK", | |
| ["11", "18"], | |
| None, | |
| ), | |
| ( | |
| "Ticaret siciline tescil ve ilanın olumlu (müspet) ve olumsuz (menfi) aleniyet etkisi nedir?", | |
| "TTK", | |
| ["36", "37"], | |
| None, | |
| ), | |
| ( | |
| "Ticari işlemlerde fatura ve teyit mektubuna itiraz edilmemesinin hukuki sonuçları nelerdir?", | |
| "TTK", | |
| ["21"], | |
| None, | |
| ), | |
| # Haksız Rekabet | |
| ( | |
| "Haksız rekabet sayılan dürüstlük kuralına aykırı davranışlara karşı açılabilecek hukuk davalarının türleri nelerdir?", | |
| "TTK", | |
| ["56"], | |
| None, | |
| ), | |
| ( | |
| "Haksız rekabet nedeniyle açılacak hukuk davalarında zamanaşımı süresi ve başlangıç anı nedir?", | |
| "TTK", | |
| ["60"], | |
| None, | |
| ), | |
| # Anonim Şirket | |
| ( | |
| "Anonim şirket yönetim kurulunun devredilemez ve vazgeçilemez görev ve yetkileri nelerdir?", | |
| "TTK", | |
| ["375"], | |
| None, | |
| ), | |
| ( | |
| "2024 TTK değişikliğiyle anonim şirket yönetim kurulunu toplantıya çağırma yetkisi kime tanınmıştır?", | |
| "TTK", | |
| ["392"], | |
| "18-1", # PwC bülteni referansı | |
| ), | |
| ( | |
| "Anonim şirket genel kurul kararlarının butlanı ile iptalinin farkları nelerdir ve iptal davası açma süresi nedir?", | |
| "TTK", | |
| ["445", "447"], | |
| None, | |
| ), | |
| ( | |
| "Anonim şirkette nama yazılı pay devrinin pay defterine kaydından şirketin hangi gerekçelerle kaçınabileceği durumlar nelerdir?", | |
| "TTK", | |
| ["490", "493"], | |
| None, | |
| ), | |
| ( | |
| "Hamiline yazılı pay senetlerinin devri ve MKK'ya bildirim yükümlülüğü nasıl düzenlenmiştir?", | |
| "TTK", | |
| ["489", "486"], | |
| None, | |
| ), | |
| ( | |
| "Anonim şirkette yönetim kurulu üyesinin azlinde gündeme bağlılık ilkesi ve istisnaları nelerdir?", | |
| "TTK", | |
| ["413"], | |
| None, | |
| ), | |
| ( | |
| "Anonim şirket yönetim kurulu üyelerinin şirkete, pay sahiplerine ve alacaklılara karşı tazminat sorumluluğunun şartları nelerdir?", | |
| "TTK", | |
| ["553"], | |
| None, | |
| ), | |
| # Limited Şirket | |
| ( | |
| "Limited şirkette esas sermaye payının devri için gereken noter onaylı yazılı şekil şartı ve genel kurul onayı zorunluluğu nedir?", | |
| "TTK", | |
| ["595"], | |
| None, | |
| ), | |
| ( | |
| "Limited şirkette müdürün devredilemez ve vazgeçilemez görev ve yetkileri nelerdir?", | |
| "TTK", | |
| ["625"], | |
| None, | |
| ), | |
| ( | |
| "Limited şirkette ortaklar genel kurulunun devredilemez yetkileri nelerdir?", | |
| "TTK", | |
| ["616"], | |
| None, | |
| ), | |
| ( | |
| "Limited şirkette ortağın haklı sebeple şirketten çıkma ve şirket tarafından çıkarılma halleri nasıl düzenlenmiştir?", | |
| "TTK", | |
| ["638", "640"], | |
| None, | |
| ), | |
| # Kıymetli Evrak | |
| ( | |
| "Poliçede kabul etmeme veya ödememe protestosunun çekilme süresi ve müracaat haklarına etkisi nedir?", | |
| "TTK", | |
| ["713", "714"], | |
| None, | |
| ), | |
| ( | |
| "Çekin ibraz süreleri nelerdir ve ibraz edilmeksizin süresi geçen çekte hamilin keşideciye ve ciranta karşı haklarının durumu ne olur?", | |
| "TTK", | |
| ["796", "808"], | |
| None, | |
| ), | |
| ( | |
| "Karşılıksız çeken hakkında hamilin talep edebileceği tazminat oranı ve cezai yaptırımlar nelerdir?", | |
| "TTK", | |
| ["814"], | |
| None, | |
| ), | |
| ( | |
| "Bonoyu (emre yazılı senedi) poliçeden ayıran temel özellikler ve ciranta sorumluluğu nasıl düzenlenir?", | |
| "TTK", | |
| ["776", "777"], | |
| None, | |
| ), | |
| # Ticari İşlemler | |
| ( | |
| "Ticari işlerde gecikme faizinin belirlenmesinde tarafların serbestisi ve Merkez Bankası referans faizinin rolü nedir?", | |
| "TTK", | |
| ["1530"], | |
| None, | |
| ), | |
| ( | |
| "Ticari defterlerin ispat aracı olarak kullanılmasının şartları ve aleyhine delil teşkil etmesi hâlleri nelerdir?", | |
| "TTK", | |
| ["64", "222"], | |
| None, | |
| ), | |
| ] | |
| # ═══════════════════════════════════════════════════════════════════════════════ | |
| # METRİK FONKSİYONLARI (İçtihat Destekli) | |
| # ═══════════════════════════════════════════════════════════════════════════════ | |
| def is_hit( | |
| result: Dict, expected_maddeler: List[str], expected_decision: str = None | |
| ) -> bool: | |
| """ | |
| Bir sonucun 'doğru' kabul edilmesi için: | |
| Ya beklenen maddelerden biri olmalı YA DA beklenen karar ID'si olmalı. | |
| """ | |
| res_art = str(result.get("article_no", "")) | |
| res_dec = str(result.get("decision_id", "")) | |
| if res_art in expected_maddeler: | |
| return True | |
| if expected_decision and res_dec == expected_decision: | |
| return True | |
| return False | |
| def recall_at_k( | |
| results: List[Dict], expected_m: List[str], expected_d: str, k: int | |
| ) -> float: | |
| if not expected_m and not expected_d: | |
| return 0.0 | |
| found_count = 0 | |
| seen_targets = set() | |
| for r in results[:k]: | |
| if is_hit(r, expected_m, expected_d): | |
| # Aynı madde/kararın farklı chunklarını mükerrer saymamak için | |
| target_key = r.get("article_no") or r.get("decision_id") | |
| if target_key not in seen_targets: | |
| found_count += 1 | |
| seen_targets.add(target_key) | |
| total_expected = len(expected_m) + (1 if expected_d else 0) | |
| return found_count / total_expected | |
| def mrr_at_k( | |
| results: List[Dict], expected_m: List[str], expected_d: str, k: int | |
| ) -> float: | |
| for rank, r in enumerate(results[:k], 1): | |
| if is_hit(r, expected_m, expected_d): | |
| return 1.0 / rank | |
| return 0.0 | |
| def ndcg_at_k( | |
| results: List[Dict], expected_m: List[str], expected_d: str, k: int | |
| ) -> float: | |
| dcg = sum( | |
| 1.0 / math.log2(i + 1) | |
| for i, r in enumerate(results[:k], 1) | |
| if is_hit(r, expected_m, expected_d) | |
| ) | |
| total_targets = len(expected_m) + (1 if expected_d else 0) | |
| idcg = sum(1.0 / math.log2(i + 1) for i in range(1, min(total_targets, k) + 1)) | |
| return dcg / idcg if idcg > 0 else 0.0 | |
| # ═══════════════════════════════════════════════════════════════════════════════ | |
| # DEĞERLENDİRME MOTORU | |
| # ═══════════════════════════════════════════════════════════════════════════════ | |
| def run_evaluation(retriever: LegalRetriever, k: int = 10): | |
| stats = {"recall": [], "mrr": [], "ndcg": [], "hit": [], "time": []} | |
| detailed_results = [] | |
| print(f"\n🚀 {len(BENCHMARK)} benchmark sorgusu test ediliyor...") | |
| for query, kanun, maddeler, karar_id in BENCHMARK: | |
| t0 = time.time() | |
| results = retriever.retrieve(query, k=k) | |
| duration = (time.time() - t0) * 1000 | |
| rec = recall_at_k(results, maddeler, karar_id, k) | |
| mrr = mrr_at_k(results, maddeler, karar_id, k) | |
| ndcg = ndcg_at_k(results, maddeler, karar_id, k) | |
| hit = 1 if mrr > 0 else 0 | |
| stats["recall"].append(rec) | |
| stats["mrr"].append(mrr) | |
| stats["ndcg"].append(ndcg) | |
| stats["hit"].append(hit) | |
| stats["time"].append(duration) | |
| detailed_results.append( | |
| { | |
| "query": query, | |
| "hit": hit, | |
| "mrr": mrr, | |
| "top_result": results[0]["text"][:100] if results else "Yok", | |
| } | |
| ) | |
| status = "✅" if hit else "❌" | |
| print(f" {status} Sorgu: {query[:50]}... (MRR: {mrr:.2f})") | |
| # Ortalama Hesaplama | |
| avg_stats = {m: sum(v) / len(v) for m, v in stats.items()} | |
| _print_report(avg_stats, k) | |
| def _print_report(results: Dict, k: int): | |
| print(f"\n{'='*60}") | |
| print(f"📊 LAWAGENT RETRIEVAL PERFORMANS RAPORU (k={k})") | |
| print(f"{'='*60}") | |
| print(f" Recall@{k} : {results['recall']:.4f} (Hedef: ≥0.75)") | |
| print(f" MRR@{k} : {results['mrr']:.4f} (Hedef: ≥0.60)") | |
| print(f" nDCG@{k} : {results['ndcg']:.4f} (Hedef: ≥0.70)") | |
| print(f" Hit Rate@{k} : {results['hit']:.4f}") | |
| print(f" Ort. Süre : {results['time']:.1f} ms") | |
| print(f"{'='*60}") | |
| # TÜBİTAK Hedef Kontrolü | |
| if results["recall"] >= 0.75 and results["mrr"] >= 0.60: | |
| print("🎉 TEBRİKLER: Proje formu hedeflerine ulaşıldı!") | |
| else: | |
| print("⚠️ DİKKAT: Bazı metrikler hedef değerlerin altında.") | |
| if __name__ == "__main__": | |
| # Önce retriever'ı başlatalım (Cache varsa hızlı yüklenir) | |
| r = LegalRetriever(quantize=False) | |
| run_evaluation(r, k=10) | |