diff --git a/server/ai.mjs b/server/ai.mjs index db194d6..f706d1f 100644 --- a/server/ai.mjs +++ b/server/ai.mjs @@ -314,8 +314,13 @@ function kesikJsonOnar(s) { /** Zinciri sırayla dener; ilk başarılı sonucu döndürür. */ export async function analyzeSpec({ text, fileName, tender, chain, systemOverride, mode }) { const derin = mode === 'derin'; - const order = (Array.isArray(chain) && chain.length ? chain : ['glmflash', 'gemini', 'deepseek', 'grok', 'gpt', 'claude']) + // Ücretli yedek: Gemini Flash her zaman zincirin sonunda. Panelde seçilen + // modeller (ör. ücretsiz/limitli olanlar) tıkanınca analiz boş kalmasın; + // yalnız üsttekilerin hepsi başarısız olursa devreye girer. + const YEDEK = 'gemini'; + const secim = (Array.isArray(chain) && chain.length ? chain : ['glmflash', 'gemini', 'deepseek', 'grok', 'gpt', 'claude']) .filter((id) => PROVIDERS[id]); + const order = secim.includes(YEDEK) ? secim : [...secim, YEDEK]; // Derin analiz hem daha çok metin okur hem daha uzun JSON üretir; çıktı // kesilirse JSON parse edilemez ve zincir boşuna tüketilir. const userPrompt = buildUserPrompt({ text, fileName, tender, limit: derin ? 90000 : 60000 }); diff --git a/src/components/KullanimKilavuzu.jsx b/src/components/KullanimKilavuzu.jsx index 985d112..4de61ee 100644 --- a/src/components/KullanimKilavuzu.jsx +++ b/src/components/KullanimKilavuzu.jsx @@ -58,7 +58,7 @@ const KILAVUZ = { api_webhooks: { baslik: 'API & Webhooks', ne: 'Kendi sistemlerinize ihale akışı.', adimlar: [ 'MCP: bir API anahtarı üretin, karttaki Claude Code komutunu veya mcp.json\'u kopyalayıp anahtarı yerine yazın; asistanınız search_tenders, get_tender, search_results, search_items, upcoming_deadlines araçlarını kullanır.', 'RSS: /api/feeds/tenders.rss?key=… adresini (il, sektor, q filtreleri) Feedly / Outlook / Slack RSS\'e ekleyin; sonuç ilanları için /api/feeds/sonuc.rss anahtarsızdır.','API anahtarı üretin; webhook adresinize yeni ihaleler gönderilir.'], ipuclari: [] }, - ai_ayarlari: { baslik: 'AI Model Ayarları', ne: 'Analizlerde kullanılacak model zinciri (yedekli).', adimlar: ['Sırayı sürükleyerek değiştirin; ilk başarılı model sonucu döner.'], ipuclari: [] }, + ai_ayarlari: { baslik: 'AI Model Ayarları', ne: 'Analizlerde kullanılacak model zinciri (yedekli).', adimlar: ['Sırayı sürükleyerek değiştirin; ilk başarılı model sonucu döner.', 'Gemini Flash ücretli yedek olarak zincirin sonunda her zaman denenir; seçtiğiniz modeller (ör. limitli/ücretsiz olanlar) tıkanınca analiz boş kalmaz.'], ipuclari: [] }, pwa_settings: { baslik: 'Mobil PWA & Bildirimler', ne: 'Uygulamayı telefona kurma, e-posta ve Telegram bildirimleri.', diff --git a/src/components/tools/AiModelSettings.jsx b/src/components/tools/AiModelSettings.jsx index ebdac96..cffab28 100644 --- a/src/components/tools/AiModelSettings.jsx +++ b/src/components/tools/AiModelSettings.jsx @@ -113,7 +113,7 @@ export const AiModelSettings = () => {
Birincil model yanıt vermezse sıradaki yedeğe otomatik geçilir.
+Birincil model yanıt vermezse sıradaki yedeğe otomatik geçilir. Zincirde olmasa bile Gemini Flash ücretli yedek olarak her zaman en sonda denenir; yalnız üsttekilerin hepsi başarısız olursa devreye girer.