CarFinanceAgent / chatbot /tools /amount_tool.py
emreceniklioglu
Initial commit: LangGraph multi-agent car finance chatbot
49102bb
Raw
History Blame Contribute Delete
4.43 kB
"""
tools/amount_tool.py — Finansman Tutarı Hesap ve Doğrulama
AGENTIC PATTERN: Tool Use — Deterministik İş Kuralları
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Tüm finansman kuralları (üst limitler, oranlar) burada KOD olarak
çalışır. LLM bu kuralları ne hesaplar ne de doğrular — sadece
hangi tool'u çağıracağını seçer.
Bu sayede:
- Kural hataları test edilebilir (birim test)
- Kural değişikliği için tek bir yer
- LLM halüsinasyonu → iş kararlarına etki edemez
"""
from langchain_core.tools import tool
from config import (
NEW_CAR_MAX_INVOICE,
NEW_CAR_FINANCE_RATIO,
NEW_CAR_GUARANTOR_THRESHOLD,
USED_CAR_MAX_AGE,
USED_CAR_FINANCE_RATIO,
USED_CAR_MAX_FINANCE,
)
@tool
def validate_new_car_amount(invoice_amount: float, requested_amount: float) -> dict:
"""
Yeni araç finansman tutarını iş kurallarına göre doğrular.
Kurallar:
- Fatura tutarı ≤ 7.000.000 TL
- Finansman ≤ %60 × fatura tutarı
Returns:
{"valid": bool, "max_allowed": float, "error": str | None,
"kefil_required": bool}
"""
# Kural 1: Fatura üst limiti
if invoice_amount > NEW_CAR_MAX_INVOICE:
return {
"valid": False,
"max_allowed": NEW_CAR_MAX_INVOICE,
"error": f"Proforma fatura tutarı {_fmt(NEW_CAR_MAX_INVOICE)} TL üst limitini aşıyor.",
"kefil_required": False,
}
# Kural 2: Finansman oranı
max_finance = invoice_amount * NEW_CAR_FINANCE_RATIO
if requested_amount > max_finance:
return {
"valid": False,
"max_allowed": max_finance,
"error": (
f"İstenen finansman ({_fmt(requested_amount)} TL), "
f"fatura tutarının %{int(NEW_CAR_FINANCE_RATIO*100)}'ini aşıyor. "
f"Maksimum: {_fmt(max_finance)} TL"
),
"kefil_required": invoice_amount >= NEW_CAR_GUARANTOR_THRESHOLD,
}
return {
"valid": True,
"max_allowed": max_finance,
"error": None,
"kefil_required": invoice_amount >= NEW_CAR_GUARANTOR_THRESHOLD,
}
@tool
def validate_used_car_amount(kasko_value: float, vehicle_age: int, requested_amount: float) -> dict:
"""
2. El araç finansman tutarını iş kurallarına göre doğrular.
Kurallar:
- Araç yaşı ≤ 5 yıl
- Finansman ≤ min(%40 × kasko_value, 3.000.000 TL)
Returns:
{"valid": bool, "max_allowed": float, "error": str | None}
"""
# Kural 1: Yaş kontrolü
if vehicle_age > USED_CAR_MAX_AGE:
return {
"valid": False,
"max_allowed": 0,
"error": f"Araç yaşı {vehicle_age} yıl, maksimum kabul edilen {USED_CAR_MAX_AGE} yıldır.",
}
# Kural 2: Finansman oranı (min ile sınırla)
ratio_limit = kasko_value * USED_CAR_FINANCE_RATIO
max_finance = min(ratio_limit, USED_CAR_MAX_FINANCE)
if requested_amount > max_finance:
return {
"valid": False,
"max_allowed": max_finance,
"error": (
f"İstenen finansman ({_fmt(requested_amount)} TL) limiti aşıyor. "
f"Kasko oranı limiti: {_fmt(ratio_limit)} TL, "
f"mutlak üst limit: {_fmt(USED_CAR_MAX_FINANCE)} TL."
),
}
return {"valid": True, "max_allowed": max_finance, "error": None}
@tool
def calculate_max_finance_new(invoice_amount: float) -> dict:
"""Yeni araç için alınabilecek maksimum finansmanı hesaplar."""
max_f = invoice_amount * NEW_CAR_FINANCE_RATIO
return {
"max_finance": max_f,
"ratio": NEW_CAR_FINANCE_RATIO,
"kefil_required": invoice_amount >= NEW_CAR_GUARANTOR_THRESHOLD,
}
@tool
def calculate_max_finance_used(kasko_value: float) -> dict:
"""2. El araç için alınabilecek maksimum finansmanı hesaplar."""
ratio_limit = kasko_value * USED_CAR_FINANCE_RATIO
max_f = min(ratio_limit, USED_CAR_MAX_FINANCE)
return {"max_finance": max_f, "ratio": USED_CAR_FINANCE_RATIO, "absolute_cap": USED_CAR_MAX_FINANCE}
def _fmt(amount: float) -> str:
"""Sayıyı Türkçe binlik ayırıcıyla formatlar: 3000000 → '3.000.000'"""
return f"{int(amount):,}".replace(",", ".")