FlowExecutor (Modules/AI/app/Services/Workflow/FlowExecutor.php) ana orchestrator'dır. Akış, JSON tabanlı flow tanımı ile çalışır.
| Özellik | Açıklama |
|---|---|
| Tenant Awareness | Her node, tenancy() konteksti içinde çalışır. Tenant-specific node'lar otomatik yüklenir. |
| Node Chaining | Edge tanımları üzerinden, node'dan node'a sırayla geçiş. Conditional branching destekli. |
| Context Passing | Her node, context array'i alır ve extend eder. Sonraki node'a ek bilgiler aktarılır. |
| Parallel Groups | Birden fazla node paralel çalışabilir (ParallelNodeExecutor). Sonuçlar merge edilir. |
| Caching | Category detection ve history loading cache'lenir. ai_response ve product_search cache'lenmez. |
Dosya: Modules/AI/app/Services/Workflow/Nodes/WelcomeNode.php
Basit pass-through node. Flow başlatma işlevi görür.
Dosya: Modules/AI/app/Services/Workflow/Nodes/CategoryDetectionNode.php
Global olarak generic kategori tespiti yapılır, ama Tenant 2 için özel mantık yok. Tenant2ProductSearchService içinde real kategori tespiti yapılır.
| Girdi | İşlev | Çıktı |
|---|---|---|
| user_message | Fallback: Generic kategori tespiti (mostly null) | detected_category: null (Tenant2 servisi override eder) |
Dosya: Modules/AI/app/Services/Workflow/Nodes/ProductSearchNode.php
Tenant-specific arama servisi kullanır. Tenant 2 için Tenant2ProductSearchService otomatik yüklenir.
| Girdi | İşlev | Çıktı |
|---|---|---|
| user_message |
1. Tenant2ProductSearchService::search() çağrılır 2. HybridSearchService (Meilisearch + Vector) kullanılır 3. Yedek parça filtresi uygulanır (isSparePartRequest) 4. Ürün listesi döndürülür |
products: Collection<ShopProduct> products_found: int detected_category: int|null |
Arama sonuçlarından yedek parça ürünleri filtreler. Temizleme kriterleri:
Fakat: isSparePartRequest = true ise, yedek parça tekrar gösterilir.
Dosya: Modules/AI/app/Services/Workflow/Nodes/StockSorterNode.php
Professionel 6-katmanlı sıralama sistemi.
| Sıra | Kriter | Yön |
|---|---|---|
| 🥇 1. | Vitrin Ürünleri (show_on_homepage = 1) | DESC (1 önce) |
| 🥈 2. | Stok Durumu (current_stock > 0) | DESC (stoklu önce) |
| 🥉 3. | Kategori Sıraması (sort_order) | ASC (küçük önce) |
| 4. | Fiyat Durumu (base_price > 0) | DESC (fiyatlı önce) |
| 5. | Fiyat Değeri (base_price) | ASC (ucuz önce) |
Dosya: Modules/AI/app/Services/Workflow/Nodes/ContextBuilderNode.php
Ürünleri Markdown formatında, AI'nin anlayacağı şekilde hazırlar.
| Girdi | İşlev | Çıktı |
|---|---|---|
| products: Collection |
1. USD → TRY conversion 2. Ürün başlığını temizle (2. Ton → 2 Ton) 3. Markdown formatında ürün listesi oluştur 4. Kategori etiketi ekle (<[KATEGORI]>) 5. Fiyat gösterimi (KDV hariç, sembol koruması) |
product_context: Markdown string products_found: int |
Dosya: Modules/AI/app/Services/Workflow/Nodes/AIResponseNode.php (341 satır!)
En karmaşık node. Sistem prompt'u dinamik olarak oluşturur.
OpenAI (gpt-4.1-mini model kullanılıyor)
| Parametre | Değer |
|---|---|
| model | gpt-4.1-mini |
| max_tokens | 500 (directive'den değişebilir) |
| temperature | 0.7 |
| streaming | false (default) |
Dosya: Modules/AI/app/Services/Workflow/Nodes/MessageSaverNode.php
Placeholder node. Gerçek kaydetme, controller tarafından yapılır.
Flow sonu işareti.
Dosya: Modules/AI/app/Services/Tenant/Tenant2ProductSearchService.php (837 satır!)
| Kategori ID | Adı | Anahtar Kelimeler |
|---|---|---|
| 1 | Forklift | forklift, fork lift, portif, akülü forklift, elektrikli forklift |
| 2 | Transpalet | transpalet, trans palet, palet jack, pallet truck |
| 3 | İstif Makinesi | istif makinesi, istif, stacker |
| 4 | Sipariş Toplama | sipariş toplama, order picker, picking |
| 5 | Otonom Sistemler | otonom, autonomous, agv, otomatik, robot |
| 6 | Reach Truck | reach truck, reach, dar koridor |
Şu ürün adı anahtar kelimeler içeriyorsa yedek parça olarak işaretlenir:
Fakat: isSparePartRequest() = true ise, yedek parça gösterilir.
Dosya: Modules/AI/app/Services/Tenant/Tenant2PromptService.php (822 satır!)
Tenant 2 (iXTİF) için tüm AI davranış kurallarını içerir.
FileLearningService.buildLearningContext() kullanıcı tercihlerini ekledi.
Örneğin: "F4 1.5 Ton transpalet" en çok satılan ürün ise, arama sonuçlarında ilk sıraya koyul.
Dosya: app/Services/AI/HybridSearchService.php
İki arama tekniğini birleştirerek en iyi sonuçlar sunar.
| Arama Tipi | Motor | Ağırlık | Özellikleri |
|---|---|---|---|
| Keyword Search | Meilisearch | 70% | Hızlı, typo-tolerant, exact match, stemming |
| Semantic Search | Vector DB (embeddings) | 30% | Anlamsal eşleşme, benzer ürünler bulma |
| Adım | İşlem | Çıktı |
|---|---|---|
| 1. Hazırlık | Ürünleri Collection'a dönüştür | $products = collect(...) |
| 2. Currency | USD → TRY çeviri (exchange_rate: 42.0) | $priceInTRY = $basePrice * 42 |
| 3. Başlık Temizliği | "2. Ton" → "2 Ton" | preg_replace('/(\d+)\.\s+(Ton)/u', '$1 $2', $title) |
| 4. Markdown Oluşturma | Her ürün için Markdown format | ### Ürün Adı\n- Özellik\n- Fiyat\n[Link] |
| 5. Görsel Ekleme | Spatie Media Library'den first image | 📷 Görsel: {URL} |
| 6. Fiyat Gösterimi | Fiyatlı ürünlerde format: "52.948 TL ≈ $1.250" | - **{price} {currency}** ≈ {original} |
| 7. Link Ekleme | Ürün slug'ından shop link | - [Ürünü İncele](/shop/{slug}) |
Ürün gösterilir, fiyat SATIRI ATLANIR. Nedeni: Context'te hiç fiyat satırı yoksa AI "Fiyat bilgisi için iletişime geçin" mesajı verir.
Stok Bilgisi:ASLA verilmez. Stok durumu AI'nin belirsiz talep kontrolüne yardımcı olmaması için gizlenir.
Kategori Etiketi:Meilisearch'ten gelen ürünlerin kategorisine göre [TRANSPALET], [FORKLIFT] vb. etiketi eklenir.
AI 1-2 temel soru sorar (Tonnaj + Elektrikli mi?). Hiç ürün göstermez.
Tetikleyiciler (BELİRLİ):AI hemen ürün listesi gösterir. Soru ASLA sorması.
Uyarı: Bu kontrol AIResponseNode'da yapılır. Context'te ürünler varsa bile, belirsiz istekte soru sorma kuralı devreye girer!
Müşteri "forklift istiyorum" dediğinde, çatal, rulman gibi parçalar gösterilmemeli. Confusing!
Fiyat MUTLAKA gösterilir. Format: "- **52.948 TL** ≈ $1.250"
Fiyatsız Ürün (base_price = 0):Context'te FİYAT SATIRI YOK. AI "Müşteri temsilcilerimizle iletişime geçerek teklif alabilirsiniz" der.
Stoksuz Ürün (current_stock = 0):Context'te ürün gösterilir ama stok bilgisi YOK. AI "Tedarik süresi için iletişime geçin" der.
KDV Notasyonu:ASLA "(KDV dahil)" yazılmaz. Tüm fiyatlar KDV HARİÇ.
Önemli: Tenant2PromptService::buildPrompt() içinde tekrar vurgulanıyor: "Context'teki fiyatları BİREBİR AYNEN kullan!"
Conversation history'deki mesajlar AIResponseNode'a geçilir. AI, önceki mesajlardan konteksti anlar ve AYNI kategoride kal.
Not: Bu Tenant2PromptService'de "KATEGORİ HAFIZASI - KRİTİK!" başlığı altında yazılıyor.
Kullanıcı "WhatsApp", "telefon", "numara", "iletişim" yazarsa → DİREKT numara ver! Ürün sorusu SORMA!
Kural 2: Ürün Sorusu GelirseKullanıcı ürün arıyorsa → Önce ürün göster (MUTLAKA linkle!), sonra ilgilendiyse "Telefon numaranız?" sor.
Kural 3: Pazarlık DurumuKullanıcı "İndirim var mı?" derse → Müşteri temsilcisine yönlendir. "Size özel fiyat için telefon numaranızı alabilir miyim?"
Fallback:Numara alamazsan → Bizim WhatsApp linkini ver: wa.me/{cleanWhatsapp}
Kritik: Telefon/WhatsApp numaraları settings'den gelir (hardcode yok!). AISettingsHelper::getContactInfo()
AIResponseNode::prepareMessages() içinde, system prompt'tan sonra, user message'dan önce.
History Nasıl Filtreler?Eğer şu anki aramalda ürün yoksa, eski ürün önerileri history'den çıkarılır (clean up).
KRITIK KURAL: Atıf Yapma!Kullanıcı, önceki konuşmayı hatırlamayabilir. Karışıklık yaratır.
Dosya: AIResponseNode.php (satır 239-245)
Sorun: API key'in environment'tan yüklenmesine dair debug logging var.
Etki: Production'da log spam. Security risk (API key preview).
Çözüm: Debug logging'i kaldır. Setting'den alınan API key kullanılmalı.
Dosya: AIResponseNode.php (satır 279-284)
Sorun: AI messages'ı /tmp/ai_messages_debug.txt'ye yazılıyor.
Etki: Production'da /tmp spam. Gizlilik riski.
Çözüm: Debug dosya yazımını kaldır. Log::info() kullan.
Dosya: FlowExecutor.php (satır 57, 88-100)
Sorun: ParallelNodeExecutor var ama aktif değil. Flow'da parallel groups tanımlanmıyor.
Etki: Potansiyel performans artışı kaybediliyor. (ProductSearch + History loading paralel çalışabilir)
Çözüm: Flow JSON'da paralel node grupları tanımla.
Dosya: ProductSearchNode.php, ContextBuilderNode.php
Sorun: Category label eklenmesine rağmen (satır 61-64, ContextBuilder), ürünlerin kategorisi AI'ye açık şekilde söylenmiyor.
Etki: AI, "TRANSPALET" + "FORKLIFT" kategorisinde ürünler mix'lediyse, önerileri optimize edemez.
Çözüm: AI prompt'una kategori context'i ekle. "[TRANSPALET] EPL153 transpalet" gibi.
Dosya: HybridSearchService.php (satır 260-264)
Sorun: Semantic search, farklı kategoriden ürünler getiriyor olabilir. Kategori filtresi SONRADAN uygulanıyor.
Etki: İyi skorlanan ürünler silinebilir. Sonuç sayısı azalabilir.
Çözüm: Kategori filtresi BAŞTAN (Meilisearch AND clause) uygulanmalı, sonradan değil.
Dosya: Tenant2PromptService.php (ALL)
Sorun: Tüm kurallar bir dosyada. Bakım ve test zorlaşıyor.
Etki: Maintenance burden. Tekrar eden kurallar.
Çözüm: Kuralları kategorilere böl:
Dosya: NodeExecutor.php (satır 132-167)
Sorun: ProductSearchNode cache'lenmesi DISABLED (satır 139). "Cache was causing wrong products" yorum var.
Etki: Performans kaybı. HybridSearch çalıştırılıyor her saat.
Çözüm: Cache key'i gözden geçir. user_message + tenant_id + timestamp(hour) olmalı.
Dosya: Tüm Node'lar
Sorun: Hata kontrolü minimal. Exception'lar throw edilmiyor, fallback'e geçiliyor.
Etki: Hata debugging zor. Silent failures.
Çözüm: Try-catch ile proper error handling ekle. User-friendly fallback mesajları sun.
Dosya: AIResponseNode.php (satır 164-178)
Sorun: Streaming konfigürasyonu var (stream: true), ama default false. Streaming logic'i test edilmemiş.
Etki: Real-time responses kullanılmıyor. UX gecikmiş hissediliyor.
Çözüm: Streaming'i test et ve default true yap.
Dosya: AIResponseNode.php (satır 620-633)
Sorun: Eski ürün önerileri "###" ve "**Fiyat:**" aranarak temizleniyor. Yanlış positive olabilir.
Etki: Meşru mesajlar silinebilir.
Çözüm: History'ye metadata flag ekle. "is_product_recommendation: true" gibi.
Dosya: Tenant2PromptService.php (satır 738-756)
Durum: FileLearningService.buildLearningContext() tercih edilen ürünleri AI'ye söylüyor.
Mevcut: System prompt'a ekleniyor (line 742-743)
Suggestion: Bu özelliği genişlet. Daha sophisticated ranking yapılabilir.
Dosya: Tenant2PromptService.php (satır 729)
Durum: AISettingsHelper::buildKnowledgeBasePrompt() sistema ekleniyor.
Potential: FAQ, teknik bilgiler sistem prompt'a eklenebilir.