YOKPilot3 / verified_query_contracts.py
mfirat007's picture
Certify six showcase answers with fail-closed source contracts
751e051 verified
Raw
History Blame Contribute Delete
12.9 kB
from __future__ import annotations
from dataclasses import dataclass
from sources import format_clause_sources, get_article_source
from utils import normalize_for_search
@dataclass(frozen=True)
class VerifiedSourceScope:
document_id: str
article_id: str
evidence_terms: tuple[str, ...]
@dataclass(frozen=True)
class VerifiedQueryContract:
contract_id: str
question: str
answer_markdown: str
sources: tuple[VerifiedSourceScope, ...]
full_article_source: VerifiedSourceScope | None = None
_RECTOR_DUTIES_ANSWER = """**Sonuç — 2547 sayılı Kanun Madde 13:** Rektör, üniversite veya yüksek teknoloji enstitüsü tüzel kişiliğini temsil eder ve aşağıdaki görevleri yürütür:
1. Üniversite kurullarına başkanlık eder; yükseköğretim üst kuruluşlarının kararlarını uygular; üniversite kurullarının önerilerini inceleyip karara bağlar ve bağlı kuruluşlar arasında düzenli çalışmayı sağlar.
2. Her eğitim-öğretim yılı sonunda ve gerektiğinde eğitim-öğretim, bilimsel araştırma ve yayım faaliyetleri hakkında Üniversitelerarası Kurula bilgi verir.
3. Birimlerin, üniversite yönetim kurulunun ve senatonun görüşlerini aldıktan sonra yatırım programı, bütçe ve kadro ihtiyaçlarını hazırlayıp Yükseköğretim Kuruluna sunar.
4. Gerekli gördüğünde öğretim elemanlarının ve diğer personelin görev yerlerini değiştirebilir veya yeni görevler verebilir.
5. Üniversitenin birimleri ve her düzeydeki personeli üzerinde genel gözetim ve denetim yapar.
6. Kanunun kendisine verdiği diğer görevleri yerine getirir.
**Birinci derece yetki ve sorumluluk:** Öğretim kapasitesinin etkin kullanılması ve geliştirilmesi, öğrencilere sosyal hizmet sağlanması, gerektiğinde güvenlik önlemleri alınması, eğitim-öğretim ile araştırma-yayım faaliyetlerinin planlanıp yürütülmesi ve bilimsel/idari gözetim ile sonuçların takibi rektörün birinci derecede yetki ve sorumluluğundadır."""
_UNIVERSITY_ALLOWANCE_ANSWER = """**Sonuç — 2914 sayılı Kanun Madde 12:** Üniversite ödeneği, 657 sayılı Kanuna tabi en yüksek Devlet memurunun brüt aylık tutarı (ek gösterge dâhil) esas alınarak aşağıdaki oranlarda her ay ödenir:
| Görev, kadro veya derece | Oran |
|---|---:|
| Rektör, rektör yardımcısı, dekan, dekan yardımcısı, yüksekokul müdürü olan profesörler ile profesör kadrosunda üç yılını tamamlayanlar | %245 |
| Diğer profesörler | %215 |
| Doçentler | %175 |
| Doktor öğretim üyeleri | %175 |
| Diğer öğretim elemanlarından birinci dereceden aylık alanlar | %130 |
| İkinci dereceden aylık alanlar | %117 |
| Üçüncü dereceden aylık alanlar | %110 |
| Dördüncü ve beşinci dereceden aylık alanlar | %104 |
| Diğer derecelerden aylık alanlar | %98 |
**Sınırlar:** Ödenek damga vergisi dışında vergiye tabi değildir ve kısmi statüde görev yapanlara ödenmez."""
_REMOTE_TEACHING_ANSWER = """**Sonuç:** 2547 sayılı Kanunda uzaktan öğretim tek bir maddede değil, birbirini tamamlayan dört ana maddede düzenlenir:
- **Madde 44:** Uzaktan öğretim programlarının Yükseköğretim Kurulu kararıyla açılması; alan, ders, kredi, materyal, sınav ve kurumlararası protokol esasları; öğretim elemanı ödemeleri ve örgün programdaki bazı derslerin uzaktan verilmesi.
- **Madde 36:** Uzaktan öğretimde verilen derslerin örgün öğretimde kaç ders saatine karşılık geldiğini belirleme yetkisi Yükseköğretim Kurulundadır.
- **Madde 46:** Uzaktan öğretim öğrencilerinin öğrenim ücreti, cari hizmet maliyeti ve kredi başına ücret hesabı düzenlenir.
- **Madde 48:** Uzaktan öğretim materyallerinin hazırlanması, çoğaltılması, öğrencilere sunulması ve telif esasları düzenlenir.
Bu nedenle program açma ve yürütme için Madde 44; ders yükü için Madde 36; öğrenci ücreti için Madde 46; materyal ve telif için Madde 48 birlikte okunmalıdır."""
_MINIMUM_FACULTIES_ANSWER = """**Sonuç — 2809 sayılı Kanun Madde 3:** Bir üniversitede **en az üç fakültenin bulunması zorunludur**.
Aynı madde üniversitenin fakülte, enstitü, yüksekokul, konservatuvar, meslek yüksekokulu, araştırma ve uygulama merkezi gibi birimlerden oluşabileceğini de belirtir. Alt birimlerin teşkili, birleştirilmesi, kaldırılması ve işleyişi ise 2547 sayılı Kanunun 7. maddesi uyarınca Yükseköğretim Kurulunca düzenlenir."""
_COURSE_LOAD_RELATION_ANSWER = """**Sonuç:** 2547 sayılı Kanunun 36. maddesi zorunlu haftalık ders yükünün tabanını; 2914 sayılı Kanunun 11. maddesi ise bu yükün üzerindeki çalışmanın hangi şartlarla ek ders ücretine dönüşeceğini belirler.
**2547 Madde 36 — zorunlu yük:**
- Öğretim üyeleri için haftada en az **10 saat**,
- Öğretim görevlileri için haftada en az **12 saat** ders yükü öngörülür.
**2914 Madde 11 — yükün üzerindeki çalışma:** Ek ders ücreti ancak;
1. 2547 Madde 36'ya göre zorunlu ders yükünün dışında kalan çalışma için,
2. Yükseköğretim Kurulunca belirlenen mecburi veya isteğe bağlı ders ve faaliyetler kapsamında,
3. Ders veya faaliyetin haftalık ders programında yer alması,
4. Fiilen yapılması şartıyla ödenir.
Ücretlendirilecek süre en çok **20 saat**, ikinci öğretimde ise ayrıca en çok **10 saattir**. Ders yükü tamamlanırken öncelikle normal örgün öğretimde verilen ders ve faaliyetler dikkate alınır. Teorik ders dışındaki faaliyetlerin hangi ölçüde ders yükünden sayılacağı da Madde 11'deki özel sınırlara tabidir.
**Normatif bağ:** Madde 36 “maaş karşılığı zorunlu ders yükünü”, Madde 11 ise bu eşik aşıldıktan sonra doğan ek ders ücretinin koşullarını ve hesabını kurar; maddeler birbirinin alternatifi değil, ardışık iki aşamasıdır."""
VERIFIED_QUERY_CONTRACTS = (
VerifiedQueryContract(
contract_id="showcase_rector_duties",
question="2547 sayılı Kanuna göre rektörün görev, yetki ve sorumlulukları nelerdir?",
answer_markdown=_RECTOR_DUTIES_ANSWER,
sources=(
VerifiedSourceScope(
"TR-KANUN-2547",
"Madde 13",
("üniversite kurullarına başkanlık", "birinci derecede yetkili ve sorumludur"),
),
),
),
VerifiedQueryContract(
contract_id="showcase_university_allowance",
question="2914 sayılı Kanuna göre üniversite ödeneği kimlere ve hangi ölçütlere göre ödenir?",
answer_markdown=_UNIVERSITY_ALLOWANCE_ANSWER,
sources=(
VerifiedSourceScope(
"TR-KANUN-2914",
"Madde 12",
("% 245", "% 215", "% 175", "% 130", "% 98", "kısmi statüde"),
),
),
),
VerifiedQueryContract(
contract_id="showcase_remote_teaching_inventory",
question="Uzaktan öğretimle ilgili 2547 sayılı Kanunda hangi maddeler vardır ve her biri neyi düzenler?",
answer_markdown=_REMOTE_TEACHING_ANSWER,
sources=(
VerifiedSourceScope("TR-KANUN-2547", "Madde 44", ("uzaktan öğretim programları açılabilir",)),
VerifiedSourceScope("TR-KANUN-2547", "Madde 36", ("uzaktan öğretim programlarında",)),
VerifiedSourceScope("TR-KANUN-2547", "Madde 46", ("uzaktan öğretimde ise öğrenim ücreti",)),
VerifiedSourceScope("TR-KANUN-2547", "Madde 48", ("uzaktan öğretim ilkelerine göre",)),
),
),
VerifiedQueryContract(
contract_id="showcase_article_40_full_text",
question="2547 sayılı Kanun Madde 40 ne diyor?",
answer_markdown="",
sources=(
VerifiedSourceScope(
"TR-KANUN-2547",
"Madde 40",
("ders yükünü dolduramadıkları", "kadroları beş yıl süre ile saklı tutulur"),
),
),
full_article_source=VerifiedSourceScope(
"TR-KANUN-2547",
"Madde 40",
("ders yükünü dolduramadıkları", "kadroları beş yıl süre ile saklı tutulur"),
),
),
VerifiedQueryContract(
contract_id="showcase_minimum_faculties",
question="2809 sayılı Kanuna göre bir üniversitede en az kaç fakültenin bulunması zorunludur?",
answer_markdown=_MINIMUM_FACULTIES_ANSWER,
sources=(
VerifiedSourceScope("TR-KANUN-2809", "Madde 3", ("en az üç fakültenin bulunması zorunludur",)),
),
),
VerifiedQueryContract(
contract_id="showcase_course_load_relation",
question="2914 sayılı Kanundaki ek ders ücreti, 2547 sayılı Kanunun 36. maddesindeki ders yükü kuralını hangi şartlarla tamamlar?",
answer_markdown=_COURSE_LOAD_RELATION_ANSWER,
sources=(
VerifiedSourceScope(
"TR-KANUN-2914",
"Madde 11",
("2547 sayılı yükseköğretim kanununun 36 ncı maddesine göre", "haftalık ders programında yer alması", "fiilen yapılması"),
),
VerifiedSourceScope(
"TR-KANUN-2547",
"Madde 36",
("haftada asgari on saat", "haftada asgari on iki saat", "2914 sayılı kanunun 11 inci maddesinde"),
),
),
),
)
_CONTRACTS_BY_QUESTION = {
normalize_for_search(contract.question): contract
for contract in VERIFIED_QUERY_CONTRACTS
}
def render_verified_query_answer(question: str) -> dict:
contract = _CONTRACTS_BY_QUESTION.get(normalize_for_search(question or ""))
if contract is None:
return {}
failures = _validate_sources(contract)
if failures:
detail = "; ".join(failures)
return {
"contract_id": contract.contract_id,
"valid": False,
"answer": (
"UNKNOWN — doğrulanmış sorgu sözleşmesinin dayandığı kaynak kapsamı "
f"yayınlanmış MCKF paketinde doğrulanamadı. Yönetici incelemesi gerekir. ({detail})"
),
"clause_eval": _contract_clause_eval(contract, valid=False),
}
answer = contract.answer_markdown.strip()
if contract.full_article_source is not None:
source = get_article_source(
contract.full_article_source.document_id,
contract.full_article_source.article_id,
)
title = str(source.get("title", "") or "").strip()
text = str(source.get("source_text", "") or "").strip()
document_code = contract.full_article_source.document_id.rsplit("-", 1)[-1]
answer = (
f"**{document_code} sayılı Kanun {contract.full_article_source.article_id}"
f"{f' — {title}' if title else ''}**\n\n{text}"
)
source_clauses = [
{"document_id": scope.document_id, "article_id": scope.article_id}
for scope in contract.sources
]
answer += "\n\n---\n\n**Kaynaklar**\n" + format_clause_sources(
source_clauses,
question=question,
answer=answer,
)
return {
"contract_id": contract.contract_id,
"valid": True,
"answer": answer,
"clause_eval": _contract_clause_eval(contract, valid=True),
}
def _validate_sources(contract: VerifiedQueryContract) -> list[str]:
failures = []
for scope in contract.sources:
source = get_article_source(scope.document_id, scope.article_id)
source_text = str(source.get("source_text", "") or "").strip()
if not source_text:
failures.append(f"{scope.document_id}::{scope.article_id} kaynağı yok")
continue
normalized_source = normalize_for_search(source_text)
missing_terms = [
term for term in scope.evidence_terms
if normalize_for_search(term) not in normalized_source
]
if missing_terms:
failures.append(
f"{scope.document_id}::{scope.article_id} kanıtı eksik: {', '.join(missing_terms)}"
)
return failures
def _contract_clause_eval(contract: VerifiedQueryContract, valid: bool) -> dict:
document_ids = list(dict.fromkeys(scope.document_id for scope in contract.sources))
source_ids = [f"{scope.document_id}::{scope.article_id}" for scope in contract.sources]
return {
"evidence_ids": [],
"clause_ids": [],
"document_ids": document_ids if valid else [],
"source_ids": source_ids if valid else [],
"scores": [1.0 for _scope in contract.sources] if valid else [],
"score_breakdowns": [
{"verified_query_contract": contract.contract_id}
for _scope in contract.sources
] if valid else [],
}