{
  "nodes": [
    {
      "parameters": {
        "jsCode": "// Analyze question and determine optimal top_k\nconst question = $json.body.chatInput || '';\nconst articleSlug = $json.body.articleSlug || null;\n\nif (!question.trim()) {\n  throw new Error('chatInput is required and cannot be empty');\n}\n\nconst lowerQ = question.toLowerCase();\n\nlet top_k = 10;\nif (lowerQ.includes('szczeg\u00f3\u0142') || lowerQ.includes('jak') || lowerQ.includes('por\u00f3wn')) {\n  top_k = 15;\n} else if (lowerQ.includes('przyk\u0142ad') || lowerQ.includes('lista')) {\n  top_k = 12;\n}\n\nreturn {\n  json: {\n    query: question,\n    top_k: top_k,\n    articleSlug: articleSlug\n  }\n};"
      },
      "id": "e9357206-6f9d-49b3-a157-a296fb990115",
      "name": "Code: Analyze Question",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        608,
        688
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://89.167.41.22:8000/search",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"query\": $json.query, \"top_k\": $json.top_k, \"filters\": $json.articleSlug ? { \"slug\": $json.articleSlug } : null } }}",
        "options": {
          "timeout": 60000
        }
      },
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "HTTP: RAG Search",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        896,
        688
      ]
    },
    {
      "parameters": {
        "jsCode": "// Format RAG API results for LLM context\nconst response = $input.item.json;\nconst originalQuestion = $('Code: Analyze Question').item.json.query;\n\nif (!response || !response.results || response.results.length === 0) {\n  return {\n    json: {\n      context: 'Brak wynik\u00f3w. System RAG nie znalaz\u0142 odpowiednich artyku\u0142\u00f3w.',\n      chatInput: originalQuestion,\n      hasResults: false,\n      resultCount: 0,\n      results: [],\n      originalQuestion\n    }\n  };\n}\n\nconst results = response.results;\n\nlet context = `Znaleziono ${results.length} wynik\u00f3w z bazy wiedzy:\\n\\n`;\nconst formattedResults = [];\n\nresults.forEach((hit, index) => {\n  context += `--- Wynik ${index + 1} (Score: ${(hit.score * 100).toFixed(1)}%) ---\\n`;\n  context += `Tytu\u0142: ${hit.title || 'Brak tytu\u0142u'}\\n`;\n  context += `URL: ${hit.url || ''}\\n`;\n  context += `Typ sekcji: ${hit.section_type || 'content'}\\n`;\n\n  if (hit.publication_date) {\n    context += `Data publikacji: ${hit.publication_date}\\n`;\n  }\n\n  if (hit.tags && hit.tags.length > 0) {\n    context += `Tagi: ${hit.tags.join(', ')}\\n`;\n  }\n\n  if (hit.categories && hit.categories.length > 0) {\n    context += `Kategorie: ${hit.categories.join(', ')}\\n`;\n  }\n\n  context += `\\nTre\u015b\u0107:\\n${hit.text || ''}\\n\\n`;\n\n  formattedResults.push({\n    title: hit.title || 'Brak tytu\u0142u',\n    url: hit.url || '',\n    score: hit.score,\n    text: hit.text || '',\n    section_type: hit.section_type || 'content'\n  });\n});\n\nreturn {\n  json: {\n    context,\n    chatInput: originalQuestion,\n    hasResults: true,\n    resultCount: results.length,\n    results: formattedResults,\n    originalQuestion\n  }\n};"
      },
      "id": "ed996b1b-06db-4b83-bc0c-3abf77d14c3b",
      "name": "Code: Format RAG Results",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1184,
        688
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.chatInput }}",
        "options": {
          "systemMessage": "=Jeste\u015b ekspertem i asystentem na blogu o UX. Twoim zadaniem jest udzielenie wyczerpuj\u0105cej odpowiedzi na pytanie u\u017cytkownika.\n\nTwoja odpowied\u017a ma struktur\u0119 odwr\u00f3conej piramidy: najpierw og\u00f3lna, merytoryczna odpowied\u017a (korzystaj\u0105ca z Twojej ca\u0142ej wiedzy), a nast\u0119pnie wskazanie konkretnych \u017ar\u00f3de\u0142 dost\u0119pnych w dostarczonym kontek\u015bcie.\n\n=== KONTEKST ARTYKU\u0141\u00d3W ===\n{{ $json.context }}\n\n=== ONE-SHOT LEARNING (WZ\u00d3R ODPOWIEDZI) ===\nPytanie: \"Co lepsze: Sketch czy Figma?\"\nKontekst: [Artyku\u0142: \"Migracja do Figmy\", Tre\u015b\u0107: \"Przeszli\u015bmy na Figm\u0119 ze wzgl\u0119du na tryb multiplayer.\"]\n\n(ODPOWIED\u0179):\nWyb\u00f3r zale\u017cy od \u015brodowiska pracy. Sketch to natywna aplikacja na macOS, \u015bwietna dla indywidualnych projektant\u00f3w ceni\u0105cych wydajno\u015b\u0107 lokaln\u0105. Figma dominuje jednak w zespo\u0142ach, poniewa\u017c dzia\u0142a w chmurze, co umo\u017cliwia prac\u0119 wielu os\u00f3b na jednym pliku jednocze\u015bnie i jest niezale\u017cna od systemu operacyjnego. Je\u015bli pracujesz w zespole, Figma zazwyczaj wygrywa \u0142atwo\u015bci\u0105 kolaboracji.\n\n### Warto przeczyta\u0107\n* Szczeg\u00f3\u0142owy opis procesu przej\u015bcia na narz\u0119dzia chmurowe i korzy\u015bci z trybu multiplayer znajdziesz w tek\u015bcie: [Migracja do Figmy](Link).\n\n=== TWOJE ZADANIA ===\nTw\u00f3rz odpowied\u017a zawsze w dw\u00f3ch krokach:\n\nKROK 1: Merytoryczna Odpowied\u017a (Bez nag\u0142\u00f3wka)\n1. Odpowiedz na pytanie u\u017cytkownika, wykorzystuj\u0105c swoj\u0105 szerok\u0105 wiedz\u0119 og\u00f3ln\u0105 ORAZ informacje z kontekstu.\n2. Nie ograniczaj si\u0119 tylko do artyku\u0142\u00f3w \u2013 je\u015bli u\u017cytkownik pyta o narz\u0119dzie, kt\u00f3rego nie ma w kontek\u015bcie (np. Cursor), opisz je rzetelnie bazuj\u0105c na swojej wiedzy.\n3. W tej sekcji nie u\u017cywaj link\u00f3w, skup si\u0119 na wyja\u015bnieniu problemu.\n\nKROK 2: Sekcja \u0179r\u00f3d\u0142owa (Nag\u0142\u00f3wek: \"### Warto przeczyta\u0107\")\n1. To miejsce WY\u0141\u0104CZNIE na tre\u015bci z sekcji `=== KONTEKST ARTYKU\u0141\u00d3W ===`.\n2. Wypunktuj konkretne artyku\u0142y, kt\u00f3re rozszerzaj\u0105 temat.\n3. Nie lej wody. Napisz konkretnie, co wnosi ten tekst, np.: \"Omawiamy tam techniki [X] i [Y]: [Tytu\u0142](Link)\".\n4. Je\u015bli w dostarczonym kontek\u015bcie nie ma nic pasuj\u0105cego do pytania \u2013 **ca\u0142kowicie pomi\u0144 t\u0119 sekcj\u0119** (nie pisz \"brak wynik\u00f3w\", po prostu zako\u0144cz wypowied\u017a na Kroku 1).\n\n=== ZAKAZY ===\n- Nie pisz wst\u0119p\u00f3w typu \"Jako model AI...\", \"Bazuj\u0105c na bazie wiedzy...\" ani \"W naszych artyku\u0142ach...\".\n- Nie u\u017cywaj sformu\u0142owa\u0144 sugeruj\u0105cych w\u0142asno\u015b\u0107 (\"nasze\", \"moje\"). Pisz bezosobowo lub bezpo\u015brednio.\n- Nie u\u017cywaj emoji.\n\nOdpowiedz teraz w j\u0119zyku polskim:"
        }
      },
      "id": "fb304eda-18f6-4d82-bddb-dcfb1f76db0d",
      "name": "AI Agent: Generate Answer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        1472,
        688
      ]
    },
    {
      "parameters": {
        "model": "anthropic/claude-haiku-4.5",
        "options": {
          "temperature": 0.5
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "typeVersion": 1,
      "position": [
        1424,
        960
      ],
      "id": "b30e576a-3858-4f5e-af68-96627ab9a4c4",
      "name": "OpenRouter Chat Model2",
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Webhook: RAG Question').item.json.body.sessionId || 'default' }}"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        1568,
        976
      ],
      "id": "3454a5e6-7e95-49c6-964a-0d5a0d0951eb",
      "name": "Simple Memory1"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "rag-agent",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "7e7472c5-fa8e-480d-81d0-5ffc61129b1f",
      "name": "Webhook: RAG Question",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        128,
        640
      ]
    }
  ],
  "connections": {
    "Webhook: RAG Question": {
      "main": [
        [
          {
            "node": "Code: Analyze Question",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Analyze Question": {
      "main": [
        [
          {
            "node": "HTTP: RAG Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: RAG Search": {
      "main": [
        [
          {
            "node": "Code: Format RAG Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Format RAG Results": {
      "main": [
        [
          {
            "node": "AI Agent: Generate Answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent: Generate Answer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory1": {
      "ai_memory": [
        [
          {
            "node": "AI Agent: Generate Answer",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    }
  }
}