700 lines
147 KiB
JSON
700 lines
147 KiB
JSON
|
|
{
|
|||
|
|
"name": "My workflow",
|
|||
|
|
"nodes": [
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"httpMethod": "POST",
|
|||
|
|
"path": "c1baae8e-bbc0-42a7-9993-2a0a9b53b23d",
|
|||
|
|
"responseMode": "lastNode",
|
|||
|
|
"responseData": "allEntries",
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.webhook",
|
|||
|
|
"typeVersion": 2,
|
|||
|
|
"position": [
|
|||
|
|
-960,
|
|||
|
|
-120
|
|||
|
|
],
|
|||
|
|
"id": "6ef2dbc6-12bc-4ee3-98c2-60c5b2469df3",
|
|||
|
|
"name": "Webhook",
|
|||
|
|
"webhookId": "562dfd4f-4e0b-4292-9986-2fbd3b8ecdc9"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"jsCode": "const q = $('Webhook').item.json.body.question.toLowerCase();\n\nif (q.includes(\"tahmin\") || q.includes(\"gelecek\") || q.includes(\"trend\")) {\n return [{ json: { type: \"analyze\", question: q } }];\n}\n\nif (q.includes(\"getir\") || q.includes(\"liste\") || q.includes(\"kaç\")) {\n return [{ json: { type: \"query\", question: q } }];\n}\n\nreturn [{ json: { type: \"chat\", question: q } }];"
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.code",
|
|||
|
|
"typeVersion": 2,
|
|||
|
|
"position": [
|
|||
|
|
-360,
|
|||
|
|
-120
|
|||
|
|
],
|
|||
|
|
"id": "18921655-2da0-41db-a0d9-8e5a57421ec6",
|
|||
|
|
"name": "Classify Question"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"rules": {
|
|||
|
|
"values": [
|
|||
|
|
{
|
|||
|
|
"conditions": {
|
|||
|
|
"options": {
|
|||
|
|
"caseSensitive": true,
|
|||
|
|
"leftValue": "",
|
|||
|
|
"typeValidation": "strict",
|
|||
|
|
"version": 2
|
|||
|
|
},
|
|||
|
|
"conditions": [
|
|||
|
|
{
|
|||
|
|
"id": "52c3156d-411d-41c8-8a74-2dd6c0f8c5a1",
|
|||
|
|
"leftValue": "={{ $json.type }}",
|
|||
|
|
"rightValue": "chat",
|
|||
|
|
"operator": {
|
|||
|
|
"type": "string",
|
|||
|
|
"operation": "equals",
|
|||
|
|
"name": "filter.operator.equals"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"combinator": "and"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"conditions": {
|
|||
|
|
"options": {
|
|||
|
|
"caseSensitive": true,
|
|||
|
|
"leftValue": "",
|
|||
|
|
"typeValidation": "strict",
|
|||
|
|
"version": 2
|
|||
|
|
},
|
|||
|
|
"conditions": [
|
|||
|
|
{
|
|||
|
|
"id": "634559bb-99d4-4b88-9b86-1c8bae7b7786",
|
|||
|
|
"leftValue": "={{ $json.type }}",
|
|||
|
|
"rightValue": "query",
|
|||
|
|
"operator": {
|
|||
|
|
"type": "string",
|
|||
|
|
"operation": "equals",
|
|||
|
|
"name": "filter.operator.equals"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"combinator": "and"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"conditions": {
|
|||
|
|
"options": {
|
|||
|
|
"caseSensitive": true,
|
|||
|
|
"leftValue": "",
|
|||
|
|
"typeValidation": "strict",
|
|||
|
|
"version": 2
|
|||
|
|
},
|
|||
|
|
"conditions": [
|
|||
|
|
{
|
|||
|
|
"id": "313e1f25-adca-4257-aa12-3370be1b5352",
|
|||
|
|
"leftValue": "={{ $json.type }}",
|
|||
|
|
"rightValue": "analyze",
|
|||
|
|
"operator": {
|
|||
|
|
"type": "string",
|
|||
|
|
"operation": "equals",
|
|||
|
|
"name": "filter.operator.equals"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"combinator": "and"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.switch",
|
|||
|
|
"typeVersion": 3.2,
|
|||
|
|
"position": [
|
|||
|
|
-180,
|
|||
|
|
-120
|
|||
|
|
],
|
|||
|
|
"id": "98754831-6d55-4c57-9902-dd1e15979e2f",
|
|||
|
|
"name": "Switch"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"operation": "executeQuery",
|
|||
|
|
"query": "{{ $json.output.replace(/```sql\\n?/gi, '').replace(/\\\\n/g, '\\n').replace(/```/g, '').trim() }};"
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.microsoftSql",
|
|||
|
|
"typeVersion": 1.1,
|
|||
|
|
"position": [
|
|||
|
|
540,
|
|||
|
|
-80
|
|||
|
|
],
|
|||
|
|
"id": "f9a67844-98ab-4460-9b06-cd0c8ac10a75",
|
|||
|
|
"name": "SQL Query",
|
|||
|
|
"credentials": {
|
|||
|
|
"microsoftSql": {
|
|||
|
|
"id": "Rxv6hREYQYyXdYAA",
|
|||
|
|
"name": "Microsoft SQL account"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"onError": "continueErrorOutput"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"operation": "executeQuery",
|
|||
|
|
"query": "{{ $json.output.replace(/```sql\\n?/gi, '').replace(/\\\\n/g, '\\n').replace(/```/g, '').trim() }};"
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.microsoftSql",
|
|||
|
|
"typeVersion": 1.1,
|
|||
|
|
"position": [
|
|||
|
|
540,
|
|||
|
|
340
|
|||
|
|
],
|
|||
|
|
"id": "865223bf-7db6-4d10-a0fb-4117094dfcea",
|
|||
|
|
"name": "SQL for Analysis",
|
|||
|
|
"alwaysOutputData": false,
|
|||
|
|
"credentials": {
|
|||
|
|
"microsoftSql": {
|
|||
|
|
"id": "Rxv6hREYQYyXdYAA",
|
|||
|
|
"name": "Microsoft SQL account"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"onError": "continueErrorOutput"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"promptType": "define",
|
|||
|
|
"text": "={{ $('Webhook').item.json.body.question }}",
|
|||
|
|
"options": {
|
|||
|
|
"systemMessage": "Kullanıcı: {{ $json.body.question }}\n\nDoğrudan yanıt ver. Açıklayıcı, öğretici ve samimi ol."
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
|||
|
|
"typeVersion": 1.8,
|
|||
|
|
"position": [
|
|||
|
|
100,
|
|||
|
|
-480
|
|||
|
|
],
|
|||
|
|
"id": "cc3e0476-394e-4ee3-b70b-c313c93ac086",
|
|||
|
|
"name": "AI Chat",
|
|||
|
|
"alwaysOutputData": false,
|
|||
|
|
"onError": "continueErrorOutput"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"jsCode": "const cleanText = (text) =>\n text\n .replace(/\\\\/g, \"\\\\\\\\\") // ters slash\n .replace(/\"/g, '\\\\\"'); // çift tırnak\n\nreturn [\n {\n json: {\n type: \"chat\",\n question: $('Webhook').first().json.body.question,\n sql: null,\n answer: cleanText($input.first().json.output),\n chart: null,\n error: $input.first().json.error || null\n }\n }\n];\n\n"
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.code",
|
|||
|
|
"typeVersion": 2,
|
|||
|
|
"position": [
|
|||
|
|
1080,
|
|||
|
|
-480
|
|||
|
|
],
|
|||
|
|
"id": "cbb0867f-ddfa-4388-8db5-4b7f5fcf9d0f",
|
|||
|
|
"name": "Chat Code",
|
|||
|
|
"alwaysOutputData": true
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"promptType": "define",
|
|||
|
|
"text": "={{ $('Webhook').item.json.body.question }}",
|
|||
|
|
"options": {
|
|||
|
|
"systemMessage": "- Veritabanı Şeması:\n\n1. Tablo: AI_Tanim_Iplik_Listesi\n\nGenel Tanım: \nTekstil üretiminde kullanılan tüm iplik ve iplik bazlı hammaddelerin sistemsel olarak tanımlandığı bir master veri tablosudur. Bu tablo; hammaddeye dair teknik, yapısal, sınıflayıcı ve süreçsel tüm bilgileri merkezi bir yapıda saklar ve üretimden satın almaya kadar birçok sistem modülüyle ilişkilidir.\n\nSütun Tanımları ve Anlamları:\n- IplikKodu: Tanımlı olan hammaddenin sistemsel hammadde kodunu belirtir.\n- RenkAdi: Tanımlı olan hammaddenin renk adını belirtir.\n- RenkKodu: Tanımlı olan hammaddenin sistemde tanımlı renk kodudur.\n- Renk: Tanımlı olan hammaddenin renk numarasını belirtir.\n- Cins: Tanımlı olan hammaddenin cinsini belirtir. Örneğin; polyester, pamuk, viskon vb.\n- Numara: Tanımlı olan hammaddenin numarasını belirtir. Hammaddenin kalınlığını veya inceliğini ifade eder (örneğin: 2 numara iplik, 30/1 Ne vb.).\n- Birim: Tanımlı olan hammaddenin numara birim bilgisini belirtir (örneğin: Nm, NeB, den).\n- Nm: İpliğin numarasını ifade eden metrik sistemdeki (Nm) numarasıdır. Bu değer, 1 gram iplikten kaç metre elde edilebileceğini gösterir. Numara büyüdükçe iplik incelir.\n- KompozisyonKisaltmasi: Hammaddenin kompozisyon yüzdelerinin belirtir. (örneğin; %90 PAN %10 PES, %100 PES, %100 RPET)\n- IplikKisaltmasi: Tanımlı olan hammaddenin sistemsel kısaltılmış hammadde kodunu belirtir.\n- UstGrup1: Hammaddenin bulunduğu ana grubu ifade eder.\n- UstGrup2: Hammaddenin ait olduğu ana grubun bir alt grubudur.\n- Tarih: Hammadde tanımlamasının yapıldığı tarihtir.\n- InsertUser: Hammadde tanımlamasını yapan kullanıcıyı belirtir.\n- IsikHasligi: Hammaddenin ışığa karşı dayanıklılık seviyesini (haslık derecesi) belirtir.\n- Bukum: Hammaddenin büküm şekli hakkında bilgi verir (örneğin: S, Z, çift büküm).\n- OrtBobinKg: Ortalama bir bobin hammaddenin kilogram cinsinden ağırlığını belirtir.\n- NumuneKodu: Hammadde tanımlamasından önce numune olarak tanımlandığındaki iplik numune kodunu belirtir.\n- NumuneOnayTarihi: Hammadde numunesinin onaylandığı tarihi belirtir. Numune onaylandıktan sonra regüle iplik tanımlanır.\n- UrunHizmetGrubu: Hammadde tanımının hizmet grubunu belirtir. Örneğin: iplik, kumaş, aksesuar vb.\n- HamMamul: Hammaddenin üretim aşamasını ifade eder. (YARI MAMÜL İPLİK, MAMÜL İPLİK, HAM İPLİK)\n- IplikKullanimDurumu: Hammadde tanımının mevcut durumunu belirtir (örneğin: Aktif, Pasif).\n- HammaddeTipi: Tanımlı olan hammaddenin tipini belirtir. (CİPS, İPLİK, ELYAF, JOKER İPLİK, POLİP BOYA)\n\nFonksiyonel Amaçlar ve İlişkiler\n- Bu tablo, üretim emirlerinde hammadde seçimi, satın alma planlaması ve depo kontrol gibi birçok süreçle ilişkilidir.\n- IplikKodu anahtar alan olarak diğer tablolarla (örneğin AI_Iplik_SatinalmaSiparis_Durum) join ilişkisinde kullanılır.\n- KompozisyonKisaltmasi, kalite hesaplamaları, üretim reçeteleri ve stok analizlerinde kullanılır.\n- NumuneOnayTarihi, numuneden regüleye geçişin kritik eşiğidir.\n\n2. Tablo: AI_Tanim_Kalite_Listesi\n\nGenel Tanım: \nAI_Tanim_Kalite_Listesi, firmanın ürün gamında yer alan kumaş kalitelerinin detaylı tanımlarını içeren referans tablosudur. Bu tablo, kumaşların üretimsel, teknik ve ticari sınıflandırmalarının yapıldığı üst seviye bilgi kaynağıdır. Kalite; çözgü/atkı özellikleri, iplik tipi, ambalaj biçimi, uygulanan proses ve kullanım cinsine kadar birçok parametre ile tanımlanır ve tüm üretim & stok yönetimi süreçlerinin çekirdek bileşeni olarak kullanılır.\n\nSütun Tanımları ve Anlamları:\n- KaliteKodu: Kumaş kalitesini ifade eden akıllı kodlama yapısı ile belirtilmiş benzersiz bir tanımlama koddur. \n- KaliteAdi: Kumaşın kaliteye verilmiş ticari veya teknik adını belirtir. Kullanıcıya daha anlaşılır bir kalite tanımı sunar.\n- AsilKaliteAdi: Kalitenin bağlı olduğu bir üst kalite
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
|||
|
|
"typeVersion": 1.8,
|
|||
|
|
"position": [
|
|||
|
|
100,
|
|||
|
|
-120
|
|||
|
|
],
|
|||
|
|
"id": "0f14a81e-5f75-4093-ab93-a24a3315ebda",
|
|||
|
|
"name": "AI Query"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"modelName": "models/gemini-2.0-flash",
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
|
|||
|
|
"typeVersion": 1,
|
|||
|
|
"position": [
|
|||
|
|
80,
|
|||
|
|
40
|
|||
|
|
],
|
|||
|
|
"id": "3b370555-d453-4eaf-8cf7-c04722350774",
|
|||
|
|
"name": "Google Gemini Chat Model2",
|
|||
|
|
"credentials": {
|
|||
|
|
"googlePalmApi": {
|
|||
|
|
"id": "g7Ev8dkuHaLU7JbG",
|
|||
|
|
"name": "Google Gemini(PaLM) Api account"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.memoryManager",
|
|||
|
|
"typeVersion": 1.1,
|
|||
|
|
"position": [
|
|||
|
|
-760,
|
|||
|
|
-120
|
|||
|
|
],
|
|||
|
|
"id": "edbd4960-3186-4cfa-afe0-ddd56bdfcbe5",
|
|||
|
|
"name": "Chat Memory Manager"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"sessionIdType": "customKey",
|
|||
|
|
"sessionKey": "={{ $('Webhook').item.json.body.sessionId }}",
|
|||
|
|
"contextWindowLength": 100
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
|
|||
|
|
"typeVersion": 1.3,
|
|||
|
|
"position": [
|
|||
|
|
-700,
|
|||
|
|
340
|
|||
|
|
],
|
|||
|
|
"id": "72d1f63a-4385-4892-a37c-396b07a7e40c",
|
|||
|
|
"name": "Simple Memory"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"modelName": "models/gemini-2.0-flash",
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
|
|||
|
|
"typeVersion": 1,
|
|||
|
|
"position": [
|
|||
|
|
100,
|
|||
|
|
480
|
|||
|
|
],
|
|||
|
|
"id": "922eb62e-090d-4bee-80e4-a6c82a155922",
|
|||
|
|
"name": "Google Gemini Chat Model4",
|
|||
|
|
"credentials": {
|
|||
|
|
"googlePalmApi": {
|
|||
|
|
"id": "g7Ev8dkuHaLU7JbG",
|
|||
|
|
"name": "Google Gemini(PaLM) Api account"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"promptType": "define",
|
|||
|
|
"text": "={{ $('Webhook').item.json.body.question }}",
|
|||
|
|
"options": {
|
|||
|
|
"systemMessage": "Senin görevin, kullanıcıdan gelen soruları yalnızca Microsoft SQL Server 2012 için çalıştırılabilir aşağıdaki örneğe ve verilen Veritabanı Şemasına göre SQL sorguları üretmektir. Bu SQL sorgunun verileri çekerek bir ön hazırlık yapacak. Bu ön hazırlık sorgusunda Yıl, Ay, Tarih ve Miktar sütunları yer almalıdır. SQL sorgularının yalnızca gerekli veriyi döndürmesi gerekmektedir. Sorguların ilk satırında `SET DATEFORMAT 'DMY';` ifadesi olmalıdır.\n\nKurallar:\n1. Sadece saf SQL sorgusu döndür. Sql sorgusuyla birlikte açıklama yapma.\n2. Microsoft SQL Server 2012 için çalıştırılabilir düz SQL sorguları üretmektir\n3. Kullanıcının sorduğu soruya göre doğru tabloyu ve sütunları seçmelisin. Sadece verilen Veritabanı şeması ve tabloları kullanarak SQL sorguları üret.\n4. Sorgularında `SELECT *` kullanma. Sadece gerekli sütunları belirt. \n5. `BETWEEN` kullanarak tarih aralığı belirt. Eğer bir tarih aralığı varsa, kullanıcının sorgusuna göre bu aralığı filtrele.\n6. Sadece veri sağlayacak SQL sorgularını döndür. Kullanıcının sorusuna göre veri toplamak için uygun sorguyu oluştur.\n7. Kullanıcının sorduğu sorunun içeriğine göre:\n - **Yıl**, **Ay**, **Tarih**, ve **Miktar** gibi bilgileri döndürebileceğin sorguları oluştur.\n8. SQL sorguları yalnızca veri sağlayacak şekilde olmalıdır. Kullanıcıya analiz veya yorum yapma, sadece veri sağlayacak SQL sorgusunu döndür.\n\nÖrnek olarak, \"Son 3 aydaki kumaş siparişlerine göre, ne kadar artış bekleniyor?\" sorusu şu şekilde bir sorguya dönüşebilir:\n\nSET DATEFORMAT 'DMY'; \nSELECT \n YEAR(SipTarihi) AS Yil, \n DATEPART(MONTH, SipTarihi) AS Ay, \n MIN(SipTarihi) AS Tarih, \n SUM(SipMiktar) AS Miktar \nFROM AI_Kumas_Siparis_Listesi \nWHERE SipTarihi BETWEEN '01-01-2025' AND '31-03-2025' \nGROUP BY YEAR(SipTarihi), DATEPART(MONTH, SipTarihi);\n\nSadece SQL sorgusunu döndür. Açıklama veya yorum ekleme.\n\nVeritabanı şeması:\n\n1. Tablo: AI_Tanim_Iplik_Listesi\n\nGenel Tanım: \nTekstil üretiminde kullanılan tüm iplik ve iplik bazlı hammaddelerin sistemsel olarak tanımlandığı bir master veri tablosudur. Bu tablo; hammaddeye dair teknik, yapısal, sınıflayıcı ve süreçsel tüm bilgileri merkezi bir yapıda saklar ve üretimden satın almaya kadar birçok sistem modülüyle ilişkilidir.\n\nSütun Tanımları ve Anlamları:\n- IplikKodu: Tanımlı olan hammaddenin sistemsel hammadde kodunu belirtir.\n- RenkAdi: Tanımlı olan hammaddenin renk adını belirtir.\n- RenkKodu: Tanımlı olan hammaddenin sistemde tanımlı renk kodudur.\n- Renk: Tanımlı olan hammaddenin renk numarasını belirtir.\n- Cins: Tanımlı olan hammaddenin cinsini belirtir. Örneğin; polyester, pamuk, viskon vb.\n- Numara: Tanımlı olan hammaddenin numarasını belirtir. Hammaddenin kalınlığını veya inceliğini ifade eder (örneğin: 2 numara iplik, 30/1 Ne vb.).\n- Birim: Tanımlı olan hammaddenin numara birim bilgisini belirtir (örneğin: Nm, NeB, den).\n- Nm: İpliğin numarasını ifade eden metrik sistemdeki (Nm) numarasıdır. Bu değer, 1 gram iplikten kaç metre elde edilebileceğini gösterir. Numara büyüdükçe iplik incelir.\n- KompozisyonKisaltmasi: Hammaddenin kompozisyon yüzdelerinin belirtir. (örneğin; %90 PAN %10 PES, %100 PES, %100 RPET)\n- IplikKisaltmasi: Tanımlı olan hammaddenin sistemsel kısaltılmış hammadde kodunu belirtir.\n- UstGrup1: Hammaddenin bulunduğu ana grubu ifade eder.\n- UstGrup2: Hammaddenin ait olduğu ana grubun bir alt grubudur.\n- Tarih: Hammadde tanımlamasının yapıldığı tarihtir.\n- InsertUser: Hammadde tanımlamasını yapan kullanıcıyı belirtir.\n- IsikHasligi: Hammaddenin ışığa karşı dayanıklılık seviyesini (haslık derecesi) belirtir.\n- Bukum: Hammaddenin büküm şekli hakkında bilgi verir (örneğin: S, Z, çift büküm).\n- OrtBobinKg: Ortalama bir bobin hammaddenin kilogram cinsinden ağırlığını belirtir.\n- NumuneKodu: Hammadde
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
|||
|
|
"typeVersion": 1.8,
|
|||
|
|
"position": [
|
|||
|
|
100,
|
|||
|
|
240
|
|||
|
|
],
|
|||
|
|
"id": "eaacf812-45d5-462d-85b5-07350499e2ca",
|
|||
|
|
"name": "AI Analyze"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"assignments": {
|
|||
|
|
"assignments": [
|
|||
|
|
{
|
|||
|
|
"id": "1e77d4b5-3b7e-4b3a-bf74-6e5c4280d6a8",
|
|||
|
|
"name": "question",
|
|||
|
|
"value": "={{ $('Classify Question').item.json.question }}",
|
|||
|
|
"type": "string"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"id": "f2d77abe-c3ef-4e23-972d-403c279883bb",
|
|||
|
|
"name": "sql",
|
|||
|
|
"value": "={{ $json.output }}",
|
|||
|
|
"type": "string"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.set",
|
|||
|
|
"typeVersion": 3.4,
|
|||
|
|
"position": [
|
|||
|
|
540,
|
|||
|
|
100
|
|||
|
|
],
|
|||
|
|
"id": "7ca4cce9-7e7f-4721-a601-570a96a7b80f",
|
|||
|
|
"name": "Edit Fields",
|
|||
|
|
"alwaysOutputData": false
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"mode": "combine",
|
|||
|
|
"combineBy": "combineAll",
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.merge",
|
|||
|
|
"typeVersion": 3.1,
|
|||
|
|
"position": [
|
|||
|
|
820,
|
|||
|
|
180
|
|||
|
|
],
|
|||
|
|
"id": "4eb583f4-bcae-401f-9386-425be6d48b68",
|
|||
|
|
"name": "Merge",
|
|||
|
|
"alwaysOutputData": true,
|
|||
|
|
"onError": "continueRegularOutput"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"modelName": "models/gemini-2.0-flash",
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
|
|||
|
|
"typeVersion": 1,
|
|||
|
|
"position": [
|
|||
|
|
100,
|
|||
|
|
-260
|
|||
|
|
],
|
|||
|
|
"id": "0cddf53c-45c8-4bbb-89e2-41f08ed25999",
|
|||
|
|
"name": "Google Gemini Chat Model1",
|
|||
|
|
"credentials": {
|
|||
|
|
"googlePalmApi": {
|
|||
|
|
"id": "g7Ev8dkuHaLU7JbG",
|
|||
|
|
"name": "Google Gemini(PaLM) Api account"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"assignments": {
|
|||
|
|
"assignments": [
|
|||
|
|
{
|
|||
|
|
"id": "8d7c497c-932d-4b0a-83e3-d38c45ae401a",
|
|||
|
|
"name": "=question",
|
|||
|
|
"value": "={{ $('Classify Question').item.json.question }}",
|
|||
|
|
"type": "string"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"id": "321034f1-d234-400f-afb3-b97f75f7f2d0",
|
|||
|
|
"name": "sql",
|
|||
|
|
"value": "={{ $json.output }}",
|
|||
|
|
"type": "string"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.set",
|
|||
|
|
"typeVersion": 3.4,
|
|||
|
|
"position": [
|
|||
|
|
540,
|
|||
|
|
-280
|
|||
|
|
],
|
|||
|
|
"id": "52dced17-5ddc-42e0-ba92-20d98a6c7332",
|
|||
|
|
"name": "Edit Fields1"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"mode": "combine",
|
|||
|
|
"combineBy": "combineAll",
|
|||
|
|
"options": {}
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-base.merge",
|
|||
|
|
"typeVersion": 3.1,
|
|||
|
|
"position": [
|
|||
|
|
820,
|
|||
|
|
-180
|
|||
|
|
],
|
|||
|
|
"id": "cee77a75-4c15-4a99-9f45-b4169e14ab8c",
|
|||
|
|
"name": "Merge1",
|
|||
|
|
"alwaysOutputData": true
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"functionCode": "import matplotlib.pyplot as plt\nimport io\nimport base64\nimport json\n\n# items listesindeki verilere ulaşırken hata kontrolü ekleyelim\nif len(items) > 0:\n question = items[0].get('question', 'Soru sağlanmadı') # Webhook'tan gelen soru\n sql = items[0].get('sql', 'SQL Sorgusu sağlanmadı') # AI Query'den gelen SQL sorgusu\nelse:\n question = \"Soru sağlanmadı\"\n sql = \"SQL Sorgusu sağlanmadı\"\n\n# SQL Query node'undan alınan sonuçlar\nresultItems = [\n {key: item[key] for key in item if key not in [\"question\", \"sql\"]}\n for item in items\n]\n\n# Dinamik sütun isimlerini almak için ilk öğeyi kullanıyoruz\nif resultItems and isinstance(resultItems[0], dict):\n columns = list(resultItems[0].keys()) # İlk öğedeki tüm sütunları alıyoruz\n\n # Dinamik olarak etiket ve veri sütunlarını belirliyoruz\n labels_column = None\n data_column = None\n\n # Etiket sütunu genellikle metin türünde (string) olacak, veri sütunu ise sayısal türde (int, float) olacak\n for col in columns:\n # Etiket sütunu olarak metin (string) türünde olan sütunu seçiyoruz\n if isinstance(resultItems[0].get(col), str):\n labels_column = col\n\n # Veri sütunu olarak sayısal (int veya float) türünde olan sütunu seçiyoruz\n elif isinstance(resultItems[0].get(col), (int, float)):\n data_column = col\n\n # Etiket ve veri sütunları bulunursa, verileri çekiyoruz\n labels = [item.get(labels_column, \"Bilinmeyen\") for item in resultItems if item.get(labels_column) is not None]\n data = [item.get(data_column, 0) for item in resultItems if item.get(data_column) is not None]\n\nelse:\n labels, data = [], [] # Eğer veri boşsa, etiketsiz ve veri içermeyen bir liste döneriz\n\n# **Önemli**: labels ve data uzunluklarını kontrol etme\nif len(labels) != len(data):\n print(f\"Veri uyumsuzluğu: labels uzunluğu: {len(labels)}, data uzunluğu: {len(data)}\")\n # Aynı uzunluktaki verilere göre filtreleme yapabilirsiniz\n min_length = min(len(labels), len(data))\n labels = labels[:min_length]\n data = data[:min_length]\n\n# Eğer etiketsiz veya veri boşsa, görsel oluşturma\nif not labels or not data:\n print(\"Etiketler veya veri listesi boş. Grafik oluşturulamaz.\")\n base64_image = None\nelse:\n # Grafik oluşturucu fonksiyonu\n def generate_base64_image(labels, data):\n # Grafik boyutunu ve başlıkları ayarlama\n fig, ax = plt.subplots(figsize=(10, 6)) # Grafik boyutunu ayarlama\n bars = ax.bar(labels, data, width=0.6) # Bar grafiği çizme\n\n # Etiketleri döndürme ve sıkışıklığı engelleme\n plt.xticks(rotation=45, ha='right')\n plt.tight_layout()\n\n # Verileri çubukların üstüne yerleştirme (değerlerin büyük olmasını engellemek için formatlama)\n for bar in bars:\n height = bar.get_height() # Her çubuğun yüksekliği\n # Burada sayıları doğru bir formatta gösteriyoruz\n formatted_height = f\"{height:,.0f}\" # Sayıyı binlik ayraçlarla biçimlendiriyoruz\n ax.text(bar.get_x() + bar.get_width() / 2, height, formatted_height, \n ha='center', va='bottom', fontsize=10, color='black')\n\n # Base64 olarak görseli kaydetme\n buf = io.BytesIO()\n plt.savefig(buf, format='png', dpi=72) # Görseli base64'e dönüştürmek için\n buf.seek(0)\n base64_image = base64.b64encode(buf.read()).decode('utf-8')\n buf.close()\n plt.close()\n\n return base64_image\n\n # Grafik görselini base64 formatında almak\n base64_image = generate_base64_image(labels, data)\n\n# Sonuçları döndür\nreturn [{\n \"type\": \"query\",\n \"question\": question,\n \"sql\": sql,\n \"answer\": resultItems,\n \"chart\": base64_image, # Grafik base64 formatında dönüyor\n}]\n"
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-python.pythonFunction",
|
|||
|
|
"typeVersion": 1,
|
|||
|
|
"position": [
|
|||
|
|
1080,
|
|||
|
|
-180
|
|||
|
|
],
|
|||
|
|
"id": "06cfbb12-7644-4380-bbf1-a4ca93ca1333",
|
|||
|
|
"name": "PythonFunction"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"parameters": {
|
|||
|
|
"functionCode": "import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport base64\nimport io\nfrom sklearn.linear_model import LinearRegression, Ridge, ElasticNet\n\n# 1. Veriyi hazırla\ndf = pd.DataFrame(items)\n\n# Verinin yeterli olup olmadığını kontrol et\nif len(df) < 3:\n return [{\"type\": \"analyze\", \"answer\": f\"⚠️ En az 3 aylık veri gerekir. Şu an sadece {len(df)} satır var.\"}]\n\ndf[\"ds\"] = pd.to_datetime(df['Tarih'], errors='coerce')\ndf[\"y\"] = pd.to_numeric(df[\"Miktar\"], errors='coerce')\n\nX = np.arange(len(df)).reshape(-1, 1) # Zaman indeksi\ny = df[\"y\"]\nnext_x = np.array([[len(y)]]) # Bir sonraki zaman dilimi (bir ay sonrası)\nnext_date = df[\"ds\"].iloc[-1] + pd.DateOffset(months=1) # Sonraki ay\n\n# 2. Modeller\nmodels = {\n \"Linear\": LinearRegression(),\n \"Ridge\": Ridge(),\n \"ElasticNet\": ElasticNet()\n}\n\nresults = {}\n\n# Modelleri eğit ve tahmin yap\nfor name, model in models.items():\n try:\n model.fit(X, y)\n results[name] = round(model.predict(next_x)[0], 2)\n except:\n results[name] = \"Error\"\n\n# 3. Grafik çizimi\nplt.figure(figsize=(10, 5))\n\n# Gerçek veri çizgisi\nplt.plot(df[\"ds\"], df[\"y\"], label=\"Gerçek Veri\", color=\"blue\", linewidth=2)\n\n# Gerçek veri noktalarına değer yaz\nfor x, y_val in zip(df[\"ds\"], df[\"y\"]):\n plt.text(x, y_val, str(round(y_val)), color='blue', fontsize=8, ha='center', va='bottom')\n\n# Tahmin noktaları\ncolors = {\"Linear\": \"orange\", \"Ridge\": \"green\", \"ElasticNet\": \"purple\"}\nfor name, val in results.items():\n if isinstance(val, (int, float)):\n plt.scatter(\n next_date, val,\n color=colors[name],\n label=f\"{name}: {val}\",\n s=100,\n edgecolors='black',\n zorder=5\n )\n\n# 📅 Tüm tarihleri x-axis’e manuel olarak yaz\nplt.xticks(df[\"ds\"].tolist() + [next_date], rotation=90)\n\n# Grafik başlık ve etiketler\nplt.title(\"Tahmin\")\nplt.xlabel(\"Tarih\")\nplt.ylabel(\"Miktar\")\nplt.legend()\nplt.grid(True)\nplt.tight_layout()\n\n# Grafik resmini base64 formatında kaydet\nbuf = io.BytesIO()\nplt.savefig(buf, format=\"png\", dpi=72) # düşük çözünürlük = daha hızlı\nbuf.seek(0)\nimage_base64 = base64.b64encode(buf.read()).decode(\"utf-8\")\nbuf.close()\nplt.close()\n\n# 4. Açıklama ve sonuçları döndürme\ntext = \"\\n\".join([f\"- 🧠 **{k}:** {v}\" for k, v in results.items()])\n\n# Sonuçları döndür\nreturn [{\n \"type\": \"analyze\",\n \"question\": items[0][\"question\"],\n \"sql\": items[0][\"sql\"],\n \"answer\": f\"📅 **{next_date.date()}** için tahmin sonucu:\\n\\n{text}\",\n \"chart\": image_base64\n}]"
|
|||
|
|
},
|
|||
|
|
"type": "n8n-nodes-python.pythonFunction",
|
|||
|
|
"typeVersion": 1,
|
|||
|
|
"position": [
|
|||
|
|
1080,
|
|||
|
|
180
|
|||
|
|
],
|
|||
|
|
"id": "b9c551d0-5011-492a-9ae1-9a585b059073",
|
|||
|
|
"name": "Analyze Python"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"pinData": {},
|
|||
|
|
"connections": {
|
|||
|
|
"Webhook": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Chat Memory Manager",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Classify Question": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Switch",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Switch": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Chat",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Query",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Analyze",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"SQL for Analysis": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Merge",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 1
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Merge",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 1
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"SQL Query": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Merge1",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 1
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Merge1",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 1
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"AI Chat": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Chat Code",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Chat Code",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Google Gemini Chat Model2": {
|
|||
|
|
"ai_languageModel": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Query",
|
|||
|
|
"type": "ai_languageModel",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"AI Query": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "SQL Query",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"node": "Edit Fields1",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Chat Memory Manager": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Classify Question",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Simple Memory": {
|
|||
|
|
"ai_memory": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Chat",
|
|||
|
|
"type": "ai_memory",
|
|||
|
|
"index": 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"node": "AI Query",
|
|||
|
|
"type": "ai_memory",
|
|||
|
|
"index": 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"node": "AI Analyze",
|
|||
|
|
"type": "ai_memory",
|
|||
|
|
"index": 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"node": "Chat Memory Manager",
|
|||
|
|
"type": "ai_memory",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Google Gemini Chat Model4": {
|
|||
|
|
"ai_languageModel": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Analyze",
|
|||
|
|
"type": "ai_languageModel",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"AI Analyze": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "SQL for Analysis",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"node": "Edit Fields",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Edit Fields": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Merge",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Merge": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Analyze Python",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Google Gemini Chat Model1": {
|
|||
|
|
"ai_languageModel": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "AI Chat",
|
|||
|
|
"type": "ai_languageModel",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Edit Fields1": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "Merge1",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"Merge1": {
|
|||
|
|
"main": [
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"node": "PythonFunction",
|
|||
|
|
"type": "main",
|
|||
|
|
"index": 0
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
[]
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"active": true,
|
|||
|
|
"settings": {
|
|||
|
|
"executionOrder": "v1"
|
|||
|
|
},
|
|||
|
|
"versionId": "8231e31d-59e4-488a-b55f-b7b23209223d",
|
|||
|
|
"meta": {
|
|||
|
|
"templateCredsSetupCompleted": true,
|
|||
|
|
"instanceId": "98a3b71e44c71f7839b97fa3055c6c36b0c5f88cbb523bd18d164bd856e39632"
|
|||
|
|
},
|
|||
|
|
"id": "tE4cQf3OM4dSmJiY",
|
|||
|
|
"tags": []
|
|||
|
|
}
|