Öğrenecekleriniz Bölümünün Detaylı Açıklaması

Gönderdiğiniz belgedeki "Öğrenecekleriniz" (What you will learn) paragrafı, modern bir yapay zeka geliştiricisinin bilmesi gereken en kritik konuları içeriyor. Bu bölümde yer alan her bir maddeyi, büyük dil modellerinin (LLM) çalışma mantığından başlayarak yazılım projelerine nasıl entegre edileceğine kadar adım adım ve detaylıca inceleyelim.


1. Temel LLM Mekanizmaları: Tokenization ve Context Window

Büyük dil modellerinin arkasındaki temel matematiksel ve sistemsel sınırları anlamak, hem bütçenizi korumak hem de uygulamanızın doğru çalışmasını sağlamak için şarttır.

Tokenization (Tokenlaştırma) Nedir?

Modeller bizim gibi kelimeleri doğrudan okuyamazlar. Metinleri token adı verilen daha küçük parçalara (bazen bir kelime, bazen birkaç harf) bölerler. Her tokene sayısal bir kimlik (ID) verilir.

Context Window (Bağlam Penceresi) Nedir?

Bir yapay zeka modelinin tek bir seferde hafızasında tutabileceği, okuyabileceği ve cevap üretebileceği toplam token sınırıdır. Bu sınır aşıldığında model konuşmanın başını unutmaya başlar.

🛠️ Uygulama: Python ile Token Sayımı

OpenAI'ın tiktoken kütüphanesini kullanarak bir metnin kaç token tuttuğunu bilgisayarımızda şu şekilde hesaplayabiliriz:

import tiktoken

 

# GPT-4 modelleri için kullanılan tokenizer'ı yüklüyoruz

enc = tiktoken.encoding_for_model("gpt-4")

 

metin = "Prompt mühendisliği öğrenmek harika!"

token_listesi = enc.encode(metin)

 

print(metin)

print(f"Token ID'leri: {token_listesi}")

print(f"Toplam Token Sayısı: {len(token_listesi)}")


2. Gelişmiş Prompt Mühendisliği Pattern'leri (Kalıpları)

Yapay zekadan her zaman en iyi sonucu almak için ona sadece "bunu yap" demek yetmez. Belirli düşünme kalıpları vermemiz gerekir.

Persona Pattern (Kişilik Kalıbı)

Yapay zekaya belirli bir meslek veya uzmanlık rolü vermektir. Model, o rolün bilgi birikimine ve konuşma tarzına bürünür.

Chain of Thought (Düşünce Zinciri - CoT)

Yapay zekaya karmaşık bir soruyu çözmeden önce "adım adım düşünmesini" söylemektir. Bu, modelin mantık hataları yapmasını engeller.

Self-Critique (Öz-Eleştiri / Kendi Kendini Düzeltme)

Modelin ürettiği ilk çıktıyı yine modele inceleterek hatalarını bulmasını ve daha iyi bir ikinci taslak yazmasını sağlama yöntemidir.

🛠️ Uygulama: Self-Critique Pipeline (Kod Örneği)

Bir metni önce yazdırıp, sonra yapay zekaya kendi yazdığı metni eleştirterek düzelttirelim:

from litellm import completion

 

# 1. Adım: İlk Taslağı Oluşturma

prompt1 = "Yapay zekanın geleceği hakkında kısa bir paragraf yaz."

yanit1 = completion(model="openai/gpt-4o", messages=[{"role": "user", "content": prompt1}])

ilk_taslak = yanit1.choices[0].message.content

print(f"--- İLK TASLAK ---\n{ilk_taslak}\n")

 

# 2. Adım: Kendi Kendini Eleştirme ve Düzenleme (Self-Critique)

prompt2 = f"Aşağıdaki metni oku. Akıcılık ve teknik doğruluk açısından eleştir ve daha profesyonel bir sürümünü yaz.\nMetin: {ilk_taslak}"

yanit2 = completion(model="openai/gpt-4o", messages=[{"role": "user", "content": prompt2}])

son_hali = yanit2.choices[0].message.content

print(f"--- ELEŞTİRİLMİŞ SON HALİ ---\n{son_hali}")


3. Makine Tarafından Okunabilir Güvenilir Çıktılar (JSON Formatı)

Yapay zekayı bir web sitesine veya otomasyon sistemine bağladığınızda, size şiirsel cümleler kurması işe yaramaz. Yazılım kodlarının anlayabileceği temiz veri formatlarına (özellikle JSON) ihtiyaç duyarsınız.

🛠️ Uygulama: response_format ile JSON Garanti Altına Alma

OpenAI ve LiteLLM kütüphanelerinde response_format parametresini kullanarak modelin kesinlikle geçerli bir JSON objesi döndürmesini sağlayabiliriz:

import json

from litellm import completion

 

kullanici_yorumu = "Ürün çok hızlı geldi ama kutusu yırtıktı, kırılmadığı için şanslıyım."

 

sistem_promptu = """

Kullanıcı yorumunu analiz et ve sonucu şu JSON formatında döndür:

{

  "durum": "olumlu" veya "olumsuz" veya "notr",

  "kargo_hizi": 1 ile 5 arasinda puan

}

Kesinlikle JSON dışında hiçbir açıklama metni yazma.

"""

 

response = completion(

    model="openai/gpt-4o",

    response_format={"type": "json_object"}, # JSON modunu aktif ediyoruz

    messages=[

        {"role": "system", "content": sistem_promptu},

        {"role": "user", "content": kullanici_yorumu}

    ]

)

 

cikti = response.choices[0].message.content

# Çıktıyı python sözlüğüne dönüştürüp güvenle kullanabiliriz

veri = json.loads(cikti)

print(veri)

print(f"Kargo Hızı Puanı: {veri['kargo_hizi']}")


4. Function Calling (Fonksiyon Çağırma / Araç Kullanımı)

Büyük dil modelleri internetteki güncel verileri veya bilgisayarınızdaki yerel dosyaları doğrudan bilemezler. Function Calling, yapay zekaya "ihtiyacın olduğunda şu araçları veya kodları tetikleyebilirsin" yetkisi vermektir.

🛠️ Uygulama: Basit Bir Kod Analiz Aracı Tanımlama

Yapay zekanın bir Python kodundaki hataları denetlemek için yerel bir aracı (linter) çağırabilmesi için gerekli şema hazırlığı:

# Modelin anlayacağı fonksiyon şeması (Araç tanımı)

kod_denetleyici_araci = {

    "type": "function",

    "function": {

        "name": "python_kod_kontrol_et",

        "description": "Verilen Python kodunu hata ve güvenlik açıkları için tarar.",

        "parameters": {

            "type": "object",

            "properties": {

                "kod_icerigi": {

                    "type": "string",

                    "description": "Analiz edilecek ham python kod blokları."

                }

            },

            "required": ["kod_icerigi"]

        }

    }

}


5. API Maliyetlerini Hesaplama ve Yönetme

Yapay zeka servisleri (OpenAI, Anthropic vb.) ücretsiz değildir. Gönderdiğiniz girdiler (input tokens) ve aldığınız çıktılar (output tokens) üzerinden turn başına (karşılıklı her konuşmada) ücretlendirilirsiniz. Konuşma uzadıkça, geçmiş mesajlar da her seferinde tekrar gönderildiği için maliyet katlanarak artar.

🛠️ Uygulama: Token Kullanımını ve Maliyeti Takip Etme

from litellm import completion

 

response = completion(

    model="openai/gpt-4o",

    messages=[{"role": "user", "content": "Bana 5 kelimelik bir motivasyon cümlesi yaz."}]

)

 

# Harcanan token miktarını response üzerinden okuyoruz

girdi_token = response.usage.prompt_tokens

cikti_token = response.usage.completion_tokens

 

# Örnek fiyatlar (Fiyatlar modellere göre değişir)

girdi_maliyeti_1k = 0.005  # 1000 token başı dolar

cikti_maliyeti_1k = 0.015

 

toplam_maliyet = ((girdi_token * girdi_maliyeti_1k) + (cikti_token * cikti_maliyeti_1k)) / 1000

 

print(f"Kullanılan Girdi Token: {girdi_token}")

print(f"Kullanılan Çıktı Token: {cikti_token}")

print(f"Bu sorgunun yaklaşık maliyeti: ${toplam_maliyet:.6f}")


6. Sağlayıcıdan Bağımsız Kodlama: LiteLLM Kullanımı

Eğer kodunuzu sadece OpenAI kütüphanesiyle yazarsanız, yarın bir gün Anthropic (Claude) ya da yerel bir modele geçmek istediğinizde tüm kod tabanınızı baştan aşağı değiştirmeniz gerekir. LiteLLM, tüm yapay zeka sağlayıcılarını tek bir standart çatı altında birleştiren açık kaynaklı harika bir araçtır.

🛠️ Uygulama: Model Değiştirme Deneyimi

import litellm

import os

 

# API anahtarlarını çevre değişkeni olarak tanımlıyoruz

os.environ["OPENAI_API_KEY"] = "your-openai-key"

os.environ["ANTHROPIC_API_KEY"] = "your-anthropic-key"

 

# OpenAI modelini çağırmak için:

yanit_openai = litellm.completion(

    model="gpt-4o",

    messages=[{"role": "user", "content": "Merhaba!"}]

)

 

# Kodda neredeyse hiçbir şeyi değiştirmeden Anthropic modeline geçmek için:

yanit_anthropic = litellm.completion(

    model="anthropic/claude-3-5-sonnet",

    messages=[{"role": "user", "content": "Merhaba!"}]

)


7. Yapay Zeka Kodlama Ajanları ve GitHub Copilot

Yazılım geliştirirken kodları sıfırdan yazmak yerine yapay zeka tabanlı kodlama yardımcılarını (GitHub Copilot, Cursor vb.) bir "yazılım ortağı" gibi kullanmayı öğreneceksiniz. Projenin ana iskeletini (scaffolding) oluşturmaktan test senaryoları yazmaya kadar tüm süreci hızlandırır.


8. Gerçek Bir Proje Geliştirme: Yapay Zeka Destekli CLI Aracı

Kurstaki teorik bilgileri birleştiren ana uygulama, terminal üzerinden (komut satırı) çalışan bir CLI aracı geliştirmektir. Bu araç iki ana işi yapay zeka ile otomatikleştirir:

  1. Smart Commit Messages: Projenizdeki değişen kodları analiz eder (git diff) ve yapılan değişikliklere en uygun, kurallara uygun Git commit mesajını otomatik yazar.
  2. Code Review (Kod İnceleme): Yazdığınız koddaki hataları, mantık açıklarını terminalden çıkmadan yapay zekaya denetletmenizi sağlar.

9. Yapay Zeka Entegreli Kodlar İçin Unit Test (Birim Testi) Yazma

Yapay zeka modelleri her seferinde tamamen aynı yanıtı vermeyebilir (buna deterministik olmayan yapı denir). Peki, çıktısı sürekli değişebilen bir fonksiyonun doğru çalışıp çalışmadığını nasıl test edebiliriz?

İşte burada Mocking (Taklit Etme) devreye girer. Test ortamında gerçek yapay zeka API'sine bağlanıp para harcamak ve rastgele yanıtlar beklemek yerine, API'yi taklit eden sahte fonksiyonlar yazarız. pytest-mock fixture'ları ile litellm.completion fonksiyonunun tam olarak bizim istediğimiz sabit bir test cümlesini döndürmesini sağlarız.

🛠️ Uygulama: Yapay Zeka Fonksiyonunu Test Etme (Mock Örneği)

Yapay zekadan gelen cevaba göre çalışan bir fonksiyonumuz olsun ve biz bunu test edelim:

# Kodumuzun yer aldığı dosya: program.py

import litellm

 

def yapay_zeka_selamla():

    response = litellm.completion(model="gpt-4o", messages=[{"role": "user", "content": "Selam de"}])

    return response.choices[0].message.content.upper() # Gelen cevabı büyütüyor

 

 

# Test dosyamız: test_program.py

def test_yapay_zeka_selamla(mocker):

    # Gerçek API çağrısını engellemek için sahte bir yanıt objesi hazırlıyoruz

    sahte_yanit = mocker.Mock()

    sahte_yanit.choices = [mocker.Mock(message=mocker.Mock(content="Merhaba dunya"))]

   

    # litellm.completion çağrıldığında internete gitme, direkt sahte_yanit'ı döndür diyoruz

    mocker.patch('litellm.completion', return_value=sahte_yanit)

   

    # Fonksiyonu test ediyoruz

    sonuc = yapay_zeka_selamla()

   

    # Fonksiyonumuz çıktıyı BÜYÜTMELİYDİ. "Merhaba dunya" -> "MERHABA DUNYA" olmalı.

    assert sonuc == "MERHABA DUNYA"

    print("Test başarıyla geçti! Gerçek API'ye hiç istek atılmadı.")

 

 

 

 

Gönderdiğiniz belgedeki tüm kritik teknik konuları, production (canlı sistem) seviyesinde, hata yönetimleri ve en iyi pratiklerle harmanlanmış derinlemesine kod uygulamalarıyla genişletelim.

Aşağıdaki tüm uygulamalar birbiriyle uyumlu, modüler ve gerçek projelerinizde doğrudan kullanabileceğiniz şekilde hazırlanmıştır.


1. Tokenization ve Dinamik Context Window Yönetimi

Büyük projelerde LLM'e göndereceğiniz metin bağlam penceresini (Context Window) aşarsa sistem kilitlenir veya bütçeniz hızla tükenir. Bu dinamik yapıyı yönetmek için metni akıllıca kırpan (truncate) ve token sayısını hesaplayan gelişmiş bir sınıf tasarlayalım.

import tiktoken

from typing import List, Dict

 

class ContextManager:

    def __init__(self, model_name: str = "gpt-4"):

        self.model_name = model_name

        try:

            self.encoder = tiktoken.encoding_for_model(model_name)

        except KeyError:

            # Model bulunamazsa varsayılan cl100k_base (cl100k_base gpt-4 ve gpt-3.5 tarafından kullanılır) yüklenir

            self.encoder = tiktoken.get_encoding("cl100k_base")

           

    def count_tokens(self, text: str) -> int:

        """Verilen ham metnin toplam token sayısını hesaplar."""

        if not text:

            return 0

        return len(self.encoder.encode(text))

   

    def count_chat_messages_tokens(self, messages: List[Dict[str, str]]) -> int:

        """OpenAI chat formatındaki (system, user, assistant) mesajların

        arka planda harcayacağı kesin token miktarını hesaplar."""

        # Her mesaj için protokol token ek yükleri vardır

        tokens_per_message = 3

        tokens_per_name = 1

       

        num_tokens = 0

        for message in messages:

            num_tokens += tokens_per_message

            for key, value in message.items():

                num_tokens += self.count_tokens(value)

                if key == "name":

                    num_tokens += tokens_per_name

        num_tokens += 3  # Her yanıtın asistan tarafından başlatılması için gereken ek yük

        return num_tokens

 

    def truncate_text_to_limit(self, text: str, max_tokens: int) -> str:

        """Metni, belirtilen token sınırını aşmayacak şekilde güvenle sondan kırpar."""

        tokens = self.encoder.encode(text)

        if len(tokens) <= max_tokens:

            return text

       

        # Sadece izin verilen sınırdaki tokenları al ve metne geri dönüştür

        truncated_tokens = tokens[:max_tokens]

        return self.encoder.decode(truncated_tokens)

 

# --- Canlı Test Örneği ---

manager = ContextManager("gpt-4")

uzun_kod_blok = "def hesapla(x):\n    return x * 2\n" * 100

 

print(f"Ham Metin Karakter Sayısı: {len(uzun_kod_blok)}")

print(f"Hesaplanan Token Sayısı: {manager.count_tokens(uzun_kod_blok)}")

 

# Güvenli Kırpma Uygulaması

kirpilmis_kod = manager.truncate_text_to_limit(uzun_kod_blok, max_tokens=50)

print(f"50 Token'a Kırpılmış Metin Token Sayısı: {manager.count_tokens(kirpilmis_kod)}")


2. Gelişmiş Prompt Mühendisliği: Çok Adımlı Self-Critique ve Geçişli Kalıplar

Yapay zekaya karmaşık bir yazılım mimarisi inceletirken, önce bir uzman kimliği verip (Persona), ardından adım adım düşünmesini sağlayıp (Chain of Thought), en son kendi çıktısını acımasızca eleştirmesini (Self-Critique) tek bir akışta birleştirelim.

import os

from litellm import completion

from typing import Tuple

 

# API Anahtarı simülasyonu (Kendi anahtarınızı girmelisiniz)

os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "mock-key")

 

class AdvancedPromptPipeline:

    @staticmethod

    def run_review_workflow(implementation_plan: str) -> Tuple[str, str]:

        """Persona, CoT ve Self-Critique kalıplarını ardışık çalıştıran boru hattı."""

       

        # 1. Adım: Persona ve Chain of Thought ile İlk Analiz

        system_prompt = (

            "Sen Kıdemli bir Bulut Çözümleri Mimarı ve Siber Güvenlik Uzmanısın. "

            "Sana verilen mimari planları siber güvenlik, maliyet ve ölçeklenebilirlik açısından incele. "

            "Yanıtını üretirken acele etme, önce sorunları adım adım düşün (<dusunme_asamasi> etiketleri içinde), "

            "ardından nihai analiz raporunu sun."

        )

       

        user_prompt = f"İncelemeni istediğim plan şu şekildedir:\n\n{implementation_plan}"

       

        print("[1/2] Mimar Persona ve CoT ile ilk analiz üretiliyor...")

        first_response = completion(

            model="openai/gpt-4o",

            messages=[

                {"role": "system", "content": system_prompt},

                {"role": "user", "content": user_prompt}

            ],

            temperature=0.2

        )

        initial_analysis = first_response.choices[0].message.content

       

        # 2. Adım: Self-Critique (Öz-Eleştiri) Aşaması

        critique_system_prompt = (

            "Sen katı ve titiz bir Yazılım Kalite Güvence (QA) Direktörüsün. "

            "Bir uzmanın hazırladığı mimari raporu oku. Gözden kaçırdığı potansiyel riskleri, "

            "aşırı maliyetli olabilecek önerileri ve belirsiz kalan noktaları acımasızca eleştirerek raporu güncelle."

        )

       

        critique_user_prompt = (

            f"İlk hazırlanan analiz raporu:\n{initial_analysis}\n\n"

            f"Lütfen bu raporu eleştir ve eksiklerini kapatarak nihai, kusursuz raporu oluştur."

        )

       

        print("[2/2] QA Direktörü kimliğiyle Self-Critique aşaması çalışıyor...")

        second_response = completion(

            model="openai/gpt-4o",

            messages=[

                {"role": "system", "content": critique_system_prompt},

                {"role": "user", "content": critique_user_prompt}

            ],

            temperature=0.1

        )

        final_analysis = second_response.choices[0].message.content

       

        return initial_analysis, final_analysis

 

# --- Çalıştırma ---

plan = "Kullanıcı şifrelerini veritabanında MD5 ile düz metin gibi saklayacağız ve AWS üzerinde tek bir EC2 makinesinde çalışacağız."

# Not: Gerçek bir API anahtarınız varsa aşağıdaki satırı çalıştırabilirsiniz.

# ilk, son = AdvancedPromptPipeline.run_review_workflow(plan)

# print(son)


3. Pydantic ve response_format ile Tipi Garanti Altına Alınmış JSON Çıktı

Yazılım otomasyonlarında ham JSON string parçalamak yerine Python'ın tip güvenceli pydantic kütüphanesini LLM yapılandırılmış çıktıları (Structured Outputs) ile tam entegre kullanmalıyız.

import json

from pydantic import BaseModel, Field

from typing import List, Optional

from litellm import completion

 

# Çıktı formatının şemasını doğrulama kurallarıyla birlikte tanımlıyoruz

class CodeDefectAnalysis(BaseModel):

    has_bug: bool = Field(description="Kod bloklarında herhangi bir bug veya mantık hatası var mı?")

    risk_level: str = Field(description="Hatanın ciddiyeti: 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'")

    line_numbers: List[int] = Field(default=[], description="Hatalı veya iyileştirilmesi gereken satır numaraları.")

    explanation: str = Field(description="Hatanın detaylı açıklaması ve çözüm önerisi.")

    refactored_code: Optional[str] = Field(None, description="Eğer varsa, kodun düzeltilmiş temiz hali.")

 

class StructuredOutputEngine:

    @staticmethod

    def analyze_code_quality(code_snippet: str) -> CodeDefectAnalysis:

        system_instructions = (

            "Sana verilen kaynak kodu analiz et ve hatayı tespit et. "

            "Çıktıyı kesinlikle sağlanan JSON şemasına birebir uyacak şekilde döndür."

        )

       

        # Pydantic şemasını OpenAI/LiteLLM'in anlayacağı JSON Schema formatına çeviriyoruz

        json_schema = CodeDefectAnalysis.model_json_schema()

       

        response = completion(

            model="openai/gpt-4o",

            messages=[

                {"role": "system", "content": system_instructions},

                {"role": "user", "content": f"Analiz edilecek kod:\n{code_snippet}"}

            ],

            response_format={

                "type": "json_object",

                "schema": json_schema  # Şemayı zorunlu kılıyoruz

            },

            temperature=0.0

        )

       

        raw_content = response.choices[0].message.content

        # Gelen ham string'i Pydantic nesnesine dönüştürüp tip kontrolü sağlıyoruz

        data_dict = json.loads(raw_content)

        return CodeDefectAnalysis(**data_dict)

 

# --- Canlı Test Örneği ---

hatali_kod = """1: def bolme_islemi(a, b):

2:     # Burada sıfıra bölme hatası kontrol edilmemiş

3:     sonuc = a / b

4:     return sonuc

"""

# analiz_sonucu = StructuredOutputEngine.analyze_code_quality(hatali_kod)

# print(f"Bug Var mı?: {analiz_sonucu.has_bug} | Seviye: {analiz_sonucu.risk_level}")


4. Gelişmiş Function Calling: Dinamik Araç Kayıt ve Yürütme Döngüsü

Yapay zekanın dış dünyaya (dosya sistemi, API'ler vb.) güvenle açılmasını sağlayan, LLM'den gelen fonksiyon çağrı sinyalini yakalayıp dinamik olarak çalıştıran tam döngülü (Loop) sistem mimarisi:

import json

from litellm import completion

from typing import Dict, Any, Callable

 

# 1. Gerçek Dünyada Çalışacak Fonksiyonları Tanımlayalım (Yerel Araçlar)

def sistem_guvenlik_taramasi(hedef_dizin: str) -> str:

    """Belirtilen dizindeki zararlı olabilecek dosyaları denetler."""

    if "admin" in hedef_dizin.lower():

        return json.dumps({"durum": "TEHLIKE", "bulgular": "Kritik sisteme yetkisiz tarama isteği!"})

    return json.dumps({"durum": "TEMIZ", "bulgular": f"{hedef_dizin} üzerinde şüpheli bir duruma rastlanmadı."})

 

# 2. Araç Kayıt Defteri (Registry) Yapısı

class ToolRegistry:

    def __init__(self):

        self._registry: Dict[str, Tuple[Callable, Dict[str, Any]]] = {}

       

    def register_tool(self, name: str, func: Callable, schema: Dict[str, Any]):

        self._registry[name] = (func, schema)

       

    def get_all_schemas(self) -> list:

        return [details[1] for details in self._registry.values()]

   

    def execute_tool(self, name: str, arguments_str: str) -> str:

        if name not in self._registry:

            return json.dumps({"hata": f"'{name}' isimli araç sistemde bulunamadı."})

       

        func, _ = self._registry[name]

        try:

            args = json.loads(arguments_str)

            return func(**args)

        except Exception as e:

            return json.dumps({"hata": f"Araç çalışırken hata oluştu: {str(e)}"})

 

# 3. Şemayı Hazırlama ve Kayıt İşlemi

tarama_semasi = {

    "type": "function",

    "function": {

        "name": "sistem_guvenlik_taramasi",

        "description": "Belirtilen yerel dizini güvenlik açıkları ve yetkisiz dosyalar için tarar.",

        "parameters": {

            "type": "object",

            "properties": {

                "hedef_dizin": {"type": "string", "description": "Taranacak klasörün tam yolu (örn: /var/www veya /home/user)"}

            },

            "required": ["hedef_dizin"]

        }

    }

}

 

registry = ToolRegistry()

registry.register_tool("sistem_guvenlik_taramasi", sistem_guvenlik_taramasi, tarama_semasi)

 

# 4. Yapay Zeka Araç Yönetim Döngüsü (Agent Loop)

def run_agent_turn(user_query: str):

    messages = [{"role": "user", "content": user_query}]

   

    # LLM'e mevcut araçlarımızı bildirerek çağrı yapıyoruz

    response = completion(

        model="openai/gpt-4o",

        messages=messages,

        tools=registry.get_all_schemas(),

        tool_choice="auto"

    )

   

    response_message = response.choices[0].message

   

    # Yapay zeka bir fonksiyon çalıştırmak istedi mi?

    if response_message.get("tool_calls"):

        print("-> Yapay zeka yerel bir aracı tetikleme kararı aldı.")

        messages.append(response_message) # Asistanın kararını geçmişe ekle

       

        for tool_call in response_message["tool_calls"]:

            func_name = tool_call.function.name

            func_args = tool_call.function.arguments

           

            # Aracı çalıştırıp cevabını alıyoruz

            tool_result = registry.execute_tool(func_name, func_args)

            print(f"   [Araç Çıktısı]: {tool_result}")

           

            # Aracın ürettiği sonucu LLM'e geri bildirmek üzere mesaj geçmişine ekliyoruz

            messages.append({

                "tool_call_id": tool_call.id,

                "role": "tool",

                "name": func_name,

                "content": tool_result

            })

           

        # Model aracı kullandıktan sonra nihai bir insani özet çıkarsın diye tekrar çağırıyoruz

        final_response = completion(model="openai/gpt-4o", messages=messages)

        return final_response.choices[0].message.content

   

    return response_message.content

 

# --- Test ---

# print(run_agent_turn("/etc/admin klasörünü acil tarar mısın?"))


5. Multi-Turn Konuşmalarda Kümülatif Maliyet Takip Sistemi

Yapay zeka ile karşılıklı konuşma (chat) uzadıkça, her yeni mesajda önceki tüm konuşma geçmişi (Context) modele tekrar iletilir. Bu durum girdi token maliyetlerini geometrik olarak artırır. Bunu izleyen gerçekçi bir bütçe takip motoru hazırlayalım:

class TokenCostTracker:

    # Model bazlı anlık fiyat listesi (1000 Token Başına Dolar Cinsinden)

    PRICING = {

        "gpt-4o": {"input": 0.0050, "output": 0.0150},

        "claude-3-5-sonnet": {"input": 0.0030, "output": 0.0150}

    }

 

    def __init__(self, model_name: str = "gpt-4o"):

        self.model_name = model_name

        self.total_input_tokens = 0

        self.total_output_tokens = 0

        self.total_cost = 0.0

       

    def log_turn(self, response_usage_obj) -> float:

        """API yanıtından gelen usage objesini okuyarak kümülatif maliyeti günceller."""

        prompt_tokens = response_usage_obj.prompt_tokens

        completion_tokens = response_usage_obj.completion_tokens

       

        self.total_input_tokens += prompt_tokens

        self.total_output_tokens += completion_tokens

       

        # Maliyet hesaplama

        model_prices = self.PRICING.get(self.model_name, {"input": 0.0, "output": 0.0})

        turn_cost = ((prompt_tokens * model_prices["input"]) + (completion_tokens * model_prices["output"])) / 1000

       

        self.total_cost += turn_cost

        return turn_cost

   

    def get_summary_report(self) -> str:

        return (

            f"--- BÜTÇE VE KULLANIM RAPORU ({self.model_name}) ---\n"

            f"Toplam Girdi (Input) Token: {self.total_input_tokens}\n"

            f"Toplam Çıktı (Output) Token: {self.total_output_tokens}\n"

            f"Şu Ana Kadar Harcanan Toplam Tutar: ${self.total_cost:.6f}\n"

            f"----------------------------------------"

        )

 

# --- Simüle Edilmiş Oturum Akışı ---

tracker = TokenCostTracker("gpt-4o")

 

# 1. Karşılıklı Konuşma Adımı (Küçük Veri)

# response1 = completion(...) -> tracker.log_turn(response1.usage)

# 2. Konuşma Adımı (Geçmiş eklendiği için girdi tokenları şişer)

# response2 = completion(...) -> tracker.log_turn(response2.usage)


6. Sağlayıcı Değiştirebilen (Ollama / Local Destekli) Soyut Mimari

Projenizin tek bir LLM sağlayıcısına bağımlı kalmaması için, konfigürasyon üzerinden yerel (Ollama / Llama3) veya bulut (OpenAI, Anthropic) arasında sıfır kod değişimiyle geçiş sağlayan esnek yapıyı inşa edelim.

import os

import litellm

from typing import List, Dict, Any

 

class AgnosticLLMEngine:

    def __init__(self, provider: str = "openai", local_url: str = None):

        """

        provider: 'openai', 'anthropic' veya 'ollama'

        """

        self.provider = provider.lower()

        self.local_url = local_url or "http://localhost:11434" # Ollama varsayılan portu

       

    def generate_text(self, messages: List[Dict[str, str]], model_name: str, **kwargs) -> str:

        call_params: Dict[str, Any] = {

            "messages": messages,

            **kwargs

        }

       

        if self.provider == "openai":

            call_params["model"] = f"openai/{model_name}"

        elif self.provider == "anthropic":

            call_params["model"] = f"anthropic/{model_name}"

        elif self.provider == "ollama":

            # Ollama yerel sunucusu için LiteLLM API base yönlendirmesi yapar

            call_params["model"] = f"ollama/{model_name}"

            call_params["api_base"] = self.local_url

        else:

            raise ValueError(f"Desteklenmeyen sağlayıcı: {self.provider}")

           

        # Birleşik arayüz üzerinden çağrıyı gerçekleştiriyoruz

        response = litellm.completion(**call_params)

        return response.choices[0].message.content

 

# --- Kullanım Çeşitliliği Örneği ---

# Yerel Ollama altyapısında bilgisayarınızda yüklü olan llama3'ü tetiklemek için:

# local_engine = AgnosticLLMEngine(provider="ollama")

# print(local_engine.generate_text([{"role":"user","content":"Selam!"}], model_name="llama3"))

 

# Aynı metodu bulut servis sağlayıcısı ile çalıştırmak için:

# cloud_engine = AgnosticLLMEngine(provider="anthropic")

# print(cloud_engine.generate_text([{"role":"user","content":"Selam!"}], model_name="claude-3-5-sonnet"))


7. Tam Güvenli Unit Test (Pytest Mocking) Senaryosu

Yapay zeka entegrasyonu barındıran uygulamanızın (Örn: Git diff okuyup commit mesajı üreten CLI fonksiyonunuzun) test kodlarını yazarken internete çıkmasını engellemek, her zaman kararlı ve masrafsız çalışmasını sağlamak için profesyonel test kurgusu:

# --- KOD DOSYASI: app_logic.py ---

import litellm

 

def generate_git_commit_suggestion(git_diff_text: str) -> str:

    """Git değişikliklerini okuyup standart kurallı commit mesajı üretir."""

    if not git_diff_text.strip():

        return "chore: no changes detected"

       

    prompt = f"Aşağıdaki git diff kodunu oku ve tek satırlık commit mesajı yaz:\n{git_diff_text}"

   

    response = litellm.completion(

        model="gpt-4o",

        messages=[{"role": "user", "content": prompt}],

        temperature=0.0

    )

    return response.choices[0].message.content.strip()

 

 

# --- TEST DOSYASI: test_app_logic.py ---

import pytest

from unittest.mock import MagicMock

 

def test_generate_git_commit_suggestion_with_mock(mocker):

    # 1. ADIM: LiteLLM yanıt şablonunu taklit eden (mock) bir sahte nesne hiyerarşisi kuruyoruz

    mock_response = MagicMock()

    mock_choice = MagicMock()

    mock_message = MagicMock()

   

    # Yapay zekanın döndüreceği sahte commit metnini enjekte ediyoruz

    mock_message.content = "feat(auth): implement jwt token rotation mechanism"

    mock_choice.message = mock_message

    mock_response.choices = [mock_choice]

   

    # 2. ADIM: Gerçek 'litellm.completion' fonksiyonunun önünü kesip bizim sahte nesneyi vermesini sağlıyoruz

    patched_completion = mocker.patch("litellm.completion", return_value=mock_response)

   

    # 3. ADIM: Fonksiyonu test girdisiyle çağırıyoruz

    test_diff = "+  def rotate_jwt_token(self): pass"

    generated_msg = generate_git_commit_suggestion(test_diff)

   

    # 4. ADIM: Doğrulama (Assertions)

    # Fonksiyon bizim sahte cevabımızı manipüle etmeden alabildi mi?

    assert generated_msg == "feat(auth): implement jwt token rotation mechanism"

   

    # Arka planda gerçekten de bizim patch'lediğimiz fonksiyon çağrıldı mı?

    patched_completion.assert_called_once()

   

    print("\n✅ Yapay zeka unit testi başarıyla tamamlandı. API bağımlılığı izole edildi.")

 

 

Bu iki güçlü özelliği tek bir yapıda birleştiriyoruz! Projenizin kod değişikliklerini (git diff) okuyan, yerel bir güvenlik/kalite kontrolünden (Linter) geçiren ve ardından tüm bu bulguları yapay zekaya analiz ettirerek kurallara uygun Git Commit mesajları ve kod inceleme raporları sunan, terminalden çalışan (CLI) tam teşekküllü bir otomasyon aracı inşa edeceğiz.

Projemizi sıfırdan oluşturmak, bağımlılıkları yönetmek ve terminale entegre etmek için Python'ın modern standart komut satırı kütüphanesi olan click ve kod analizi için flake8 / bandit mantığını taklit eden bir yapı kullanacağız.


Proje Dosya Yapısı

Projemizin klasör mimarisi şu şekilde olacaktır:

ai_cli_tool/

│

├── ai_engine.py       # Yapay zeka motoru ve prompt şablonları

├── linter.py          # Yerel kod kalitesi ve güvenlik denetleyicisi (Linter)

├── cli.py             # Click kütüphanesi ile CLI komut yönetimi

└── requirements.txt   # Gerekli kütüphaneler listesi


1. Adım: Bağımlılıkların Belirlenmesi (requirements.txt)

Öncelikle projenizin çalışması için gerekli kütüphaneleri içeren dosyayı oluşturun:

click>=8.0.0

litellm>=1.0.0

tiktoken>=0.5.0

pydantic>=2.0.0


2. Adım: Yerel Güvenlik ve Kalite Denetleyicisi (linter.py)

Bu modül, projenizdeki Python dosyalarını yapay zekaya göndermeden önce yerel olarak analiz eder. Kodun içindeki tehlikeli fonksiyonları (örn: eval, exec), zayıf şifreleme algoritmalarını (örn: md5) ve temel sözdizimi/stil hatalarını (örn: çok uzun satırlar, boş fonksiyonlar) yakalar.

import re

from typing import List, Dict, Any

 

class LocalSecurityLinter:

    """Yerel kod kalitesi ve temel siber güvenlik açıklarını tarayan motor."""

   

    @staticmethod

    def analyze_code_string(filename: str, code_content: str) -> List[Dict[str, Any]]:

        issues = []

        lines = code_content.split('\n')

       

        # Güvenlik ve kalite için regex kuralları

        security_patterns = {

            r"eval\(|exec\(": {"level": "CRITICAL", "msg": "Tehlikeli dinamik kod yürütme fonksiyonu (eval/exec) kullanımı tespit edildi!"},

            r"md5\(": {"level": "HIGH", "msg": "Zayıf ve kırılmış şifreleme algoritması (MD5) tespiti. SHA-256 tercih edilmelidir."},

            r"password\s*=\s*['\"][^'\"]+['\"]": {"level": "HIGH", "msg": "Kod içinde açık metin (Hardcoded) şifre/parola tanımlanmış olabilir!"},

            r"http://": {"level": "MEDIUM", "msg": "Güvensiz HTTP bağlantısı tespiti. HTTPS protokolü kullanılmalıdır."}

        }

       

        for idx, line in enumerate(lines, start=1):

            # 1. Güvenlik Taramaları

            for pattern, info in security_patterns.items():

                if re.search(pattern, line):

                    issues.append({

                        "file": filename,

                        "line": idx,

                        "category": "SECURITY",

                        "level": info["level"],

                        "message": info["msg"],

                        "code_snippet": line.strip()

                    })

           

            # 2. Kod Kalitesi Taramaları

            if len(line) > 100:

                issues.append({

                    "file": filename,

                    "line": idx,

                    "category": "QUALITY",

                    "level": "LOW",

                    "message": "Satır uzunluğu PEP8 standart sınırı olan 100 karakteri aşmaktadır.",

                    "code_snippet": line.strip()

                })

               

            if "except:" in line:

                issues.append({

                    "file": filename,

                    "line": idx,

                    "category": "QUALITY",

                    "level": "MEDIUM",

                    "message": "Çok geniş kapsamlı (Bare except) hata yakalama. Spesifik hata sınıfları belirtilmelidir.",

                    "code_snippet": line.strip()

                })

               

        return issues


3. Adım: Yapay Zeka Motoru ve Yapılandırılmış Çıktılar (ai_engine.py)

Yapay zeka ile iletişim kurduğumuz katmandır. Hem otomatik commit mesajları üretir hem de linter'dan gelen çıktıları yorumlayarak akıllı bir rapor hazırlar. Pydantic şeması kullanarak modelden kusursuz JSON verisi alırız.

import os

import json

from pydantic import BaseModel, Field

from typing import List, Optional

import litellm

 

# Yapay zekanın döndüreceği yapılandırılmış analiz şeması

class AIReviewReport(BaseModel):

    summary: str = Field(description="Kod değişikliklerinin ve linter bulgularının genel özeti.")

    critical_risks: List[str] = Field(description="Kodda acilen çözülmesi gereken en riskli noktalar.")

    refactor_suggestion: Optional[str] = Field(description="Hataları çözen, temiz ve optimize edilmiş düzeltme kod örneği.")

 

class AICLIEngine:

    def __init__(self):

        # Varsayılan model tanımı (İsterseniz çevre değişkenlerinden de beslenebilir)

        self.model = "openai/gpt-4o"

       

    def generate_commit_message(self, git_diff: str) -> str:

        """Git değişiklik analizine göre kurallara uygun konvansiyonel commit mesajı yazar."""

        if not git_diff.strip():

            return "chore: no changes detected"

           

        system_prompt = (

            "Sen profesyonel bir yazılım sürüm yöneticisisin. Sana verilen Git Diff (kod değişiklikleri) çıktısını oku. "

            "Değişikliğin türüne göre (feat, fix, docs, style, refactor, test, chore) kurallara uygun, "

            "öz, sadece TEK BİR SATIRLIK conventional commit mesajı oluştur. Başka hiçbir şey yazma."

        )

       

        response = litellm.completion(

            model=self.model,

            messages=[

                {"role": "system", "content": system_prompt},

                {"role": "user", "content": f"Git Değişiklikleri:\n{git_diff}"}

            ],

            temperature=0.1

        )

        return response.choices.message.content.strip()

 

    def generate_smart_review(self, code_content: str, linter_findings: List[dict]) -> AIReviewReport:

        """Yerel linter bulgularını ve kaynak kodu harmanlayarak akıllı inceleme raporu üretir."""

        system_prompt = (

            "Sen kıdemli bir kod kalitesi ve siber güvenlik denetçisisin. Kullanıcının kaynak kodunu "

            "ve yerel statik analiz aracından (linter) gelen uyarıları incele. "

            "Hataların neden sorun yarattığını açıklayan ve nasıl çözüleceğini gösteren yapılandırılmış bir rapor hazırla."

        )

       

        user_content = {

            "source_code": code_content,

            "local_linter_warnings": linter_findings

        }

       

        response = litellm.completion(

            model=self.model,

            messages=[

                {"role": "system", "content": system_prompt},

                {"role": "user", "content": json.dumps(user_content, ensure_ascii=False)}

            ],

            response_format={"type": "json_object", "schema": AIReviewReport.model_json_schema()},

            temperature=0.2

        )

       

        raw_json = json.loads(response.choices.message.content)

        return AIReviewReport(**raw_json)


4. Adım: Click Komut Satırı Arayüzü (cli.py)

Tüm parçaların birleştiği, terminal ekranından kullanıcıyla etkileşime geçen ana giriş kapısıdır. Bu dosya üzerinden terminal komutlarımızı yönetiriz.

import click

import subprocess

import os

import json

from linter import LocalSecurityLinter

from ai_engine import AICLIEngine

 

# CLI Araç Grubumuzu Tanımlıyoruz

@click.group()

def main():

    """🤖 AI-CLI: Yapay Zeka Destekli Geliştirici ve Güvenlik Otomasyon Aracı."""

    pass

 

@main.command()

@click.option('--file', '-f', type=click.Path(exists=True), help="Doğrudan taranacak dosyanın yolu.")

def lint(file):

    """Linter ve Yapay Zeka ile kod kalitesi/güvenlik taraması gerçekleştirir."""

    if not file:

        click.echo(click.style("❌ Hata: Lütfen taramak için bir dosya yolu belirtin. Örn: -f dosya.py", fg="red"))

        return

 

    click.echo(click.style(f"🔍 {file} dosyası üzerinde yerel linter çalıştırılıyor...", fg="cyan"))

   

    with open(file, 'r', encoding='utf-8') as f:

        code_content = f.read()

       

    # 1. Yerel linter'ı çalıştır

    linter_issues = LocalSecurityLinter.analyze_code_string(file, code_content)

   

    if linter_issues:

        click.echo(click.style(f"⚠️ Yerel taramada {len(linter_issues)} adet potansiyel sorun bulundu!", fg="yellow"))

        for issue in linter_issues:

            click.echo(f"  [{issue['category']}] Satır {issue['line']} ({issue['level']}): {issue['message']}")

    else:

        click.echo(click.style("✅ Yerel statik analiz temiz çıktı.", fg="green"))

       

    # 2. Yapay zekaya derin analiz yaptır

    click.echo(click.style("🧠 Bulgular yapay zeka denetçisine gönderiliyor...", fg="magenta"))

    ai = AICLIEngine()

   

    try:

        report = ai.generate_smart_review(code_content, linter_issues)

       

        click.echo("\n" + click.style("=== YAPAY ZEKA İNCELEME RAPORU ===", fg="green", bold=True))

        click.echo(click.style("📝 Özet:", fg="cyan") + f" {report.summary}")

       

        if report.critical_risks:

            click.echo(click.style("\n🚨 Kritik Riskler ve Açıklar:", fg="red", bold=True))

            for risk in report.critical_risks:

                click.echo(f"  • {risk}")

               

        if report.refactor_suggestion:

            click.echo(click.style("\n💡 Önerilen Güvenli Kod Değişikliği (Refactored):", fg="green"))

            click.echo(click.style(report.refactor_suggestion, fg="white"))

           

    except Exception as e:

        click.echo(click.style(f"❌ Yapay zeka analizi sırasında bir sorun oluştu: {str(e)}", fg="red"))

 

 

@main.command()

@click.option('--execute', '-e', is_flag=True, help="Üretilen commit mesajını onay sonrası otomatik commit eder.")

def commit(execute):

    """Git staging alanındaki (staged) değişiklikleri analiz edip akıllı commit mesajı üretir."""

    # Git diff kodunu terminalden alıyoruz

    try:

        diff_output = subprocess.check_output(["git", "diff", "--staged"], text=True)

    except subprocess.CalledProcessError:

        click.echo(click.style("❌ Git diff komutu çalıştırılamadı. Bir git reposunda olduğunuzdan emin olun.", fg="red"))

        return

       

    if not diff_output.strip():

        click.echo(click.style("⚠️ Staging alanında (git add) bekleyen bir değişiklik bulunamadı!", fg="yellow"))

        return

       

    click.echo(click.style("📝 Git değişiklikleri analiz ediliyor...", fg="cyan"))

    ai = AICLIEngine()

    commit_msg = ai.generate_commit_message(diff_output)

   

    click.echo("\n" + click.style("🤖 Önerilen Commit Mesajı:", fg="magenta", bold=True))

    click.echo(click.style(f"   {commit_msg}", fg="white", bg="blue"))

   

    # Eğer kullanıcı otomatik çalıştırma bayrağı (-e) eklediyse veya onay verirse commit et

    if execute:

        if click.confirm("\nBu mesajla commit işlemini onaylıyor musunuz?", default=True):

            subprocess.run(["git", "commit", "-m", commit_msg])

            click.echo(click.style("🚀 Kod başarıyla commit edildi!", fg="green"))

        else:

            click.echo(click.style("❌ İşlem kullanıcı tarafından iptal edildi.", fg="yellow"))

 

if __name__ == '__main__':

    main()


Nasıl Test Edilir ve Çalıştırılır?

1. Hazırlık ve Ortam Kurulumu

Öncelikle gerekli kütüphaneleri yükleyin ve OpenAI API anahtarınızı terminale tanımlayın:

pip install -r requirements.txt

export OPENAI_API_KEY="sk-your-real-api-key-here"

2. Güvenlik ve Kalite Linter Aracını Test Etme

Uygulamayı test etmek için içinde bilerek siber güvenlik açığı barındıran sahte bir Python dosyası oluşturalım (deneme.py):

# deneme.py içeriği

import hashlib

 

def login_user(username, password_raw):

    # Açık açık kod içinde şifre saklama riski

    system_pass = "123456_admin_secret"

   

    # Güvensiz şifreleme algoritması (MD5) kullanımı

    hashed = hashlib.md5(password_raw.encode()).hexdigest()

   

    # Güvensiz ağ protokolü çağrısı uyarısı

    api_url = "http://internal.company"

   

    eval("print('Giris yapiliyor')") # Kritik güvenlik riski

    return hashed

Şimdi bu hatalı dosyayı CLI aracımızla denetleyelim:

python cli.py lint -f deneme.py

Terminal Çıktısı: Aracınız önce LocalSecurityLinter sayesinde eval, md5, http:// ve password kalıplarını yakalayacak, ardından bunları GPT-4o modeline göndererek size harika bir güvenli kod mimari düzeltmesi (Refactoring) ve raporu basacaktır!

3. Yapay Zeka Destekli Akıllı Commit Aracını Test Etme

Bir dosyayı değiştirip git add yaptıktan sonra terminale şu komutu vermeniz yeterlidir:

python cli.py commit -e

Araç kodun içindeki satır değişikliklerini çıkarıp doğrudan size feat(auth): secure login architecture with sha-256 and remove eval gibi nokta atışı bir öneri sunacak ve onaylarsanız commit işlemini gerçekleştirecektir.

 

 

Uygulamanızı yerel bilgisayarınızda küresel bir komut gibi (ai-cli lint veya ai-cli commit) doğrudan çalıştırabilmeniz için projeyi modern paketleme standartlarına uygun hale getirelim.

Günümüzün modern Python standartlarına en uygun yaklaşım olan pyproject.toml dosyasını kullanacağız. Bu dosya, projenizin bağımlılıklarını ve terminale kaydedilecek kısayol komutlarını (entry-points) tek bir yerden yönetmenizi sağlar.


1. Adım: Proje Klasör Düzenini Güncelleme

Komut satırı araçlarının temiz kurulabilmesi için kaynak kodlarımızı bir paket klasörü altına toplamak en iyi pratiktir. Dosya yapınızı şu küçük değişiklikle güncelleyin:

ai_cli_tool/

│

├── pyproject.toml     # Yeni ekleyeceğimiz paket yapılandırma dosyası

├── requirements.txt   # Mevcut bağımlılıklar listesi

│

└── src/               # Kodlarımızı bu klasörün içine taşıyoruz

    ├── __init__.py    # Boş bir dosya (klasörü paket yapmak için)

    ├── ai_engine.py

    ├── cli.py

    └── linter.py

Not: src klasörünü oluşturun, __init__.py adında tamamen boş bir dosya ekleyin ve önceki adımda yazdığımız ai_engine.py, cli.py ve linter.py dosyalarını bu src/ klasörünün içine taşıyın.


2. Adım: pyproject.toml Dosyasını Oluşturma

Projenizin ana dizinine (yani src/ klasörünün dışına, yanına) pyproject.toml isimli bir dosya açın ve içine şu kodları ekleyin:

[build-system]

requires = ["setuptools>=61.0.0", "wheel"]

build-backend = "setuptools.build_meta"

 

[project]

name = "ai-cli-tool"

version = "0.1.0"

description = "Yapay Zeka Destekli Geliştirici ve Güvenlik Otomasyon Aracı"

readme = "README.md"

requires-python = ">=3.8"

authors = [

    { name = "Geliştirici", email = "developer@example.com" }

]

classifiers = [

    "Programming Language :: Python :: 3",

    "License :: OSI Approved :: MIT License",

    "Operating System :: OS Independent",

]

dependencies = [

    "click>=8.0.0",

    "litellm>=1.0.0",

    "tiktoken>=0.5.0",

    "pydantic>=2.0.0",

]

 

# 🚀 İşte terminale 'ai-cli' komutunu kaydeden sihirli alan!

[project.scripts]

ai-cli = "src.cli:main"

Bu Yapılandırmada Ne Yaptık?


3. Adım: Yerel Geliştirici Modunda Kurulum (Editable Install)

Yapılandırmayı tamamladıktan sonra projenizi bilgisayarınıza bir Python paketi gibi kaydetmemiz gerekiyor. Ancak kod üzerinde değişiklik yapmaya devam edeceğimiz için bunu düzenlenebilir (editable) modda kuracağız. Böylece koddaki değişiklikleriniz anında terminal komutuna yansır, her seferinde yeniden kurmak zorunda kalmazsınız.

Terminalinizi açın, pyproject.toml dosyasının bulunduğu ana dizine gelin ve şu komutu çalıştırın:

pip install -e .

(Eğer sanal ortam kullanıyorsanız - venv - sanal ortamın aktif olduğundan emin olun.)


4. Adım: Artık Hazırsınız! Terminalden Test Edin

Kurulum bittikten sonra terminalinizde python cli.py ... şeklinde dosya çağırma devri bitti! Artık terminalin her yerinden projenizi küresel bir araç gibi çağırabilirsiniz:

Güvenlik ve Linter Taraması İçin:

ai-cli lint -f src/linter.py

Otomatik Git Commit Mesajı İçin:

ai-cli commit -e

Yardım Menüsünü Görmek İçin:

ai-cli --help