fix: replace exact-phrase wrap with AND-required-terms in /search
Wrapping every multi-word phrase in exact-phrase quotes (added for the "uyuşturucu madde ticareti" false-positive problem) was too strict for independent keyword queries like "bıçak yaralaması beraat" or the AI query-optimizer's extracted keywords — those words rarely appear verbatim adjacent to each other, so exact-phrase returned 0 results. Now each word is prefixed with + instead (AND semantics: all words must appear somewhere in the decision, not necessarily adjacent). This still fixes the original "madde" noise problem while no longer breaking loose multi-keyword searches.
This commit is contained in:
+23
-12
@@ -52,10 +52,12 @@ class SearchRequest(BaseModel):
|
|||||||
exact_phrase: bool = Field(
|
exact_phrase: bool = Field(
|
||||||
default=True,
|
default=True,
|
||||||
description=(
|
description=(
|
||||||
"True ise coklu kelimeli phrase otomatik tam ifade (\"...\") aramasina cevrilir. "
|
"True ise coklu kelimeli phrase'deki her kelime otomatik olarak '+' ile zorunlu "
|
||||||
"Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri ayri ayri eslestirir "
|
"kilinir (orn. 'a b' -> '+a +b') — tum kelimeler karar icinde gecmeli ama yan yana "
|
||||||
"(orn. 'madde' gibi her kararda gecen ortak kelimeler alakasiz sonuclari one cikarir); "
|
"olmalari gerekmez. Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri gevsek "
|
||||||
"tam ifade araması bu gurultuyu onler. Kullanici zaten tirnak/AND/OR/NOT/+/- kullaniyorsa dokunulmaz."
|
"eslestirir (orn. 'madde' gibi her kararda gecen ortak kelimeler alakasiz sonuclari "
|
||||||
|
"one cikarir); bu ayar bu gurultuyu onler. Kullanici zaten tirnak/AND/OR/NOT/+/- "
|
||||||
|
"kullaniyorsa dokunulmaz."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -95,25 +97,34 @@ def _format_date(value: Optional[str], end_of_day: bool = False) -> str:
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
# --- Yardimci fonksiyon: coklu kelimeli aramalari tam ifadeye cevirme ---
|
# --- Yardimci fonksiyon: coklu kelimeli aramalari daha isabetli hale getirme ---
|
||||||
#
|
#
|
||||||
# Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri ayri ayri eslestiriyor.
|
# Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri ayri ayri (gevsek) eslestiriyor.
|
||||||
# Ornek: "uyusturucu madde ticareti" -> "madde" gibi her kararda gecen (kanun maddesi
|
# Ornek: "uyusturucu madde ticareti" -> "madde" gibi her kararda gecen (kanun maddesi
|
||||||
# anlaminda) ortak bir kelime yuzunden alakasiz sonuclar (ic icra/iflas kararlari) one
|
# anlaminda) ortak bir kelime yuzunden alakasiz sonuclar (ic icra/iflas kararlari) one
|
||||||
# cikabiliyor. Kullanici zaten ozel operator/tirnak kullanmiyorsa, coklu kelimeli
|
# cikabiliyor.
|
||||||
# aramayi otomatik tam ifadeye ("...") ceviriyoruz.
|
#
|
||||||
|
# Once tum ifadeyi tirnaklayip "tam bitisik ifade" aramasi denendi, ama bu cok kati
|
||||||
|
# cikti: "bicak yaralamasi beraat" gibi bagimsiz anahtar kelimelerden olusan (AI'nin
|
||||||
|
# uzun sorulardan cikardigi turden) aramalar, bu 3 kelime kararlarda hic yan yana/aynen
|
||||||
|
# gecmedigi icin 0 sonuc donduruyordu. Bunun yerine her kelimeyi "+" ile ayri ayri
|
||||||
|
# zorunlu kiliyoruz (AND semantigi): tum kelimeler karar icinde herhangi bir yerde
|
||||||
|
# gecmeli ama bitisik/ayni sirada olmalari gerekmiyor. Bu hem orijinal "madde" sorununu
|
||||||
|
# cozuyor (uyusturucu VE madde VE ticaret hepsi gecmeli) hem de bagimsiz anahtar kelime
|
||||||
|
# aramalarini kirmiyor.
|
||||||
_OPERATOR_PATTERN = re.compile(r'"|\bAND\b|\bOR\b|\bNOT\b|(?:^|\s)[+-]\S', re.IGNORECASE)
|
_OPERATOR_PATTERN = re.compile(r'"|\bAND\b|\bOR\b|\bNOT\b|(?:^|\s)[+-]\S', re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
def _apply_exact_phrase(phrase: str, exact_phrase: bool) -> str:
|
def _apply_required_terms(phrase: str, exact_phrase: bool) -> str:
|
||||||
stripped = phrase.strip()
|
stripped = phrase.strip()
|
||||||
if not exact_phrase or not stripped:
|
if not exact_phrase or not stripped:
|
||||||
return phrase
|
return phrase
|
||||||
if len(stripped.split()) < 2:
|
words = stripped.split()
|
||||||
|
if len(words) < 2:
|
||||||
return phrase
|
return phrase
|
||||||
if _OPERATOR_PATTERN.search(stripped):
|
if _OPERATOR_PATTERN.search(stripped):
|
||||||
return phrase
|
return phrase
|
||||||
return f'"{stripped}"'
|
return " ".join(f"+{w}" for w in words)
|
||||||
|
|
||||||
|
|
||||||
# --- Endpoint 1: Arama ---
|
# --- Endpoint 1: Arama ---
|
||||||
@@ -126,7 +137,7 @@ async def search(req: SearchRequest):
|
|||||||
"""
|
"""
|
||||||
karar_tarihi_start = _format_date(req.karar_tarihi_start)
|
karar_tarihi_start = _format_date(req.karar_tarihi_start)
|
||||||
karar_tarihi_end = _format_date(req.karar_tarihi_end, end_of_day=True)
|
karar_tarihi_end = _format_date(req.karar_tarihi_end, end_of_day=True)
|
||||||
phrase = _apply_exact_phrase(req.phrase, req.exact_phrase)
|
phrase = _apply_required_terms(req.phrase, req.exact_phrase)
|
||||||
|
|
||||||
search_data = BedestenSearchData(
|
search_data = BedestenSearchData(
|
||||||
pageSize=10,
|
pageSize=10,
|
||||||
|
|||||||
Reference in New Issue
Block a user