| from __future__ import annotations |
|
|
| import re |
| from dataclasses import dataclass |
|
|
| from utils import normalize_for_search
|
|
|
|
|
| class ConversationIntent:
|
| EMPTY = "empty"
|
| GREETING = "greeting"
|
| HELP = "help"
|
| THANKS = "thanks"
|
| OUT_OF_SCOPE = "out_of_scope"
|
| LEGAL_QUERY = "legal_query"
|
|
|
|
|
| GREETING_ANSWER = (
|
| "Merhaba. Ben MitrAnlil Yükseköğretim Mevzuatı AI Asistanıyım. "
|
| "2547, 2914 ve 2809 sayılı kanunlara dayalı olarak kaynak gösterimli cevaplar üretirim. "
|
| "YÖK, üniversiteler, akademik personel, öğrenciler, teşkilat, ödenekler, görevler, yetkiler ve ilgili hükümler hakkında soru sorabilirsiniz."
|
| )
|
|
|
| HELP_ANSWER = (
|
| "Ben yükseköğretim mevzuatı için geliştirilmiş kaynak gösterimli bir mevzuat asistanıyım. "
|
| "Sorunuzu kanundaki madde, alt hüküm ve kanıt parçalarıyla eşleştirerek cevaplamaya çalışırım. "
|
| "Örneğin dekanın görevleri, YÖK'ün oluşumu, ek ders ücreti, üniversite ödeneği, teşkilat yapısı veya kurumların kuruluşu hakkında soru sorabilirsiniz."
|
| )
|
|
|
| THANKS_ANSWER = "Rica ederim. Yükseköğretim mevzuatı ile ilgili başka bir soru sorabilirsiniz."
|
|
|
| OUT_OF_SCOPE_ANSWER = (
|
| "Bu pilot yükseköğretim mevzuatı kapsamında kaynak gösterimli cevap üretmek üzere tasarlanmıştır. "
|
| "YÖK, üniversiteler, akademik personel, öğrenciler, diplomalar, teşkilat, ödenekler, görevler ve yetkiler gibi konularda soru sorabilirsiniz."
|
| )
|
|
|
|
|
| @dataclass(frozen=True)
|
| class ConversationIntentResult:
|
| intent: str
|
| answer: str = ""
|
|
|
|
|
| LEGAL_CUE_TERMS = { |
| "egitim", "uzaktan egitim", "yonetmelik", "yonerge", "tez", "savunma", |
| "tez savunmasi", "basvuru", "devam", "akademik takvim", |
| "2547", "2914", "2809", "kanun", "madde", "yok", "yök", "yuksekogretim", "yükseköğretim",
|
| "universite", "üniversite", "rektor", "rektör", "dekan", "senato", "fakulte", "fakülte",
|
| "enstitu", "enstitü", "yuksekokul", "yüksekokul", "meslek", "onlisans", "önlisans",
|
| "on lisans", "ön lisans", "lisans", "diploma", "ogrenci", "öğrenci", "ogretim", "öğretim",
|
| "profesor", "profesör", "docent", "doçent", "arastirma", "araştırma", "gorev", "görev",
|
| "yetki", "sorumluluk", "atan", "atama", "kurul", "kurulus", "kuruluş", "disiplin",
|
| "harc", "harç", "katki", "katkı", "ucret", "ücret", "denklik", "azami", "sure", "süre",
|
| "ek ders", "ödenek", "odenek", "derece", "kademe", "teşkilat", "teskilat", |
| "faaliyete", "ek gösterge", "ek gosterge", "makam tazminatı", "makam tazminati", |
| "maaş", "maas", "aylık", "aylik", "mali hak", "özlük hakkı", "ozluk hakki", |
| "tazminat", "ödeme", "odeme", "gösterge", "gosterge", "sosyal hak", |
| } |
|
|
| OUT_OF_SCOPE_CUE_TERMS = {
|
| "hava", "yemek", "tarif", "siir", "şiir", "hikaye", "futbol", "borsa", "kripto",
|
| "film", "muzik", "müzik", "resim", "kod yaz", "mail yaz", "cevir", "çevir",
|
| }
|
|
|
|
|
| def detect_conversation_intent(message: str) -> ConversationIntentResult:
|
| raw = (message or "").strip()
|
| normalized = normalize_for_search(raw)
|
| compact = normalized.replace(" ", "")
|
|
|
| if not normalized:
|
| return ConversationIntentResult(ConversationIntent.EMPTY, "Lütfen yükseköğretim mevzuatı ile ilgili bir soru yazın.")
|
|
|
| if _is_greeting(normalized, compact):
|
| return ConversationIntentResult(ConversationIntent.GREETING, GREETING_ANSWER)
|
|
|
| if _is_thanks(normalized):
|
| return ConversationIntentResult(ConversationIntent.THANKS, THANKS_ANSWER)
|
|
|
| if _is_help_request(normalized):
|
| return ConversationIntentResult(ConversationIntent.HELP, HELP_ANSWER)
|
|
|
| if _has_legal_cue(normalized):
|
| return ConversationIntentResult(ConversationIntent.LEGAL_QUERY, "")
|
|
|
| if _has_out_of_scope_cue(normalized):
|
| return ConversationIntentResult(ConversationIntent.OUT_OF_SCOPE, OUT_OF_SCOPE_ANSWER)
|
|
|
|
|
|
|
|
|
| if any(term in normalized for term in ("nedir", "nasil", "nasıl", "kim", "hangi", "ne zaman", "kac", "kaç", "gerekir", "olur")):
|
| return ConversationIntentResult(ConversationIntent.LEGAL_QUERY, "")
|
|
|
| return ConversationIntentResult(ConversationIntent.OUT_OF_SCOPE, OUT_OF_SCOPE_ANSWER)
|
|
|
|
|
| def _is_greeting(normalized: str, compact: str) -> bool:
|
| greetings = {
|
| "merhaba", "selam", "selamlar", "gunaydin", "günaydın", "iyi gunler", "iyi günler",
|
| "iyi aksamlar", "iyi akşamlar", "iyi geceler", "kolay gelsin", "mrb", "slm",
|
| }
|
| if normalized in greetings or compact in {g.replace(" ", "") for g in greetings}:
|
| return True
|
| if len(normalized.split()) <= 3 and any(g in normalized for g in greetings):
|
| return True
|
| return False
|
|
|
|
|
| def _is_thanks(normalized: str) -> bool:
|
| return len(normalized.split()) <= 6 and any(term in normalized for term in ("tesekkur", "teşekkür", "sag ol", "sağ ol", "eyvallah", "tşk"))
|
|
|
|
|
| def _is_help_request(normalized: str) -> bool: |
| phrases = ( |
| "ne yapabilirsin", "neler yapabilirsin", "nasil calisiyorsun", "nasıl çalışıyorsun", |
| "bu sistem nedir", "hangi sorular", "ne sorabilirim", |
| ) |
| if any(phrase in normalized for phrase in phrases): |
| return True |
| |
| |
| return bool(re.search(r"(?<![a-z0-9])yardim(?![a-z0-9])", normalized)) |
|
|
|
|
| def _has_legal_cue(normalized: str) -> bool:
|
| return any(term in normalized for term in LEGAL_CUE_TERMS)
|
|
|
|
|
| def _has_out_of_scope_cue(normalized: str) -> bool:
|
| return any(term in normalized for term in OUT_OF_SCOPE_CUE_TERMS)
|
|
|