Skip to content

5. ChatGPT ile üç sorunun çözümü

5.1. Giriş

İşte bir ChatGPT oturumunun ilk ekran görüntüsü:

 
  • [1-3]'te, ChatGPT'te ortaya çıkan üç sorun;
  • [4]'te, ChatGPT'in URL'i;
  • [5]'te, ChatGPT'in kullanılan sürümü;

ChatGPT, OpenAI'in bir ürünüdür ve URL ile [https://chatgpt.com/]'te mevcuttur. Yukarıdaki gibi soru-cevap oturumlarınızın geçmişine erişmek için bir hesap oluşturmanız gerekir. Ayrıca, test edilen diğer tüm IA'ler gibi, ChatGPT de soru sayınızı ve indirilen dosya sayısını sınırlamaktadır. Bu sınıra ulaşıldığında oturum sona erer ve daha sonra devam etmeniz önerilir. ChatGPT tarafından uygulanan sınırlar çok hızlı bir şekilde dolmaktadır. Bu eğitimi hazırlamak için bir aylık ücretli abonelik almam gerekti.

ChatGPT'in arayüzü şu şekildedir:

 
  • [1]'te, sorulan soruya dosya eklemek için;
  • [2]'te, sorulan soru;
  • [3]'te, IA'in çalıştırılması;

5.2. Sorun 1

ChatGPT'teki soru:

  
 

ChatGPT doğru yanıt veriyor.

5.3. Sorun 2

PDF ile vergi hesaplaması. Dürüst olmak gerekirse, ilk PDF'teki hataları düzelten ve Gemini tarafından oluşturulan PDF'i kullanacağız.

 
  • [1]'te, Gemini tarafından oluşturulan PDF'i verdik;
  • [2] dosyasında, Gemini'nin üstünlüğünü kanıtladığı birim testi eklenmiştir:
test12 : (2, 2, 49500) -> (1297, 431, 324)

ChatGPT'i çalıştırıyoruz. Yanıtını oluşturması yaklaşık 3 dakika sürüyor. Gemini'nin aksine, oluşturulan komut dosyasını almak için çalışan bir bağlantı sağlıyor. Bunu PyCharm'e yüklüyoruz:

 

[chatGPT1] komut dosyası ilk denemede çalışıyor. Bu konuda tartışmaya gerek yok, bu sorunda ChatGPT, Gemini'den daha iyi performans gösterdi.

ChatGPT tarafından sağlanan [chatGPT1] komut dosyası şöyledir:

# -*- coding: utf-8 -*-
"""
Calcul de l'impôt 2019 (revenus 2018) en Python.

Hypothèses et règles (d'après le PDF fourni) :
- Tous les revenus sont portés sur le déclarant 1 (même pour un couple).
- Abattement forfaitaire de 10 % encadré par un minimum et un maximum.
- Barème progressif 2018 appliqué au quotient familial (QF).
- Plafonnement du quotient familial : avantage par demi-part enfant limité.
- Décote et réduction de 20 % pour faibles revenus, avec la règle de repêchage.
- Ordre des correctifs : plafonnement QF -> décote -> réduction 20 %.
- Arrondis : abattement (↑), décote (↑), réduction (↑), impôt final (↓).
- On renvoie l'impôt à payer (arrondi à l'euro inf.), la décote et la réduction
  (arrondies à l'euro sup.).

Les nombres “magiques” sont regroupés en constantes, et chaque étape est isolée
dans des fonctions pour la clarté.
"""

from dataclasses import dataclass
from math import ceil, floor

# ---------- Yasal sabitler ----------

# 2018 gelirleri için mesleki gider indirimi (alt sınır/üst sınır)
ABATTEMENT_TAUX = 0.10
ABATTEMENT_MIN = 437
ABATTEMENT_MAX = 12502

# 2018 tarifesi (QF)
# Her dilim (borne_sup, oran) şeklindedir. %0'lık ilk dilim 9.964 €'da sona erer.
BAREME_2018 = [
    (9964, 0.00),
    (27519, 0.14),
    (73779, 0.30),
    (156244, 0.41),
    (float("inf"), 0.45),
]

# Aile katsayısı üst sınırı
PF_QF_AVANTAGE_PAR_DEMI_PART = 1551  # 1/2 pay başına maksimum avantaj ENFANT

# İndirim (yetişkin sayısına / çift statüsüne göre eşikler)
DECOTE_SEUIL_CELIB = 1196
DECOTE_SEUIL_COUPLE = 1970

# %20 indirim: paylara göre eşikler
REDUCTION_BASE_1_PART = 18985
REDUCTION_BASE_2_PARTS = 37970
REDUCTION_PAR_DEMI_PART_SUP = 3803  # 1 veya 2 paylık temel payın üzerindeki her 1/2 pay için ek indirim


# ---------- Veri yapıları ----------

@dataclass
class ResultatImpot:
    impot: int  # ödenecek nihai vergi, bir alt euroya yuvarlanmış
    decote: int  # yukarı doğru euro'ya yuvarlanan indirim
    reduction: int  # %20 indirim, bir üst euroya yuvarlanmış


# ---------- Yardımcı işlevler ----------

def arrondi_sup(euros: float) -> int:
    """Arrondi à l'euro supérieur (ceil)."""
    return int(ceil(euros))


def arrondi_inf(euros: float) -> int:
    """Arrondi à l'euro inférieur (floor)."""
    return int(floor(euros))


# ---------- Adım 1: Vergilendirilebilir Net Gelir (RNI) ----------

def calcul_abattement(revenus_bruts: float) -> int:
    """
    Calcule l'abattement de 10 %, plafonné/planche, ARRONDI À L'EURO SUPÉRIEUR.
    """
    abattement_calcule = revenus_bruts * ABATTEMENT_TAUX
    abattement_calcule = max(ABATTEMENT_MIN, min(ABATTEMENT_MAX, abattement_calcule))
    return arrondi_sup(abattement_calcule)


def revenu_net_imposable(revenus_bruts: float) -> int:
    """RNI = revenus bruts - abattement (abattement arrondi ↑)."""
    return int(round(revenus_bruts - calcul_abattement(revenus_bruts)))


# ---------- Adım 2: Hisse Sayısı ----------

def nombre_parts(adultes: int, enfants: int) -> float:
    """
    Règles : 1 part si 1 adulte, 2 parts si 2 adultes.
    Enfants : +0,5 pour les 2 premiers, +1 par enfant à partir du 3e.
    (On ignore ici tout cas particulier type parent isolé, conformément au PDF.)
    """
    parts = 1.0 if adultes == 1 else 2.0
    if enfants <= 0:
        return parts
    if enfants == 1:
        return parts + 0.5
     # çocuk sayısı >= 2
    parts += 1.0  # +0,5 İlk ikisi için +0,5
    if enfants > 2:
        parts += (enfants - 2) * 1.0  # 3. çocuktan itibaren her çocuk için +1
    return parts


def demi_parts_enfants(enfants: int) -> int:
    """Nombre de DEMI-parts dû aux enfants (utile pour le plafonnement QF)."""
    if enfants <= 0:
        return 0
    if enfants == 1:
        return 1  # 0,5 pay
     # İlk iki çocuk = 2 * yarım pay, ardından 3. çocuktan itibaren her çocuk için +2 yarım pay
    return 2 + (enfants - 2) * 2


# ---------- Adım 3: QF aracılığıyla brüt vergi hesaplanması ----------

def impot_brut_par_parts(qf: float) -> float:
    """Impôt par part via barème progressif 2018 (sans arrondi)."""
    imp = 0.0
    previous = 0.0
    for borne_sup, taux in BAREME_2018:
        montant_tranche = max(0.0, min(qf, borne_sup) - previous)
        imp += montant_tranche * taux
        if qf <= borne_sup:
            break
        previous = borne_sup
    return imp


def impot_brut_total(rni: float, parts: float) -> float:
    """Impôt brut total = impôt par part * nombre de parts (sans arrondi)."""
    if parts <= 0:
        return 0.0
    qf = rni / parts
    return impot_brut_par_parts(qf) * parts


# ---------- Adım 4.1: Aile katsayısı üst sınırı ----------

def apply_plafonnement_qf(impot_avec_enfants: float, rni: float, adultes: int, enfants: int) -> float:
    """
    Calcule l'impôt après plafonnement QF si l'avantage des enfants dépasse le plafond.
    - Impôt A : avec parts incluant enfants
    - Impôt B : avec seulement parts des adultes (1 ou 2)
    - Avantage réel = B - A
    - Avantage maximal = 1551 € par 1/2 part ENFANT
    Si avantage réel > avantage max, impôt = B - avantage max, sinon impôt = A.
    """
    parts_adultes = 1.0 if adultes == 1 else 2.0
    imp_b = impot_brut_total(rni, parts_adultes)
    imp_a = impot_avec_enfants
    avantage_reel = max(0.0, imp_b - imp_a)
    avantage_max = PF_QF_AVANTAGE_PAR_DEMI_PART * demi_parts_enfants(enfants)
    if avantage_reel > avantage_max:
        return imp_b - avantage_max
    return imp_a


# ---------- Adım 4.2: İndirim ve %20 Azaltma ----------

def seuil_decote(adultes: int) -> int:
    return DECOTE_SEUIL_COUPLE if adultes >= 2 else DECOTE_SEUIL_CELIB


def seuil_reduction_20(rni: int, adultes: int, parts: float) -> int:
    """
    Seuil d'éligibilité à la réduction de 20 % :
    - Base : 18 985 € pour 1 part, 37 970 € pour 2 parts
    - + 3 803 € par 1/2 part supplémentaire au-delà de la base correspondante.
    """
    base = REDUCTION_BASE_2_PARTS if adultes >= 2 else REDUCTION_BASE_1_PART
    base_parts = 2.0 if adultes >= 2 else 1.0
    demi_sup = max(0, int(round((parts - base_parts) * 2)))
    return base + demi_sup * REDUCTION_PAR_DEMI_PART_SUP


def calc_decote_reduction(impot_apres_plaf: float, rni: int, adultes: int, parts: float):
    """
    Calcule (decote_arrondie, reduction_arrondie, impot_apres_correctifs).
    Règle d'interaction : la décote peut s'appliquer via repêchage si, après
    application THÉORIQUE de la réduction de 20 %, l'impôt passerait sous le seuil.
    Ordre : décote -> réduction.
    """
    imp = max(0.0, impot_apres_plaf)
    decote = 0
    reduction = 0

     # RNI'e dayalı %20 indirim uygunluğu
    seuil_red = seuil_reduction_20(rni, adultes, parts)
    eligible_reduction = rni < seuil_red  # PDF'te "eşik değerin altında"

     # İndirim uygunluğu: eşiğin doğrudan altında olması veya indirim uygulandığında eşiğin altına düşecekse yeniden değerlendirme
    s_dec = seuil_decote(adultes)
    direct_decote = imp <= s_dec
    repechage = False
    if not direct_decote and eligible_reduction:
        imp_theorique_apres_red = imp * 0.80  # teorik indirim %20
        if imp_theorique_apres_red <= s_dec:
            repechage = True

    elig_decote = (direct_decote or repechage) and (imp > 0)

     # Önce indirimi uygula (uygunsa)
    if elig_decote:
        montant_decote = s_dec - (imp * 0.75)
        decote_calc = max(0, arrondi_sup(montant_decote))
         # İndirim, kalan vergi tutarını aşamaz: sınırlandırılır
        decote = min(decote_calc, arrondi_sup(imp))
        imp = max(0.0, imp - decote)

     # Ardından, uygunsa indirimi uygulayın
    if eligible_reduction and imp > 0:
        montant_reduction = imp * 0.20
        reduction = max(0, arrondi_sup(montant_reduction))
        imp = max(0.0, imp - reduction)

    return decote, reduction, imp


# ---------- API ana işlem ----------

def calcule_impot(adultes: int, enfants: int, revenus_bruts: float) -> ResultatImpot:
    """
    Calcule l'impôt 2019 (revenus 2018) pour un foyer.
    Retourne ResultatImpot(impot, decote, reduction).
    """
     # 1) RNI
    rni = revenu_net_imposable(revenus_bruts)

     # 2) Paylar
    parts = nombre_parts(adultes, enfants)

     # 3) Vergi tablosuna göre brüt vergi (tüm paylar dahil)
    imp_brut_A = impot_brut_total(rni, parts)

     # 4.1) Aile katsayısı üst sınırı
    imp_apres_plaf = apply_plafonnement_qf(imp_brut_A, rni, adultes, enfants)

     # 4.2) İndirim ve ardından %20 azaltma (telafi dahil)
    decote, reduction, imp_corrige = calc_decote_reduction(imp_apres_plaf, rni, adultes, parts)

     # 5) Verginin nihai yuvarlama (↓) ve 0'a sınırlama
    imp_final = max(0, arrondi_inf(imp_corrige))

    return ResultatImpot(impot=imp_final, decote=decote, reduction=reduction)


# ---------- Küçük test programı ----------

def _nearly_equal(a: int, b: int, tol: int = 1) -> bool:
    return abs(a - b) <= tol


def tests_unitaires():
    """
    Renvoie une liste de tuples (inputs, attendu, obtenu, ok) pour chaque test.
    Tolérance : ±1 € sur chaque valeur (impôt, décote, réduction).
    """
    cas = [
         # (yetişkinler, çocuklar, gelirler) -> (vergi, indirim, iskonto)
        ((2, 2, 55555), (2815, 0, 0)),
        ((2, 2, 50000), (1385, 384, 346)),
        ((2, 3, 50000), (0, 720, 0)),
        ((1, 2, 100000), (19884, 0, 0)),
        ((1, 3, 100000), (16782, 0, 0)),
        ((2, 3, 100000), (9200, 0, 0)),
        ((2, 5, 100000), (4230, 0, 0)),
        ((1, 0, 100000), (22986, 0, 0)),
        ((2, 2, 30000), (0, 0, 0)),
        ((1, 0, 200000), (64211, 0, 0)),
        ((2, 3, 200000), (42843, 0, 0)),
        ((2, 2, 49500), (1297, 431, 324)),
    ]

    resultats = []
    for (adultes, enfants, revenus), attendu in cas:
        res = calcule_impot(adultes, enfants, revenus)
        obtenu = (res.impot, res.decote, res.reduction)
        ok = _nearly_equal(obtenu[0], attendu[0]) and _nearly_equal(obtenu[1], attendu[1]) and _nearly_equal(obtenu[2],
                                                                                                             attendu[2])
        resultats.append(((adultes, enfants, revenus), attendu, obtenu, ok))
    return resultats


if __name__ == "__main__":
    for inputs, attendu, obtenu, ok in tests_unitaires():
        print(f"{inputs} -> attendu={attendu}, obtenu={obtenu} : {'OK' if ok else 'ECHEC'}")

5.4. 3. Sorun

Şimdi ChatGPT'ten internet üzerinden vergi hesaplama kurallarını aramasını istiyoruz:

 

Bu sefer, uyulması gereken hesaplama kurallarını içeren PDF dosyası sağlanmamaktadır. Yalnızca metin dosyasında talimatlarımız verilmektedir. Hatırlatmak isteriz ki, bu metin dosyası artık 12 birim testi içermektedir; çünkü başlangıçtaki 11 teste, Gemini'nin benim ilk PDF dosyamın hatalı olduğunu kanıtlamak için kullandığı testi de ekledik.

ChatGPT, 8 dakika içinde yanıt verdi ve oluşturulan komut dosyasını indirmek için bir bağlantı sağladı. PyCharm’e yüklendikten sonra, bu komut dosyası 12 testi de geçti. Dolayısıyla, sorulan iki soruya ChatGPT ilk denemede doğru yanıt verdi ve böylece Gemini’yi geride bıraktı.

ChatGPT, yanıtında kaynaklarını belirtir:

 

Söylenecek bir şey yok, harika bir iş çıkarmış.

Şimdi, Gemini’ye yaptığımız gibi, öğrenciler için bir PDF oluşturmasını isteyebiliriz.

 

ChatGPT yanıtı, birkaç kez gidip gelmenin ardından elde edildi; çünkü oluşturulan PDF, karakterleri kareyle değiştiren bir yazı tipi kullanıyordu. Ancak sonunda PDF'i oluşturdu. Bunu paylaşıyorum çünkü Gemini'nin PDF'inden farklı kurallar veriyor ve ben de hangisinin doğru olduğunu merak ettim. Bunu araştıracağız.

 
 
 

Gemini'nin PDF modeliyle arasındaki fark, indirim hesaplamasında yatmaktadır. İki IA modeli aynı yaklaşımı benimsememektedir. Gemini şöyle yazmıştı:

 
 
 

İki IA kodu da birbirinden farklı yaklaşımlar sergiliyor. Hangisi doğru?

5.5. 4. Problem

ChatGPT'ten, vergi hesaplamasını yapmak için PDF'i temel almasını isteyeceğiz:

Önceki seferlerde olduğu gibi, ilk denemede çalışan bir Python betiği oluşturuyor. Talimatlara ek bir test eklemiştik:

test13 : (1, 0, 18535) -> (359, 491, 90)

13 testin tümü başarıyla geçildi.

5.6. Gemini’ye geri dönüş

Şimdi Gemini'ye geri dönüyoruz ve ona ChatGPT'ten PDF'i sunacağız. Bu PDF'te uygulanan kurallar, Gemini'deki PDF'te uygulanan kurallardan farklı olduğu için, ne olacağını merak edebiliriz:

 

Gemini ilk olarak testleri geçemeyen bir Python betiği oluşturdu. Ona günlükler gösterildi:

Soru 2

 

Soru 3

Hala hatalar var. Devam ediyoruz.

 

Soru 4

Yürütme sırasında hâlâ hatalar var:

 

Bu sefer doğru.

Yine de, hesaplama kuralları oldukça farklı olan PDF ve IA'in her ikisinin de doğru sonuçlar vermesi merak uyandırıcı.

Gemini’ye şu soruyu soruyoruz:

 

Sorunun tam metni şöyledir:

Après tout ce qu'on a fait, compare les deux approches, la tienne et celle de ChatGPT dans les pDF que je te joins [.. selon Gemini] pour toi, [.. selon ChatGPT] pour ChatGPT. Dis-moi laquelle on doit préférer vu que sur les 13 tests générés tu les réussis tous avec l'un ou avec l'autre PDF.

Gemini’nin cevabı kesin:

 
 
 
 
 
 

5.7. ChatGPT ne düşünüyor?

ChatGPT’e de Gemini’ye sorulan aynı soru soruluyor.

 

ChatGPT’in cevabı şöyledir:

 
 

Bunun üzerine, ChatGPT, iki yöntemi karşılaştırmak için bir birim testi öneriyor. Şunu kopyalıyoruz:

  • Gemini tarafından, PDF'i kaynak alarak oluşturulan [gemini3] betiği; [Le problème selon Gemini], [gemini4] betiğinde kopyalanır;
  • ChatGPT komut dosyası, PDF ve [Le problème selon ChatGPT] komut dosyalarını kaynak alarak oluşturulan [chatGPT3] komut dosyası, [chatGPT4] komut dosyasına kopyalanır;

Ayrıca, her bir [gemini4, chatGPT4] komut dosyasına, iki IA komut dosyası arasında ayrım yapmak için ChatGPT tarafından önerilen birim testi eklenir.

[gemini4] komutunun çalıştırılması sonucunda aşağıdaki sonuçlar elde edilir:


C:\Data\st-2025\dev\python\code\python-flask-2025-cours\.venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm 2025.2.1.1/plugins/python-ce/helpers/pycharm/_jb_unittest_runner.py" --path "C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\gemini\gemini4.py" 
Testing started at 17:45 ...
Launching unittests with arguments python -m unittest C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\gemini\gemini4.py in C:\Data\st-2025\dev\python\code\python-flask-2025-cours

SubTest failure: Traceback (most recent call last):
  File "C:\Program Files\Python313\Lib\unittest\case.py", line 58, in testPartExecutor
    yield
  File "C:\Program Files\Python313\Lib\unittest\case.py", line 556, in subTest
    yield
  File "C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\gemini\gemini4.py", line 234, in test_cas_verifies_simulateur_officiel
    self.assertAlmostEqual(calcul_impot, attendu_impot, delta=1, msg="Échec sur le montant de l'impôt")
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 2669 != 2270 within 1 delta (399 difference) : Échec sur le montant de l'impôt




Ran 1 test in 0.010s

FAILED (failures=1)

One or more subtests failed
Failed subtests list: [Test 'test12' avec entrée (2, 0, 43333)]

Process finished with exit code 1

Dolayısıyla Gemini, ChatGPT tarafından eklenen testte başarısız oluyor.

[chatGPT4] komutunun çalıştırılması şu sonuçları verir:


C:\Data\st-2025\dev\python\code\python-flask-2025-cours\.venv\Scripts\python.exe "C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\chatGPT\chatGPT4.py" 
Test (2, 2, 55555) -> obtenu (impôt=2814, décote=0, réduction=0) | attendu (2815, 0, 0) | OK
Test (2, 2, 50000) -> obtenu (impôt=1384, décote=384, réduction=347) | attendu (1385, 384, 346) | OK
Test (2, 3, 50000) -> obtenu (impôt=0, décote=721, réduction=0) | attendu (0, 720, 0) | OK
Test (1, 2, 100000) -> obtenu (impôt=19884, décote=0, réduction=0) | attendu (19884, 0, 0) | OK
Test (1, 3, 100000) -> obtenu (impôt=16782, décote=0, réduction=0) | attendu (16782, 0, 0) | OK
Test (2, 3, 100000) -> obtenu (impôt=9200, décote=0, réduction=0) | attendu (9200, 0, 0) | OK
Test (2, 5, 100000) -> obtenu (impôt=4230, décote=0, réduction=0) | attendu (4230, 0, 0) | OK
Test (1, 0, 100000) -> obtenu (impôt=22986, décote=0, réduction=0) | attendu (22986, 0, 0) | OK
Test (2, 2, 30000) -> obtenu (impôt=0, décote=0, réduction=0) | attendu (0, 0, 0) | OK
Test (1, 0, 200000) -> obtenu (impôt=64210, décote=0, réduction=0) | attendu (64211, 0, 0) | OK
Test (2, 3, 200000) -> obtenu (impôt=42842, décote=0, réduction=0) | attendu (42843, 0, 0) | OK
Test (2, 2, 49500) -> obtenu (impôt=1296, décote=431, réduction=325) | attendu (1297, 431, 324) | OK
Test (1, 0, 18535) -> obtenu (impôt=359, décote=491, réduction=90) | attendu (359, 491, 90) | OK
Test (2, 0, 43333) -> obtenu (impôt=2268, décote=0, réduction=401) | attendu (2270, 0, 400) | ECHEC
 Détails tolérance ±1€ : impôt ok? False, décote ok? True, réduction ok? True

Résultat global : AU MOINS UN TEST ÉCHOUE ❌

Process finished with exit code 0

ChatGPT de eklenen testte başarısız oluyor, ancak bunun nedeni Gemini ile aynı değil. ChatGPT doğru sonuçları buldu, ancak belirlenen 1 euro yerine 2 euro farkla.

Dolayısıyla bundan sonra, ChatGPT tarafından üretilen PDF'i, sonraki IA'lerle birlikte kullanacağız. Talimatlarımda önerilen birim testlerinin eksikliği nedeniyle, iki IA'in de ilk testleri başarıyla geçtiğini belirtmek gerekir. Bu nedenle, bu özel örnekte, vergi hesaplamasının sınır durumları için birim testleri eklemenin önemi ortaya çıkmaktadır. Bu testleri kendi başımıza hayal etmek oldukça zor olduğundan, IA'lerden bunları kendileri eklemelerini isteyeceğiz.

5.8. IA tarafından oluşturulan birim testleri ile 3. problem

Gemini ve ChatGPT ile elde edilen sonuçlar şüphe uyandırıyor. IA, akla gelebilecek tüm testleri geçerli kılan genel bir çözüm mü buldu, yoksa sadece zorunlu testleri geçerli kılan bir çözüm mü buldu? PDF'i içermeyen bir çözüme geri döneceğiz; böylece IA'leri, ihtiyaç duydukları bilgileri internetten aramaya zorlayacağız. Talimatlarımızı şu şekilde değiştiriyoruz:

 

[instructionsSansPDF4.txt] metin dosyası zaten 14 zorunlu test içeriyor. Bu testlere şu talimatları ekliyoruz:


7 - tu ajouteras autant de tests unitaires que nécessaires pour vérifier les cas limites du calcul de l'impôt.

Pour le code tu complèteras le script suivant auquel tu auras rajouté tes propres tests.

# =========================
# Birim testleri (±1 € tolerans)
# =========================

TESTS = [
     # (yetişkinler, çocuklar, gelirler) -> (vergi, indirim, muafiyet)
    ((2, 2, 55555), (2815, 0, 0)),
    ((2, 2, 50000), (1385, 384, 346)),
    ((2, 3, 50000), (0, 720, 0)),
    ((1, 2, 100000), (19884, 0, 0)),
    ((1, 3, 100000), (16782, 0, 0)),
    ((2, 3, 100000), (9200, 0, 0)),
    ((2, 5, 100000), (4230, 0, 0)),
    ((1, 0, 100000), (22986, 0, 0)),
    ((2, 2, 30000), (0, 0, 0)),
    ((1, 0, 200000), (64211, 0, 0)),
    ((2, 3, 200000), (42843, 0, 0)),
    ((2, 2, 49500), (1297, 431, 324)),
    ((1, 0, 18535), (359, 491, 90)),
    ((2, 0, 43333), (2270, 0, 400)),
]


def _ok(a, b, tol=1):
    return abs(a - b) <= tol


def run_tests(verbose: bool = True) -> bool:
    all_ok = True
    for (params, expected) in TESTS:
        a, e, r = params
        exp_impot, exp_decote, exp_reduc = expected
        res = calcul_impot_2019(a, e, r)
        ok_impot = _ok(res.impot, exp_impot)
        ok_decote = _ok(res.decote, exp_decote)
        ok_reduc = _ok(res.reduction, exp_reduc)
        test_ok = ok_impot and ok_decote and ok_reduc
        if verbose:
            print(
                f"Test {params} -> obtenu (impôt={res.impot}, décote={res.decote}, réduction={res.reduction}) | attendu {expected} | {'OK' if test_ok else 'ECHEC'}")
            if not test_ok:
                print(
                    f" Détails tolérance ±1€ : impôt ok? {ok_impot}, décote ok? {ok_decote}, réduction ok? {ok_reduc}")
        all_ok &= test_ok
    if verbose:
        print("\nRésultat global :", "TOUS LES TESTS PASSENT ✅" if all_ok else "AU MOINS UN TEST ÉCHOUE ❌")
    return all_ok


if __name__ == "__main__":
    run_tests()
  • 11-24. satırlar, zorunlu 14 test;
  • 5-55. satırlar: Bu kod, ChatGPT tarafından oluşturulan komut dosyasından alınmıştır. Oluşturulan iki komut dosyası arasındaki karşılaştırmaları kolaylaştırmak için Gemini'ye bu kodu kullanmasını zorunlu kılacağız.

ChatGPT ile başlayalım:

 

İlk yanıtı yanlış. Yürütme günlüklerini göstererek bunu ona bildiriyorum:

İkinci cevabı doğru. ChatGPT, zorunlu 14 teste aşağıdaki 11 testi daha ekledi:

# Ek sınır durumları (kademelerin sınırları/yuvarlama)
TESTS += [
     # %10 indirim: alt ve üst sınır
    ((1, 0, 3000), (0, 0, 0)),  # %10 = 300 < alt sınır 437 => RNI düşük -> vergi sıfır
    ((1, 0, 200000), (64211, 0, 0)),  # İndirim üst sınırı ilk testlerde zaten dikkate alınmıştır

     # İndirim: eşiklerin hemen altında / üstünde
    ((1, 0, 25000), None),  # tanı
    ((2, 0, 35000), None),  # tanı

     # %20 indirim: tam hak vs. sınırlandırma
    ((1, 0, 17000), None),  # tanı
    ((2, 0, 34000), None),  # tanı
    ((1, 0, 20000), None),  # tanı
    ((2, 0, 40000), None),  # tanı

     # Pay Değişikliği (QF üst sınırı)
    ((2, 1, 80000), None),
    ((2, 2, 80000), None),
    ((2, 3, 80000), None),
]

Artık 25 birim testi var. 11 yeni testi DGIP'in resmi simülatörüyle manuel olarak kontrol ettim ve her şey yolunda.

Şimdi Gemini’ye geçiyoruz. Bu çok daha karmaşık olacak. Uzun bir hata ayıklama sürecinin ardından, ChatGPT’in 25 testini geçen bir komut dosyası oluşturmayı başaracak.

 

Aşağıda hata ayıklama listesi yer almaktadır:

 

Garip bir şekilde, geçmişte Gemini tüm testleri geçen kod üretmiş olmasına rağmen, zorunlu 14 testin bile çoğu başarısız oldu.

Gemini’nin aşağıdaki yanıtı hâlâ doğru değil:

 

Aşağıdaki yanıt da doğru değil:

 

Aşağıdaki yanıt da değil. Bu yüzden taktiğimi değiştiriyorum. ChatGPT'in geçtiği 25 testi geçmesini istiyorum ve ChatGPT'in günlüklerini de ekliyorum:

 

Gemini başarısız oldu. ChatGPT’in testlerini eklemiş. Ona bu testlerin çalıştırma günlüklerini ekliyorum:

 

Hala çalışmıyor:

 

Hâlâ çalışmıyor:

 

Hala yok:

 

Hâlâ yok ama daha iyi:

 

Gemini yeni hatalar yapıyor:

 

Yine iyileşiyor:

 

Bu sefer doğru:

Tartışmasız olarak, talimat dosyasında belirtilen kısıtlamalarla 2019 yılı vergi hesaplamasına ilişkin bu somut örnekte, ChatGPT, Gemini'den daha isabetli sonuçlar verdi. Ancak bu sadece bir örnektir.

Daha da ileri gidebiliriz. Gemini’den, 25 testi başarıyla geçmek için kullandığı hesaplama kurallarına göre bir PDF dosyası yeniden oluşturmasını isteyebiliriz. İndirim ve %20’lik azaltma hesaplamalarıyla ilgili ilk mantığını değiştirip değiştirmediğini görmek istiyoruz:

Bu sefer Gemini, MarkDown adlı bir dosya oluşturdu; ben de bunu daha sonra PDF ve [Le problème selon Gemini version 2] olarak dönüştürdüm. Ve Gemini, mantığını gerçekten de değiştirmiş:

 
 

Görüldüğü üzere, artık özel iskonto hesaplaması ya da yeniden değerlendirme kuralı yok. Gemini artık ChatGPT'in mantığını benimsemiştir.