From 1fc7f997bbd970ac72557bab72389e7c9d375566 Mon Sep 17 00:00:00 2001 From: enescingoz Date: Thu, 8 May 2025 19:45:17 +0100 Subject: [PATCH] n8n automations part 6 --- ...ecommendations with Qdrant and Open AI.txt | 849 ++++++++++++ Building Your First WhatsApp Chatbot (1).txt | 700 ++++++++++ Building Your First WhatsApp Chatbot.txt | 700 ++++++++++ ...es Memory And API Calling Capabalities.txt | 425 ++++++ ...Powered Chatbot with Pinecone & OpenAI.txt | 426 ++++++ ... OpenAI Assistant (by adding a memory).txt | 335 +++++ ... OpenAIs GPT via a simple Telegram Bot.txt | 122 ++ ...th PDF docs using AI (quoting sources).txt | 598 +++++++++ Chat with Postgresql Database.txt | 283 ++++ Chat with a Google Sheet using AI.txt | 616 +++++++++ Chat with local LLMs using n8n and Ollama.txt | 116 ++ ...chedule from Google Sheets in Telegram.txt | 678 ++++++++++ ...GPT Automatic Code Review in Gitlab MR.txt | 405 ++++++ ...rant, Python and Information Extractor.txt | 1150 +++++++++++++++++ 14 files changed, 7403 insertions(+) create mode 100644 Building RAG Chatbot for Movie Recommendations with Qdrant and Open AI.txt create mode 100644 Building Your First WhatsApp Chatbot (1).txt create mode 100644 Building Your First WhatsApp Chatbot.txt create mode 100644 Chat Assistant (OpenAI assistant) with Postgres Memory And API Calling Capabalities.txt create mode 100644 Chat with GitHub API Documentation_ RAG-Powered Chatbot with Pinecone & OpenAI.txt create mode 100644 Chat with OpenAI Assistant (by adding a memory).txt create mode 100644 Chat with OpenAIs GPT via a simple Telegram Bot.txt create mode 100644 Chat with PDF docs using AI (quoting sources).txt create mode 100644 Chat with Postgresql Database.txt create mode 100644 Chat with a Google Sheet using AI.txt create mode 100644 Chat with local LLMs using n8n and Ollama.txt create mode 100644 Chat with your event schedule from Google Sheets in Telegram.txt create mode 100644 ChatGPT Automatic Code Review in Gitlab MR.txt create mode 100644 Customer Insights with Qdrant, Python and Information Extractor.txt diff --git a/Building RAG Chatbot for Movie Recommendations with Qdrant and Open AI.txt b/Building RAG Chatbot for Movie Recommendations with Qdrant and Open AI.txt new file mode 100644 index 0000000..c81d10b --- /dev/null +++ b/Building RAG Chatbot for Movie Recommendations with Qdrant and Open AI.txt @@ -0,0 +1,849 @@ +{ +"id": "a58HZKwcOy7lmz56", +"meta": { +"instanceId": "178ef8a5109fc76c716d40bcadb720c455319f7b7a3fd5a39e4f336a091f524a", +"templateCredsSetupCompleted": true +}, +"name": "Building RAG Chatbot for Movie Recommendations with Qdrant and Open AI", +"tags": [], +"nodes": [ +{ +"id": "06a34e3b-519a-4b48-afd0-4f2b51d2105d", +"name": "When clicking ‘Test workflow’", +"type": "n8n-nodes-base.manualTrigger", +"position": [ +4980, +740 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "9213003d-433f-41ab-838b-be93860261b2", +"name": "GitHub", +"type": "n8n-nodes-base.github", +"position": [ +5200, +740 +], +"parameters": { +"owner": { +"__rl": true, +"mode": "name", +"value": "mrscoopers" +}, +"filePath": "Top_1000_IMDB_movies.csv", +"resource": "file", +"operation": "get", +"repository": { +"__rl": true, +"mode": "list", +"value": "n8n_demo", +"cachedResultUrl": "https://github.com/mrscoopers/n8n_demo", +"cachedResultName": "n8n_demo" +}, +"additionalParameters": {} +}, +"credentials": { +"githubApi": { +"id": "VbfC0mqEq24vPIwq", +"name": "GitHub n8n demo" +} +}, +"typeVersion": 1 +}, +{ +"id": "9850d1a9-3a6f-44c0-9f9d-4d20fda0b602", +"name": "Extract from File", +"type": "n8n-nodes-base.extractFromFile", +"position": [ +5360, +740 +], +"parameters": { +"options": {} +}, +"typeVersion": 1 +}, +{ +"id": "7704f993-b1c9-477a-8b5a-77dc2cb68161", +"name": "Embeddings OpenAI", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +5560, +940 +], +"parameters": { +"model": "text-embedding-3-small", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "deYJUwkgL1Euu613", +"name": "OpenAi account 2" +} +}, +"typeVersion": 1 +}, +{ +"id": "bc6dd8e5-0186-4bf9-9c60-2eab6d9b6520", +"name": "Default Data Loader", +"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", +"position": [ +5700, +960 +], +"parameters": { +"options": { +"metadata": { +"metadataValues": [ +{ +"name": "movie_name", +"value": "={{ $('Extract from File').item.json['Movie Name'] }}" +}, +{ +"name": "movie_release_date", +"value": "={{ $('Extract from File').item.json['Year of Release'] }}" +}, +{ +"name": "movie_description", +"value": "={{ $('Extract from File').item.json.Description }}" +} +] +} +}, +"jsonData": "={{ $('Extract from File').item.json.Description }}", +"jsonMode": "expressionData" +}, +"typeVersion": 1 +}, +{ +"id": "f87ea014-fe79-444b-88ea-0c4773872b0a", +"name": "Token Splitter", +"type": "@n8n/n8n-nodes-langchain.textSplitterTokenSplitter", +"position": [ +5700, +1140 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "d8d28cec-c8e8-4350-9e98-cdbc6da54988", +"name": "Qdrant Vector Store", +"type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant", +"position": [ +5600, +740 +], +"parameters": { +"mode": "insert", +"options": {}, +"qdrantCollection": { +"__rl": true, +"mode": "id", +"value": "imdb" +} +}, +"credentials": { +"qdrantApi": { +"id": "Zin08PA0RdXVUKK7", +"name": "QdrantApi n8n demo" +} +}, +"typeVersion": 1 +}, +{ +"id": "f86e03dc-12ea-4929-9035-4ec3cf46e300", +"name": "When chat message received", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +4920, +1140 +], +"webhookId": "71bfe0f8-227e-466b-9d07-69fd9fe4a27b", +"parameters": { +"options": {} +}, +"typeVersion": 1.1 +}, +{ +"id": "ead23ef6-2b6b-428d-b412-b3394bff8248", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +5040, +1340 +], +"parameters": { +"model": "gpt-4o-mini", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "deYJUwkgL1Euu613", +"name": "OpenAi account 2" +} +}, +"typeVersion": 1 +}, +{ +"id": "7ab936e1-aac8-43bc-a497-f2d02c2c19e5", +"name": "Call n8n Workflow Tool", +"type": "@n8n/n8n-nodes-langchain.toolWorkflow", +"position": [ +5320, +1340 +], +"parameters": { +"name": "movie_recommender", +"schemaType": "manual", +"workflowId": { +"__rl": true, +"mode": "id", +"value": "a58HZKwcOy7lmz56" +}, +"description": "Call this tool to get a list of recommended movies from a vector database. ", +"inputSchema": "{\n\"type\": \"object\",\n\"properties\": {\n\t\"positive_example\": {\n \"type\": \"string\",\n \"description\": \"A string with a movie description matching the user's positive recommendation request\"\n },\n \"negative_example\": {\n \"type\": \"string\",\n \"description\": \"A string with a movie description matching the user's negative anti-recommendation reuqest\"\n }\n}\n}", +"specifyInputSchema": true +}, +"typeVersion": 1.2 +}, +{ +"id": "ce55f334-698b-45b1-9e12-0eaa473187d4", +"name": "Window Buffer Memory", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +5160, +1340 +], +"parameters": {}, +"typeVersion": 1.2 +}, +{ +"id": "41c1ee11-3117-4765-98fc-e56cc6fc8fb2", +"name": "Execute Workflow Trigger", +"type": "n8n-nodes-base.executeWorkflowTrigger", +"position": [ +5640, +1600 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "db8d6ab6-8cd2-4a8c-993d-f1b7d7fdcffd", +"name": "Merge", +"type": "n8n-nodes-base.merge", +"position": [ +6540, +1500 +], +"parameters": { +"mode": "combine", +"options": {}, +"combineBy": "combineAll" +}, +"typeVersion": 3 +}, +{ +"id": "c7bc5e04-22b1-40db-ba74-1ab234e51375", +"name": "Split Out", +"type": "n8n-nodes-base.splitOut", +"position": [ +7260, +1480 +], +"parameters": { +"options": {}, +"fieldToSplitOut": "result" +}, +"typeVersion": 1 +}, +{ +"id": "a2002d2e-362a-49eb-a42d-7b665ddd67a0", +"name": "Split Out1", +"type": "n8n-nodes-base.splitOut", +"position": [ +7140, +1260 +], +"parameters": { +"options": {}, +"fieldToSplitOut": "result.points" +}, +"typeVersion": 1 +}, +{ +"id": "f69a87f1-bfb9-4337-9350-28d2416c1580", +"name": "Merge1", +"type": "n8n-nodes-base.merge", +"position": [ +7520, +1400 +], +"parameters": { +"mode": "combine", +"options": {}, +"fieldsToMatchString": "id" +}, +"typeVersion": 3 +}, +{ +"id": "b2f2529e-e260-4d72-88ef-09b804226004", +"name": "Aggregate", +"type": "n8n-nodes-base.aggregate", +"position": [ +7960, +1400 +], +"parameters": { +"options": {}, +"aggregate": "aggregateAllItemData", +"destinationFieldName": "response" +}, +"typeVersion": 1 +}, +{ +"id": "bedea10f-b4de-4f0e-9d60-cc8117a2b328", +"name": "AI Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +5140, +1140 +], +"parameters": { +"options": { +"systemMessage": "You are a Movie Recommender Tool using a Vector Database under the hood. Provide top-3 movie recommendations returned by the database, ordered by their recommendation score, but not showing the score to the user." +} +}, +"typeVersion": 1.6 +}, +{ +"id": "e04276b5-7d69-437b-bf4f-9717808cc8f6", +"name": "Embedding Recommendation Request with Open AI", +"type": "n8n-nodes-base.httpRequest", +"position": [ +5900, +1460 +], +"parameters": { +"url": "https://api.openai.com/v1/embeddings", +"method": "POST", +"options": {}, +"sendBody": true, +"sendHeaders": true, +"authentication": "predefinedCredentialType", +"bodyParameters": { +"parameters": [ +{ +"name": "input", +"value": "={{ $json.query.positive_example }}" +}, +{ +"name": "model", +"value": "text-embedding-3-small" +} +] +}, +"headerParameters": { +"parameters": [ +{ +"name": "Authorization", +"value": "Bearer $OPENAI_API_KEY" +} +] +}, +"nodeCredentialType": "openAiApi" +}, +"credentials": { +"openAiApi": { +"id": "deYJUwkgL1Euu613", +"name": "OpenAi account 2" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "68e99f06-82f5-432c-8b31-8a1ae34981a6", +"name": "Embedding Anti-Recommendation Request with Open AI", +"type": "n8n-nodes-base.httpRequest", +"position": [ +5920, +1660 +], +"parameters": { +"url": "https://api.openai.com/v1/embeddings", +"method": "POST", +"options": {}, +"sendBody": true, +"sendHeaders": true, +"authentication": "predefinedCredentialType", +"bodyParameters": { +"parameters": [ +{ +"name": "input", +"value": "={{ $json.query.negative_example }}" +}, +{ +"name": "model", +"value": "text-embedding-3-small" +} +] +}, +"headerParameters": { +"parameters": [ +{ +"name": "Authorization", +"value": "Bearer $OPENAI_API_KEY" +} +] +}, +"nodeCredentialType": "openAiApi" +}, +"credentials": { +"openAiApi": { +"id": "deYJUwkgL1Euu613", +"name": "OpenAi account 2" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "ecb1d7e1-b389-48e8-a34a-176bfc923641", +"name": "Extracting Embedding", +"type": "n8n-nodes-base.set", +"position": [ +6180, +1460 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "01a28c9d-aeb1-48bb-8a73-f8bddbd73460", +"name": "positive_example", +"type": "array", +"value": "={{ $json.data[0].embedding }}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "4ed11142-a734-435f-9f7a-f59e2d423076", +"name": "Extracting Embedding1", +"type": "n8n-nodes-base.set", +"position": [ +6180, +1660 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "01a28c9d-aeb1-48bb-8a73-f8bddbd73460", +"name": "negative_example", +"type": "array", +"value": "={{ $json.data[0].embedding }}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "ce3aa9bc-a5b1-4529-bff5-e0dba43b99f3", +"name": "Calling Qdrant Recommendation API", +"type": "n8n-nodes-base.httpRequest", +"position": [ +6840, +1500 +], +"parameters": { +"url": "https://edcc6735-2ffb-484f-b735-3467043828fe.europe-west3-0.gcp.cloud.qdrant.io:6333/collections/imdb_1000_open_ai/points/query", +"method": "POST", +"options": {}, +"jsonBody": "={\n \"query\": {\n \"recommend\": {\n \"positive\": [[{{ $json.positive_example }}]],\n \"negative\": [[{{ $json.negative_example }}]],\n \"strategy\": \"average_vector\"\n }\n },\n \"limit\":3\n}", +"sendBody": true, +"specifyBody": "json", +"authentication": "predefinedCredentialType", +"nodeCredentialType": "qdrantApi" +}, +"credentials": { +"qdrantApi": { +"id": "Zin08PA0RdXVUKK7", +"name": "QdrantApi n8n demo" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "9b8a6bdb-16fe-4edc-86d0-136fe059a777", +"name": "Retrieving Recommended Movies Meta Data", +"type": "n8n-nodes-base.httpRequest", +"position": [ +7060, +1460 +], +"parameters": { +"url": "https://edcc6735-2ffb-484f-b735-3467043828fe.europe-west3-0.gcp.cloud.qdrant.io:6333/collections/imdb_1000_open_ai/points", +"method": "POST", +"options": {}, +"jsonBody": "={\n \"ids\": [\"{{ $json.result.points[0].id }}\", \"{{ $json.result.points[1].id }}\", \"{{ $json.result.points[2].id }}\"],\n \"with_payload\":true\n}", +"sendBody": true, +"specifyBody": "json", +"authentication": "predefinedCredentialType", +"nodeCredentialType": "qdrantApi" +}, +"credentials": { +"qdrantApi": { +"id": "Zin08PA0RdXVUKK7", +"name": "QdrantApi n8n demo" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "28cdcad5-3dca-48a1-b626-19eef657114c", +"name": "Selecting Fields Relevant for Agent", +"type": "n8n-nodes-base.set", +"position": [ +7740, +1400 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "b4b520a5-d0e2-4dcb-af9d-0b7748fd44d6", +"name": "movie_recommendation_score", +"type": "number", +"value": "={{ $json.score }}" +}, +{ +"id": "c9f0982e-bd4e-484b-9eab-7e69e333f706", +"name": "movie_description", +"type": "string", +"value": "={{ $json.payload.content }}" +}, +{ +"id": "7c7baf11-89cd-4695-9f37-13eca7e01163", +"name": "movie_name", +"type": "string", +"value": "={{ $json.payload.metadata.movie_name }}" +}, +{ +"id": "1d1d269e-43c7-47b0-859b-268adf2dbc21", +"name": "movie_release_year", +"type": "string", +"value": "={{ $json.payload.metadata.release_year }}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "56e73f01-5557-460a-9a63-01357a1b456f", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +5560, +1780 +], +"parameters": { +"content": "Tool, calling Qdrant's recommendation API based on user's request, transformed by AI agent" +}, +"typeVersion": 1 +}, +{ +"id": "cce5250e-0285-4fd0-857f-4b117151cd8b", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +4680, +720 +], +"parameters": { +"content": "Uploading data (movies and their descriptions) to Qdrant Vector Store\n" +}, +"typeVersion": 1 +} +], +"active": false, +"pinData": { +"Execute Workflow Trigger": [ +{ +"json": { +"query": { +"negative_example": "horror bloody movie", +"positive_example": "romantic comedy" +} +} +} +] +}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "40d3669b-d333-435f-99fc-db623deda2cb", +"connections": { +"Merge": { +"main": [ +[ +{ +"node": "Calling Qdrant Recommendation API", +"type": "main", +"index": 0 +} +] +] +}, +"GitHub": { +"main": [ +[ +{ +"node": "Extract from File", +"type": "main", +"index": 0 +} +] +] +}, +"Merge1": { +"main": [ +[ +{ +"node": "Selecting Fields Relevant for Agent", +"type": "main", +"index": 0 +} +] +] +}, +"Split Out": { +"main": [ +[ +{ +"node": "Merge1", +"type": "main", +"index": 1 +} +] +] +}, +"Split Out1": { +"main": [ +[ +{ +"node": "Merge1", +"type": "main", +"index": 0 +} +] +] +}, +"Token Splitter": { +"ai_textSplitter": [ +[ +{ +"node": "Default Data Loader", +"type": "ai_textSplitter", +"index": 0 +} +] +] +}, +"Embeddings OpenAI": { +"ai_embedding": [ +[ +{ +"node": "Qdrant Vector Store", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"Extract from File": { +"main": [ +[ +{ +"node": "Qdrant Vector Store", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Default Data Loader": { +"ai_document": [ +[ +{ +"node": "Qdrant Vector Store", +"type": "ai_document", +"index": 0 +} +] +] +}, +"Extracting Embedding": { +"main": [ +[ +{ +"node": "Merge", +"type": "main", +"index": 0 +} +] +] +}, +"Window Buffer Memory": { +"ai_memory": [ +[ +{ +"node": "AI Agent", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"Extracting Embedding1": { +"main": [ +[ +{ +"node": "Merge", +"type": "main", +"index": 1 +} +] +] +}, +"Call n8n Workflow Tool": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Execute Workflow Trigger": { +"main": [ +[ +{ +"node": "Embedding Recommendation Request with Open AI", +"type": "main", +"index": 0 +}, +{ +"node": "Embedding Anti-Recommendation Request with Open AI", +"type": "main", +"index": 0 +} +] +] +}, +"When chat message received": { +"main": [ +[ +{ +"node": "AI Agent", +"type": "main", +"index": 0 +} +] +] +}, +"Calling Qdrant Recommendation API": { +"main": [ +[ +{ +"node": "Retrieving Recommended Movies Meta Data", +"type": "main", +"index": 0 +}, +{ +"node": "Split Out1", +"type": "main", +"index": 0 +} +] +] +}, +"When clicking ‘Test workflow’": { +"main": [ +[ +{ +"node": "GitHub", +"type": "main", +"index": 0 +} +] +] +}, +"Selecting Fields Relevant for Agent": { +"main": [ +[ +{ +"node": "Aggregate", +"type": "main", +"index": 0 +} +] +] +}, +"Retrieving Recommended Movies Meta Data": { +"main": [ +[ +{ +"node": "Split Out", +"type": "main", +"index": 0 +} +] +] +}, +"Embedding Recommendation Request with Open AI": { +"main": [ +[ +{ +"node": "Extracting Embedding", +"type": "main", +"index": 0 +} +] +] +}, +"Embedding Anti-Recommendation Request with Open AI": { +"main": [ +[ +{ +"node": "Extracting Embedding1", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Building Your First WhatsApp Chatbot (1).txt b/Building Your First WhatsApp Chatbot (1).txt new file mode 100644 index 0000000..9263c95 --- /dev/null +++ b/Building Your First WhatsApp Chatbot (1).txt @@ -0,0 +1,700 @@ +{ +"meta": { +"instanceId": "408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9" +}, +"nodes": [ +{ +"id": "77ee6494-4898-47dc-81d9-35daf6f0beea", +"name": "WhatsApp Trigger", +"type": "n8n-nodes-base.whatsAppTrigger", +"position": [ +1360, +-280 +], +"webhookId": "aaa71f03-f7af-4d18-8d9a-0afb86f1b554", +"parameters": { +"updates": [ +"messages" +] +}, +"credentials": { +"whatsAppTriggerApi": { +"id": "H3uYNtpeczKMqtYm", +"name": "WhatsApp OAuth account" +} +}, +"typeVersion": 1 +}, +{ +"id": "57210e27-1f89-465a-98cc-43f890a4bf58", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +1960, +-200 +], +"parameters": { +"model": "gpt-4o-2024-08-06", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "e1053235-0ade-4e36-9ad2-8b29c78fced8", +"name": "Window Buffer Memory", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +2080, +-200 +], +"parameters": { +"sessionKey": "=whatsapp-75-{{ $json.messages[0].from }}", +"sessionIdType": "customKey" +}, +"typeVersion": 1.2 +}, +{ +"id": "69f1b78b-7c93-4713-863a-27e04809996f", +"name": "Vector Store Tool", +"type": "@n8n/n8n-nodes-langchain.toolVectorStore", +"position": [ +2200, +-200 +], +"parameters": { +"name": "query_product_brochure", +"description": "Call this tool to query the product brochure. Valid for the year 2024." +}, +"typeVersion": 1 +}, +{ +"id": "170e8f7d-7e14-48dd-9f80-5352cc411fc1", +"name": "Embeddings OpenAI", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +2200, +80 +], +"parameters": { +"model": "text-embedding-3-small", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "ee78320b-d407-49e8-b4b8-417582a44709", +"name": "OpenAI Chat Model1", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +2440, +-60 +], +"parameters": { +"model": "gpt-4o-2024-08-06", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "9dd89378-5acf-4ca6-8d84-e6e64254ed02", +"name": "When clicking ‘Test workflow’", +"type": "n8n-nodes-base.manualTrigger", +"position": [ +0, +-240 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "e68fc137-1bcb-43f0-b597-3ae07f380c15", +"name": "Embeddings OpenAI1", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +760, +-20 +], +"parameters": { +"model": "text-embedding-3-small", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "2d31e92b-18d4-4f6b-8cdb-bed0056d50d7", +"name": "Default Data Loader", +"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", +"position": [ +900, +-20 +], +"parameters": { +"options": {}, +"jsonData": "={{ $('Extract from File').item.json.text }}", +"jsonMode": "expressionData" +}, +"typeVersion": 1 +}, +{ +"id": "ca0c015e-fba2-4dca-b0fe-bac66681725a", +"name": "Recursive Character Text Splitter", +"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", +"position": [ +900, +100 +], +"parameters": { +"options": {}, +"chunkSize": 2000, +"chunkOverlap": {} +}, +"typeVersion": 1 +}, +{ +"id": "63abb6b2-b955-4e65-9c63-3211dca65613", +"name": "Extract from File", +"type": "n8n-nodes-base.extractFromFile", +"position": [ +360, +-240 +], +"parameters": { +"options": {}, +"operation": "pdf" +}, +"typeVersion": 1 +}, +{ +"id": "be2add9c-3670-4196-8c38-82742bf4f283", +"name": "get Product Brochure", +"type": "n8n-nodes-base.httpRequest", +"position": [ +180, +-240 +], +"parameters": { +"url": "https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf", +"options": {} +}, +"typeVersion": 4.2 +}, +{ +"id": "1ae5a311-36d7-4454-ab14-6788d1331780", +"name": "Reply To User", +"type": "n8n-nodes-base.whatsApp", +"position": [ +2820, +-280 +], +"parameters": { +"textBody": "={{ $json.output }}", +"operation": "send", +"phoneNumberId": "477115632141067", +"requestOptions": {}, +"additionalFields": { +"previewUrl": false +}, +"recipientPhoneNumber": "={{ $('WhatsApp Trigger').item.json.messages[0].from }}" +}, +"credentials": { +"whatsAppApi": { +"id": "9SFJPeqrpChOkAmw", +"name": "WhatsApp account" +} +}, +"typeVersion": 1 +}, +{ +"id": "b6efba81-18b0-4378-bb91-51f39ca57f3e", +"name": "Reply To User1", +"type": "n8n-nodes-base.whatsApp", +"position": [ +1760, +80 +], +"parameters": { +"textBody": "=I'm unable to process non-text messages. Please send only text messages. Thanks!", +"operation": "send", +"phoneNumberId": "477115632141067", +"requestOptions": {}, +"additionalFields": { +"previewUrl": false +}, +"recipientPhoneNumber": "={{ $('WhatsApp Trigger').item.json.messages[0].from }}" +}, +"credentials": { +"whatsAppApi": { +"id": "9SFJPeqrpChOkAmw", +"name": "WhatsApp account" +} +}, +"typeVersion": 1 +}, +{ +"id": "52decd86-ac6c-4d91-a938-86f93ec5f822", +"name": "Product Catalogue", +"type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", +"position": [ +2200, +-60 +], +"parameters": { +"memoryKey": "whatsapp-75" +}, +"typeVersion": 1 +}, +{ +"id": "6dd5a652-2464-4ab8-8e5f-568529299523", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-88.75, +-473.4375 +], +"parameters": { +"color": 7, +"width": 640.4375, +"height": 434.6875, +"content": "## 1. Download Product Brochure PDF\n[Read more about the HTTP Request Tool](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest)\n\nImport your marketing PDF document to build your vector store. This will be used as the knowledgebase by the Sales AI Agent.\n\nFor this demonstration, we'll use the HTTP request node to import the YAMAHA POWERED LOUDSPEAKERS 2024 brochure ([Source](https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf)) and an Extract from File node to extract the text contents. " +}, +"typeVersion": 1 +}, +{ +"id": "116663bc-d8d6-41a5-93dc-b219adbb2235", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +580, +-476 +], +"parameters": { +"color": 7, +"width": 614.6875, +"height": 731.1875, +"content": "## 2. Create Product Brochure Vector Store\n[Read more about the In-Memory Vector Store](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/)\n\nVector stores are powerful databases which serve the purpose of matching a user's questions to relevant parts of a document. By creating a vector store of our product catalog, we'll allow users to query using natural language.\n\nTo keep things simple, we'll use the **In-memory Vector Store** which comes built-in to n8n and doesn't require a separate service. For production deployments, I'd recommend replacing the in-memory vector store with either [Qdrant](https://qdrant.tech) or [Pinecone](https://pinecone.io)." +}, +"typeVersion": 1 +}, +{ +"id": "86bd5334-d735-4650-aeff-06230119d705", +"name": "Create Product Catalogue", +"type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", +"position": [ +760, +-200 +], +"parameters": { +"mode": "insert", +"memoryKey": "whatsapp-75", +"clearStore": true +}, +"typeVersion": 1 +}, +{ +"id": "b8078b0d-cbd7-423f-bb30-13902988be38", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1254, +-552 +], +"parameters": { +"color": 7, +"width": 546.6875, +"height": 484.1875, +"content": "## 3. Use the WhatsApp Trigger\n[Learn more about the WhatsApp Trigger](https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.whatsapptrigger/)\n\nThe WhatsApp Trigger allows you to receive incoming WhatsApp messages from customers. It requires a bit of setup so remember to follow the documentation carefully! Once ready however, it's quite easy to build powerful workflows which are easily accessible to users.\n\nNote that WhatsApp can send many message types such as audio and video so in this demonstration, we'll filter them out and just accept the text messages." +}, +"typeVersion": 1 +}, +{ +"id": "5bf7ed07-282b-4198-aa90-3e5ae5180404", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1640, +280 +], +"parameters": { +"width": 338, +"height": 92, +"content": "### Want to handle all message types?\nCheck out my other WhatsApp template in my creator page! https://n8n.io/creators/jimleuk/" +}, +"typeVersion": 1 +}, +{ +"id": "a3661b59-25d2-446e-8462-32b4d692b69d", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1640, +-40 +], +"parameters": { +"color": 7, +"width": 337.6875, +"height": 311.1875, +"content": "### 3a. Handle Unsupported Message Types\nFor non-text messages, we'll just reply with a simple message to inform the sender." +}, +"typeVersion": 1 +}, +{ +"id": "ea3c9ee1-505a-40e7-82fe-9169bdbb80af", +"name": "Sticky Note5", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1840, +-682.5 +], +"parameters": { +"color": 7, +"width": 746.6875, +"height": 929.1875, +"content": "## 4. Sales AI Agent Responds To Customers\n[Learn more about using AI Agents](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/)\n\nn8n's AI agents are powerful nodes which make it incredibly easy to use state-of-the-art AI in your workflows. Not only do they have the ability to remember conversations per individual customer but also tap into resources such as our product catalogue vector store to pull factual information and data for every question.\n\nIn this demonstration, we use an AI agent which is directed to help the user navigate the product brochure. A Chat memory subnode is attached to identify and keep track of the customer session. A Vector store tool is added to allow the Agent to tap into the product catalogue knowledgebase we built earlier." +}, +"typeVersion": 1 +}, +{ +"id": "5c72df8d-bca1-4634-b1ed-61ffec8bd103", +"name": "Sticky Note6", +"type": "n8n-nodes-base.stickyNote", +"position": [ +2620, +-560 +], +"parameters": { +"color": 7, +"width": 495.4375, +"height": 484.1875, +"content": "## 5. Repond to WhatsApp User\n[Learn more about the WhatsApp Node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.whatsapp/)\n\nThe WhatsApp node is the go-to if you want to interact with WhatsApp users. With this node, you can send text, images, audio and video messages as well as use your WhatsApp message templates.\n\nHere, we'll keep it simple by replying with a text message which is the output of the AI agent." +}, +"typeVersion": 1 +}, +{ +"id": "48ec809f-ca0e-4052-b403-9ad7077b3fff", +"name": "Sticky Note7", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-520, +-620 +], +"parameters": { +"width": 401.25, +"height": 582.6283033962263, +"content": "## Try It Out!\n\n### This n8n template builds a simple WhatsApp chabot acting as a Sales Agent. The Agent is backed by a product catalog vector store to better answer user's questions.\n\n* This template is in 2 parts: creating the product catalog vector store and building the WhatsApp AI chatbot.\n* A product brochure is imported via HTTP request node and its text contents extracted.\n* The text contents are then uploaded to the in-memory vector store to build a knowledgebase for the chatbot.\n* A WhatsApp trigger is used to capture messages from customers where non-text messages are filtered out.\n* The customer's message is sent to the AI Agent which queries the product catalogue using the vector store tool.\n* The Agent's response is sent back to the user via the WhatsApp node.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!" +}, +"typeVersion": 1 +}, +{ +"id": "87cf9b41-66de-49a7-aeb0-c8809191b5a0", +"name": "Handle Message Types", +"type": "n8n-nodes-base.switch", +"position": [ +1560, +-280 +], +"parameters": { +"rules": { +"values": [ +{ +"outputKey": "Supported", +"conditions": { +"options": { +"version": 2, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"operator": { +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $json.messages[0].type }}", +"rightValue": "text" +} +] +}, +"renameOutput": true +}, +{ +"outputKey": "Not Supported", +"conditions": { +"options": { +"version": 2, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "89971d8c-a386-4e77-8f6c-f491a8e84cb6", +"operator": { +"type": "string", +"operation": "notEquals" +}, +"leftValue": "={{ $json.messages[0].type }}", +"rightValue": "text" +} +] +}, +"renameOutput": true +} +] +}, +"options": {} +}, +"typeVersion": 3.2 +}, +{ +"id": "e52f0a50-0c34-4c4a-b493-4c42ba112277", +"name": "Sticky Note8", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-80, +-20 +], +"parameters": { +"color": 5, +"width": 345.10906976744184, +"height": 114.53583720930231, +"content": "### You only have to run this part once!\nRun this step to populate our product catalogue vector. Run again if you want to update the vector store with a new version." +}, +"typeVersion": 1 +}, +{ +"id": "c1a7d6d1-191e-4343-af9f-f2c9eb4ecf49", +"name": "Sticky Note9", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1260, +-40 +], +"parameters": { +"color": 5, +"width": 364.6293255813954, +"height": 107.02804651162779, +"content": "### Activate your workflow to use!\nTo start using the WhatsApp chatbot, you'll need to activate the workflow. If you are self-hosting ensure WhatsApp is able to connect to your server." +}, +"typeVersion": 1 +}, +{ +"id": "a36524d0-22a6-48cc-93fe-b4571cec428a", +"name": "AI Sales Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +1960, +-400 +], +"parameters": { +"text": "={{ $json.messages[0].text.body }}", +"options": { +"systemMessage": "You are an assistant working for a company who sells Yamaha Powered Loudspeakers and helping the user navigate the product catalog for the year 2024. Your goal is not to facilitate a sale but if the user enquires, direct them to the appropriate website, url or contact information.\n\nDo your best to answer any questions factually. If you don't know the answer or unable to obtain the information from the datastore, then tell the user so." +}, +"promptType": "define" +}, +"typeVersion": 1.6 +} +], +"pinData": {}, +"connections": { +"AI Sales Agent": { +"main": [ +[ +{ +"node": "Reply To User", +"type": "main", +"index": 0 +} +] +] +}, +"WhatsApp Trigger": { +"main": [ +[ +{ +"node": "Handle Message Types", +"type": "main", +"index": 0 +} +] +] +}, +"Embeddings OpenAI": { +"ai_embedding": [ +[ +{ +"node": "Product Catalogue", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"Extract from File": { +"main": [ +[ +{ +"node": "Create Product Catalogue", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Sales Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Product Catalogue": { +"ai_vectorStore": [ +[ +{ +"node": "Vector Store Tool", +"type": "ai_vectorStore", +"index": 0 +} +] +] +}, +"Vector Store Tool": { +"ai_tool": [ +[ +{ +"node": "AI Sales Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Embeddings OpenAI1": { +"ai_embedding": [ +[ +{ +"node": "Create Product Catalogue", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"OpenAI Chat Model1": { +"ai_languageModel": [ +[ +{ +"node": "Vector Store Tool", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Default Data Loader": { +"ai_document": [ +[ +{ +"node": "Create Product Catalogue", +"type": "ai_document", +"index": 0 +} +] +] +}, +"Handle Message Types": { +"main": [ +[ +{ +"node": "AI Sales Agent", +"type": "main", +"index": 0 +} +], +[ +{ +"node": "Reply To User1", +"type": "main", +"index": 0 +} +] +] +}, +"Window Buffer Memory": { +"ai_memory": [ +[ +{ +"node": "AI Sales Agent", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"get Product Brochure": { +"main": [ +[ +{ +"node": "Extract from File", +"type": "main", +"index": 0 +} +] +] +}, +"Recursive Character Text Splitter": { +"ai_textSplitter": [ +[ +{ +"node": "Default Data Loader", +"type": "ai_textSplitter", +"index": 0 +} +] +] +}, +"When clicking ‘Test workflow’": { +"main": [ +[ +{ +"node": "get Product Brochure", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Building Your First WhatsApp Chatbot.txt b/Building Your First WhatsApp Chatbot.txt new file mode 100644 index 0000000..9263c95 --- /dev/null +++ b/Building Your First WhatsApp Chatbot.txt @@ -0,0 +1,700 @@ +{ +"meta": { +"instanceId": "408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9" +}, +"nodes": [ +{ +"id": "77ee6494-4898-47dc-81d9-35daf6f0beea", +"name": "WhatsApp Trigger", +"type": "n8n-nodes-base.whatsAppTrigger", +"position": [ +1360, +-280 +], +"webhookId": "aaa71f03-f7af-4d18-8d9a-0afb86f1b554", +"parameters": { +"updates": [ +"messages" +] +}, +"credentials": { +"whatsAppTriggerApi": { +"id": "H3uYNtpeczKMqtYm", +"name": "WhatsApp OAuth account" +} +}, +"typeVersion": 1 +}, +{ +"id": "57210e27-1f89-465a-98cc-43f890a4bf58", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +1960, +-200 +], +"parameters": { +"model": "gpt-4o-2024-08-06", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "e1053235-0ade-4e36-9ad2-8b29c78fced8", +"name": "Window Buffer Memory", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +2080, +-200 +], +"parameters": { +"sessionKey": "=whatsapp-75-{{ $json.messages[0].from }}", +"sessionIdType": "customKey" +}, +"typeVersion": 1.2 +}, +{ +"id": "69f1b78b-7c93-4713-863a-27e04809996f", +"name": "Vector Store Tool", +"type": "@n8n/n8n-nodes-langchain.toolVectorStore", +"position": [ +2200, +-200 +], +"parameters": { +"name": "query_product_brochure", +"description": "Call this tool to query the product brochure. Valid for the year 2024." +}, +"typeVersion": 1 +}, +{ +"id": "170e8f7d-7e14-48dd-9f80-5352cc411fc1", +"name": "Embeddings OpenAI", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +2200, +80 +], +"parameters": { +"model": "text-embedding-3-small", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "ee78320b-d407-49e8-b4b8-417582a44709", +"name": "OpenAI Chat Model1", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +2440, +-60 +], +"parameters": { +"model": "gpt-4o-2024-08-06", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "9dd89378-5acf-4ca6-8d84-e6e64254ed02", +"name": "When clicking ‘Test workflow’", +"type": "n8n-nodes-base.manualTrigger", +"position": [ +0, +-240 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "e68fc137-1bcb-43f0-b597-3ae07f380c15", +"name": "Embeddings OpenAI1", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +760, +-20 +], +"parameters": { +"model": "text-embedding-3-small", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "2d31e92b-18d4-4f6b-8cdb-bed0056d50d7", +"name": "Default Data Loader", +"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", +"position": [ +900, +-20 +], +"parameters": { +"options": {}, +"jsonData": "={{ $('Extract from File').item.json.text }}", +"jsonMode": "expressionData" +}, +"typeVersion": 1 +}, +{ +"id": "ca0c015e-fba2-4dca-b0fe-bac66681725a", +"name": "Recursive Character Text Splitter", +"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", +"position": [ +900, +100 +], +"parameters": { +"options": {}, +"chunkSize": 2000, +"chunkOverlap": {} +}, +"typeVersion": 1 +}, +{ +"id": "63abb6b2-b955-4e65-9c63-3211dca65613", +"name": "Extract from File", +"type": "n8n-nodes-base.extractFromFile", +"position": [ +360, +-240 +], +"parameters": { +"options": {}, +"operation": "pdf" +}, +"typeVersion": 1 +}, +{ +"id": "be2add9c-3670-4196-8c38-82742bf4f283", +"name": "get Product Brochure", +"type": "n8n-nodes-base.httpRequest", +"position": [ +180, +-240 +], +"parameters": { +"url": "https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf", +"options": {} +}, +"typeVersion": 4.2 +}, +{ +"id": "1ae5a311-36d7-4454-ab14-6788d1331780", +"name": "Reply To User", +"type": "n8n-nodes-base.whatsApp", +"position": [ +2820, +-280 +], +"parameters": { +"textBody": "={{ $json.output }}", +"operation": "send", +"phoneNumberId": "477115632141067", +"requestOptions": {}, +"additionalFields": { +"previewUrl": false +}, +"recipientPhoneNumber": "={{ $('WhatsApp Trigger').item.json.messages[0].from }}" +}, +"credentials": { +"whatsAppApi": { +"id": "9SFJPeqrpChOkAmw", +"name": "WhatsApp account" +} +}, +"typeVersion": 1 +}, +{ +"id": "b6efba81-18b0-4378-bb91-51f39ca57f3e", +"name": "Reply To User1", +"type": "n8n-nodes-base.whatsApp", +"position": [ +1760, +80 +], +"parameters": { +"textBody": "=I'm unable to process non-text messages. Please send only text messages. Thanks!", +"operation": "send", +"phoneNumberId": "477115632141067", +"requestOptions": {}, +"additionalFields": { +"previewUrl": false +}, +"recipientPhoneNumber": "={{ $('WhatsApp Trigger').item.json.messages[0].from }}" +}, +"credentials": { +"whatsAppApi": { +"id": "9SFJPeqrpChOkAmw", +"name": "WhatsApp account" +} +}, +"typeVersion": 1 +}, +{ +"id": "52decd86-ac6c-4d91-a938-86f93ec5f822", +"name": "Product Catalogue", +"type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", +"position": [ +2200, +-60 +], +"parameters": { +"memoryKey": "whatsapp-75" +}, +"typeVersion": 1 +}, +{ +"id": "6dd5a652-2464-4ab8-8e5f-568529299523", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-88.75, +-473.4375 +], +"parameters": { +"color": 7, +"width": 640.4375, +"height": 434.6875, +"content": "## 1. Download Product Brochure PDF\n[Read more about the HTTP Request Tool](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest)\n\nImport your marketing PDF document to build your vector store. This will be used as the knowledgebase by the Sales AI Agent.\n\nFor this demonstration, we'll use the HTTP request node to import the YAMAHA POWERED LOUDSPEAKERS 2024 brochure ([Source](https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf)) and an Extract from File node to extract the text contents. " +}, +"typeVersion": 1 +}, +{ +"id": "116663bc-d8d6-41a5-93dc-b219adbb2235", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +580, +-476 +], +"parameters": { +"color": 7, +"width": 614.6875, +"height": 731.1875, +"content": "## 2. Create Product Brochure Vector Store\n[Read more about the In-Memory Vector Store](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/)\n\nVector stores are powerful databases which serve the purpose of matching a user's questions to relevant parts of a document. By creating a vector store of our product catalog, we'll allow users to query using natural language.\n\nTo keep things simple, we'll use the **In-memory Vector Store** which comes built-in to n8n and doesn't require a separate service. For production deployments, I'd recommend replacing the in-memory vector store with either [Qdrant](https://qdrant.tech) or [Pinecone](https://pinecone.io)." +}, +"typeVersion": 1 +}, +{ +"id": "86bd5334-d735-4650-aeff-06230119d705", +"name": "Create Product Catalogue", +"type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory", +"position": [ +760, +-200 +], +"parameters": { +"mode": "insert", +"memoryKey": "whatsapp-75", +"clearStore": true +}, +"typeVersion": 1 +}, +{ +"id": "b8078b0d-cbd7-423f-bb30-13902988be38", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1254, +-552 +], +"parameters": { +"color": 7, +"width": 546.6875, +"height": 484.1875, +"content": "## 3. Use the WhatsApp Trigger\n[Learn more about the WhatsApp Trigger](https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.whatsapptrigger/)\n\nThe WhatsApp Trigger allows you to receive incoming WhatsApp messages from customers. It requires a bit of setup so remember to follow the documentation carefully! Once ready however, it's quite easy to build powerful workflows which are easily accessible to users.\n\nNote that WhatsApp can send many message types such as audio and video so in this demonstration, we'll filter them out and just accept the text messages." +}, +"typeVersion": 1 +}, +{ +"id": "5bf7ed07-282b-4198-aa90-3e5ae5180404", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1640, +280 +], +"parameters": { +"width": 338, +"height": 92, +"content": "### Want to handle all message types?\nCheck out my other WhatsApp template in my creator page! https://n8n.io/creators/jimleuk/" +}, +"typeVersion": 1 +}, +{ +"id": "a3661b59-25d2-446e-8462-32b4d692b69d", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1640, +-40 +], +"parameters": { +"color": 7, +"width": 337.6875, +"height": 311.1875, +"content": "### 3a. Handle Unsupported Message Types\nFor non-text messages, we'll just reply with a simple message to inform the sender." +}, +"typeVersion": 1 +}, +{ +"id": "ea3c9ee1-505a-40e7-82fe-9169bdbb80af", +"name": "Sticky Note5", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1840, +-682.5 +], +"parameters": { +"color": 7, +"width": 746.6875, +"height": 929.1875, +"content": "## 4. Sales AI Agent Responds To Customers\n[Learn more about using AI Agents](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/)\n\nn8n's AI agents are powerful nodes which make it incredibly easy to use state-of-the-art AI in your workflows. Not only do they have the ability to remember conversations per individual customer but also tap into resources such as our product catalogue vector store to pull factual information and data for every question.\n\nIn this demonstration, we use an AI agent which is directed to help the user navigate the product brochure. A Chat memory subnode is attached to identify and keep track of the customer session. A Vector store tool is added to allow the Agent to tap into the product catalogue knowledgebase we built earlier." +}, +"typeVersion": 1 +}, +{ +"id": "5c72df8d-bca1-4634-b1ed-61ffec8bd103", +"name": "Sticky Note6", +"type": "n8n-nodes-base.stickyNote", +"position": [ +2620, +-560 +], +"parameters": { +"color": 7, +"width": 495.4375, +"height": 484.1875, +"content": "## 5. Repond to WhatsApp User\n[Learn more about the WhatsApp Node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.whatsapp/)\n\nThe WhatsApp node is the go-to if you want to interact with WhatsApp users. With this node, you can send text, images, audio and video messages as well as use your WhatsApp message templates.\n\nHere, we'll keep it simple by replying with a text message which is the output of the AI agent." +}, +"typeVersion": 1 +}, +{ +"id": "48ec809f-ca0e-4052-b403-9ad7077b3fff", +"name": "Sticky Note7", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-520, +-620 +], +"parameters": { +"width": 401.25, +"height": 582.6283033962263, +"content": "## Try It Out!\n\n### This n8n template builds a simple WhatsApp chabot acting as a Sales Agent. The Agent is backed by a product catalog vector store to better answer user's questions.\n\n* This template is in 2 parts: creating the product catalog vector store and building the WhatsApp AI chatbot.\n* A product brochure is imported via HTTP request node and its text contents extracted.\n* The text contents are then uploaded to the in-memory vector store to build a knowledgebase for the chatbot.\n* A WhatsApp trigger is used to capture messages from customers where non-text messages are filtered out.\n* The customer's message is sent to the AI Agent which queries the product catalogue using the vector store tool.\n* The Agent's response is sent back to the user via the WhatsApp node.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!" +}, +"typeVersion": 1 +}, +{ +"id": "87cf9b41-66de-49a7-aeb0-c8809191b5a0", +"name": "Handle Message Types", +"type": "n8n-nodes-base.switch", +"position": [ +1560, +-280 +], +"parameters": { +"rules": { +"values": [ +{ +"outputKey": "Supported", +"conditions": { +"options": { +"version": 2, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"operator": { +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $json.messages[0].type }}", +"rightValue": "text" +} +] +}, +"renameOutput": true +}, +{ +"outputKey": "Not Supported", +"conditions": { +"options": { +"version": 2, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "89971d8c-a386-4e77-8f6c-f491a8e84cb6", +"operator": { +"type": "string", +"operation": "notEquals" +}, +"leftValue": "={{ $json.messages[0].type }}", +"rightValue": "text" +} +] +}, +"renameOutput": true +} +] +}, +"options": {} +}, +"typeVersion": 3.2 +}, +{ +"id": "e52f0a50-0c34-4c4a-b493-4c42ba112277", +"name": "Sticky Note8", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-80, +-20 +], +"parameters": { +"color": 5, +"width": 345.10906976744184, +"height": 114.53583720930231, +"content": "### You only have to run this part once!\nRun this step to populate our product catalogue vector. Run again if you want to update the vector store with a new version." +}, +"typeVersion": 1 +}, +{ +"id": "c1a7d6d1-191e-4343-af9f-f2c9eb4ecf49", +"name": "Sticky Note9", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1260, +-40 +], +"parameters": { +"color": 5, +"width": 364.6293255813954, +"height": 107.02804651162779, +"content": "### Activate your workflow to use!\nTo start using the WhatsApp chatbot, you'll need to activate the workflow. If you are self-hosting ensure WhatsApp is able to connect to your server." +}, +"typeVersion": 1 +}, +{ +"id": "a36524d0-22a6-48cc-93fe-b4571cec428a", +"name": "AI Sales Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +1960, +-400 +], +"parameters": { +"text": "={{ $json.messages[0].text.body }}", +"options": { +"systemMessage": "You are an assistant working for a company who sells Yamaha Powered Loudspeakers and helping the user navigate the product catalog for the year 2024. Your goal is not to facilitate a sale but if the user enquires, direct them to the appropriate website, url or contact information.\n\nDo your best to answer any questions factually. If you don't know the answer or unable to obtain the information from the datastore, then tell the user so." +}, +"promptType": "define" +}, +"typeVersion": 1.6 +} +], +"pinData": {}, +"connections": { +"AI Sales Agent": { +"main": [ +[ +{ +"node": "Reply To User", +"type": "main", +"index": 0 +} +] +] +}, +"WhatsApp Trigger": { +"main": [ +[ +{ +"node": "Handle Message Types", +"type": "main", +"index": 0 +} +] +] +}, +"Embeddings OpenAI": { +"ai_embedding": [ +[ +{ +"node": "Product Catalogue", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"Extract from File": { +"main": [ +[ +{ +"node": "Create Product Catalogue", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Sales Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Product Catalogue": { +"ai_vectorStore": [ +[ +{ +"node": "Vector Store Tool", +"type": "ai_vectorStore", +"index": 0 +} +] +] +}, +"Vector Store Tool": { +"ai_tool": [ +[ +{ +"node": "AI Sales Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Embeddings OpenAI1": { +"ai_embedding": [ +[ +{ +"node": "Create Product Catalogue", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"OpenAI Chat Model1": { +"ai_languageModel": [ +[ +{ +"node": "Vector Store Tool", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Default Data Loader": { +"ai_document": [ +[ +{ +"node": "Create Product Catalogue", +"type": "ai_document", +"index": 0 +} +] +] +}, +"Handle Message Types": { +"main": [ +[ +{ +"node": "AI Sales Agent", +"type": "main", +"index": 0 +} +], +[ +{ +"node": "Reply To User1", +"type": "main", +"index": 0 +} +] +] +}, +"Window Buffer Memory": { +"ai_memory": [ +[ +{ +"node": "AI Sales Agent", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"get Product Brochure": { +"main": [ +[ +{ +"node": "Extract from File", +"type": "main", +"index": 0 +} +] +] +}, +"Recursive Character Text Splitter": { +"ai_textSplitter": [ +[ +{ +"node": "Default Data Loader", +"type": "ai_textSplitter", +"index": 0 +} +] +] +}, +"When clicking ‘Test workflow’": { +"main": [ +[ +{ +"node": "get Product Brochure", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat Assistant (OpenAI assistant) with Postgres Memory And API Calling Capabalities.txt b/Chat Assistant (OpenAI assistant) with Postgres Memory And API Calling Capabalities.txt new file mode 100644 index 0000000..083a1d9 --- /dev/null +++ b/Chat Assistant (OpenAI assistant) with Postgres Memory And API Calling Capabalities.txt @@ -0,0 +1,425 @@ +{ +"id": "BMI5WkmyU8nZqfII", +"meta": { +"instanceId": "e03b0f22ca12c92061d789d5980a9bc31d9d7e7dd7513ac93c09ac5a0d147623", +"templateCredsSetupCompleted": true +}, +"name": "modelo do chatbot", +"tags": [], +"nodes": [ +{ +"id": "c6e454af-70a1-4c65-8450-8159f7fc738b", +"name": "If", +"type": "n8n-nodes-base.if", +"position": [ +160, +560 +], +"parameters": { +"options": {}, +"conditions": { +"options": { +"version": 1, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "7ea831a4-0e20-4725-a6f5-3dc2f41f1cf4", +"operator": { +"type": "object", +"operation": "exists", +"singleValue": true +}, +"leftValue": "={{ $json.leadData }}", +"rightValue": "" +}, +{ +"id": "ccb46339-4e43-42e6-aa45-d5a0cbd62214", +"operator": { +"name": "filter.operator.equals", +"type": "string", +"operation": "equals" +}, +"leftValue": "", +"rightValue": "" +} +] +} +}, +"typeVersion": 2 +}, +{ +"id": "2221736f-ef99-4ac8-8a81-51af6d4e7dcd", +"name": "Edit Fields1", +"type": "n8n-nodes-base.set", +"position": [ +440, +960 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "19a16867-b574-4b99-82f1-a86752b7fe9f", +"name": "chatInput", +"type": "string", +"value": "=\"Hello, just so you can get to know me, with no intention of a response, please save this information in your memory. My name is {{ $json.leadData.name }}. I am {{ $json.leadData.age }} years old and currently live in {{ $json.leadData.city }}, {{ $json.leadData.state }}. My profession is {{ $json.leadData.profession }}, and my education level is {{ $json.leadData.educationLevel }}.\nIf I’m part of an adhesion group and have an entity, it would be {{ $json.leadData.entity }}.\n\nI am using a {{ $json.leadData.deviceType }} device to access this through the {{ $json.leadData.channel }} channel. At the moment, I am looking for a health insurance plan of type {{ $json.leadData.quotationType }}.\"" +}, +{ +"id": "0df8d578-8332-4cde-9044-489de16ab390", +"name": "session_id", +"type": "string", +"value": "={{ $json.session_id }}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "6aa1b3a4-0e6a-4312-9d9f-f67c4bf8f443", +"name": "Edit Fields2", +"type": "n8n-nodes-base.set", +"position": [ +920, +960 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "19a16867-b574-4b99-82f1-a86752b7fe9f", +"name": "chatInput", +"type": "string", +"value": "={{ $('Chat Trigger').item.json.chatInput}}" +}, +{ +"id": "0df8d578-8332-4cde-9044-489de16ab390", +"name": "session_id", +"type": "string", +"value": "={{ $('Chat Trigger').item.json.session_id }}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "6afe6158-7a8b-4a83-a778-6fd28e2a11af", +"name": "OpenAI", +"type": "@n8n/n8n-nodes-langchain.openAi", +"position": [ +600, +960 +], +"parameters": { +"options": {}, +"resource": "assistant", +"assistantId": { +"__rl": true, +"mode": "list", +"value": "asst_numdCoMZPQ6GwfiJg5drg9hr", +"cachedResultName": "Chat IA - Testes - Dezembro - APIS" +} +}, +"credentials": { +"openAiApi": { +"id": "FW1FWHcMcwemQ1kZ", +"name": "OpenAi account" +} +}, +"typeVersion": 1.4 +}, +{ +"id": "4b961f1d-7da2-4a0b-98e3-7ec35ee14335", +"name": "Chat Trigger", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +-20, +560 +], +"webhookId": "1f83e8ac-d465-454a-8327-cef7f0149cb1", +"parameters": { +"public": true, +"options": {}, +"initialMessages": "Olá 👋\nSou Jovelino, o serviço de IA do Joov, me mande sua pergunta e responderei em seguida! :)" +}, +"typeVersion": 1 +}, +{ +"id": "dccdb07f-97db-4a5a-9b09-02a5de65246e", +"name": "Postgres Chat Memory", +"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat", +"position": [ +640, +720 +], +"parameters": { +"tableName": "aimessages", +"sessionKey": "={{ $('Chat Trigger').item.json.session_id }}{{ $json.sessionId }}", +"sessionIdType": "customKey", +"contextWindowLength": 30 +}, +"credentials": { +"postgres": { +"id": "M1cYa0bOSX1nfczy", +"name": "Postgres account" +} +}, +"typeVersion": 1.3 +}, +{ +"id": "553dd27b-ab06-4605-99e0-8f15735cfff3", +"name": "Postgres Chat Memory1", +"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat", +"position": [ +760, +1160 +], +"parameters": { +"tableName": "aimessages", +"sessionKey": "={{ $('Chat Trigger').item.json.session_id }}{{ $json.sessionId }}", +"sessionIdType": "customKey", +"contextWindowLength": 1 +}, +"credentials": { +"postgres": { +"id": "M1cYa0bOSX1nfczy", +"name": "Postgres account" +} +}, +"typeVersion": 1.3 +}, +{ +"id": "0103fb97-c691-4bd3-b26d-85aaa9774594", +"name": "Products in Daatabase", +"type": "n8n-nodes-base.mySqlTool", +"position": [ +1460, +600 +], +"parameters": { +"query": "SELECT * \nFROM Products p \nWHERE \n cityQuery = '{{ $fromAI(\"cityQuery\") }}' AND \n state = '{{ $fromAI(\"state\") }}' AND \n modality = 'PME' AND \n removed = 0 AND \n ({{ $fromAI(\"holderCount\") || 1 }} + {{ $fromAI(\"dependentsCount\") || 0 }}) BETWEEN p.minLifeAmount AND p.maxLifeAmount AND\n (CASE\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 0 AND 18 THEN priceAtAge0To18\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 19 AND 23 THEN priceAtAge19To23\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 24 AND 28 THEN priceAtAge24To28\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 29 AND 33 THEN priceAtAge29To33\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 34 AND 38 THEN priceAtAge34To38\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 39 AND 43 THEN priceAtAge39To43\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 44 AND 48 THEN priceAtAge44To48\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 49 AND 53 THEN priceAtAge49To53\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 54 AND 58 THEN priceAtAge54To58\n ELSE priceAtAge59To199\n END) IS NOT NULL\nORDER BY \n (CASE\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 0 AND 18 THEN priceAtAge0To18\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 19 AND 23 THEN priceAtAge19To23\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 24 AND 28 THEN priceAtAge24To28\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 29 AND 33 THEN priceAtAge29To33\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 34 AND 38 THEN priceAtAge34To38\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 39 AND 43 THEN priceAtAge39To43\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 44 AND 48 THEN priceAtAge44To48\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 49 AND 53 THEN priceAtAge49To53\n WHEN {{ $fromAI(\"holderAge\") }} BETWEEN 54 AND 58 THEN priceAtAge54To58\n ELSE priceAtAge59To199\n END) ASC, \n createdAt DESC\nLIMIT 3;\n", +"options": { +"detailedOutput": true +}, +"operation": "executeQuery", +"descriptionType": "manual", +"toolDescription": "// Search for the X product bla bla bla" +}, +"credentials": { +"mySql": { +"id": "lkGJt8aNB0azyaGy", +"name": "MySQL account 2" +} +}, +"typeVersion": 2.4 +}, +{ +"id": "0cdfd89f-eb9e-4b6c-90d1-1cf8d6ed96bb", +"name": "Knowledge Base", +"type": "@n8n/n8n-nodes-langchain.toolHttpRequest", +"position": [ +1340, +600 +], +"parameters": { +"url": "https://quotation.joov.com.br/widget/info?modalidade={modalidade}&estado=SP&cidade={city}&operadora={operadora}", +"toolDescription": "Here you will find the knowlegde base of my shop and bla bla bla Use this when they ask for price, whatever i want." +}, +"typeVersion": 1.1 +}, +{ +"id": "393f792a-4eff-4b33-aac0-025fc622a4b3", +"name": "External API", +"type": "@n8n/n8n-nodes-langchain.toolHttpRequest", +"position": [ +1200, +600 +], +"parameters": { +"url": "https://integracao-sed-alb-323570099.us-east-1.elb.amazonaws.com/findByNameAndBirthDate", +"method": "POST", +"jsonBody": "={\n \"name\": \"{{json.name}}\",\n \"birthdate\": \"{{json.birthdate }}\"\n}", +"sendBody": true, +"specifyBody": "json", +"toolDescription": "Pegue o nome completo em camel case, exemplo: Fernanda Melo, e a data de nacimento nesse formato: 1990-03-28" +}, +"typeVersion": 1.1 +}, +{ +"id": "7ce7a5e7-6238-4479-a26f-bdcde1784188", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1160, +414 +], +"parameters": { +"color": 5, +"width": 436.73182569600795, +"height": 367.7413881276459, +"content": "TOOLS" +}, +"typeVersion": 1 +}, +{ +"id": "df6737ca-c588-48fc-9761-2a5307841298", +"name": "OpenAI2", +"type": "@n8n/n8n-nodes-langchain.openAi", +"position": [ +460, +460 +], +"parameters": { +"text": "={{ $json.chatInput }}", +"prompt": "define", +"options": {}, +"resource": "assistant", +"assistantId": { +"__rl": true, +"mode": "list", +"value": "asst_x2qfc7EuoPv7XGOL84ClEZ3L", +"cachedResultName": "PINE" +} +}, +"credentials": { +"openAiApi": { +"id": "FW1FWHcMcwemQ1kZ", +"name": "OpenAi account" +} +}, +"typeVersion": 1.4 +} +], +"active": false, +"pinData": {}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "d1dc3988-6677-47c9-b91a-6875c7b6151d", +"connections": { +"If": { +"main": [ +[ +{ +"node": "Edit Fields1", +"type": "main", +"index": 0 +} +], +[ +{ +"node": "OpenAI2", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI": { +"main": [ +[ +{ +"node": "Edit Fields2", +"type": "main", +"index": 0 +} +] +] +}, +"Chat Trigger": { +"main": [ +[ +{ +"node": "If", +"type": "main", +"index": 0 +} +] +] +}, +"Edit Fields1": { +"main": [ +[ +{ +"node": "OpenAI", +"type": "main", +"index": 0 +} +] +] +}, +"Edit Fields2": { +"main": [ +[ +{ +"node": "OpenAI2", +"type": "main", +"index": 0 +} +] +] +}, +"External API": { +"ai_tool": [ +[ +{ +"node": "OpenAI2", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Knowledge Base": { +"ai_tool": [ +[ +{ +"node": "OpenAI2", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Postgres Chat Memory": { +"ai_memory": [ +[ +{ +"node": "OpenAI2", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"Postgres Chat Memory1": { +"ai_memory": [ +[ +{ +"node": "OpenAI", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"Products in Daatabase": { +"ai_tool": [ +[ +{ +"node": "OpenAI2", +"type": "ai_tool", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with GitHub API Documentation_ RAG-Powered Chatbot with Pinecone & OpenAI.txt b/Chat with GitHub API Documentation_ RAG-Powered Chatbot with Pinecone & OpenAI.txt new file mode 100644 index 0000000..47aa04d --- /dev/null +++ b/Chat with GitHub API Documentation_ RAG-Powered Chatbot with Pinecone & OpenAI.txt @@ -0,0 +1,426 @@ +{ +"id": "FD0bHNaehP3LzCNN", +"meta": { +"instanceId": "69133932b9ba8e1ef14816d0b63297bb44feb97c19f759b5d153ff6b0c59e18d" +}, +"name": "Chat with GitHub OpenAPI Specification using RAG (Pinecone and OpenAI)", +"tags": [], +"nodes": [ +{ +"id": "362cb773-7540-4753-a401-e585cdf4af8a", +"name": "When clicking ‘Test workflow’", +"type": "n8n-nodes-base.manualTrigger", +"position": [ +0, +0 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "45470036-cae6-48d0-ac66-addc8999e776", +"name": "HTTP Request", +"type": "n8n-nodes-base.httpRequest", +"position": [ +300, +0 +], +"parameters": { +"url": "https://raw.githubusercontent.com/github/rest-api-description/refs/heads/main/descriptions/api.github.com/api.github.com.json", +"options": {} +}, +"typeVersion": 4.2 +}, +{ +"id": "a9e65897-52c9-4941-bf49-e1a659e442ef", +"name": "Pinecone Vector Store", +"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone", +"position": [ +520, +0 +], +"parameters": { +"mode": "insert", +"options": {}, +"pineconeIndex": { +"__rl": true, +"mode": "list", +"value": "n8n-demo", +"cachedResultName": "n8n-demo" +} +}, +"credentials": { +"pineconeApi": { +"id": "bQTNry52ypGLqt47", +"name": "PineconeApi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "c2a2354b-5457-4ceb-abfc-9a58e8593b81", +"name": "Default Data Loader", +"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", +"position": [ +660, +180 +], +"parameters": { +"options": {} +}, +"typeVersion": 1 +}, +{ +"id": "7338d9ea-ae8f-46eb-807f-a15dc7639fc9", +"name": "Recursive Character Text Splitter", +"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", +"position": [ +740, +360 +], +"parameters": { +"options": {} +}, +"typeVersion": 1 +}, +{ +"id": "44fd7a59-f208-4d5d-a22d-e9f8ca9badf1", +"name": "When chat message received", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +-20, +760 +], +"webhookId": "089e38ab-4eee-4c34-aa5d-54cf4a8f53b7", +"parameters": { +"options": {} +}, +"typeVersion": 1.1 +}, +{ +"id": "51d819d6-70ff-428d-aa56-1d7e06490dee", +"name": "AI Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +320, +760 +], +"parameters": { +"options": { +"systemMessage": "You are a helpful assistant providing information about the GitHub API and how to use it based on the OpenAPI V3 specifications." +} +}, +"typeVersion": 1.7 +}, +{ +"id": "aed548bf-7083-44ad-a3e0-163dee7423ef", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +220, +980 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "tQLWnWRzD8aebYvp", +"name": "OpenAi account" +} +}, +"typeVersion": 1.1 +}, +{ +"id": "dfe9f356-2225-4f4b-86c7-e56a230b4193", +"name": "Window Buffer Memory", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +420, +1020 +], +"parameters": {}, +"typeVersion": 1.3 +}, +{ +"id": "4cf672ee-13b8-4355-b8e0-c2e7381671bc", +"name": "Vector Store Tool", +"type": "@n8n/n8n-nodes-langchain.toolVectorStore", +"position": [ +580, +980 +], +"parameters": { +"name": "GitHub_OpenAPI_Specification", +"description": "Use this tool to get information about the GitHub API. This database contains OpenAPI v3 specifications." +}, +"typeVersion": 1 +}, +{ +"id": "1df7fb85-9d4a-4db5-9bed-41d28e2e4643", +"name": "OpenAI Chat Model1", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +840, +1160 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "tQLWnWRzD8aebYvp", +"name": "OpenAi account" +} +}, +"typeVersion": 1.1 +}, +{ +"id": "7b52ef7a-5935-451e-8747-efe16ce288af", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-40, +-260 +], +"parameters": { +"width": 640, +"height": 200, +"content": "## Indexing content in the vector database\nThis part of the workflow is responsible for extracting content, generating embeddings and sending them to the Pinecone vector store.\n\nIt requests the OpenAPI specifications from GitHub using a HTTP request. Then, it splits the file in chunks, generating embeddings for each chunk using OpenAI, and saving them in Pinecone vector DB." +}, +"typeVersion": 1 +}, +{ +"id": "3508d602-56d4-4818-84eb-ca75cdeec1d0", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-20, +560 +], +"parameters": { +"width": 580, +"content": "## Querying and response generation \n\nThis part of the workflow is responsible for the chat interface, querying the vector store and generating relevant responses.\n\nIt uses OpenAI GPT 4o-mini to generate responses." +}, +"typeVersion": 1 +}, +{ +"id": "5a9808ef-4edd-4ec9-ba01-2fe50b2dbf4b", +"name": "Generate User Query Embedding", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +480, +1400 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "tQLWnWRzD8aebYvp", +"name": "OpenAi account" +} +}, +"typeVersion": 1.2 +}, +{ +"id": "f703dc8e-9d4b-45e3-8994-789b3dfe8631", +"name": "Pinecone Vector Store (Querying)", +"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone", +"position": [ +440, +1220 +], +"parameters": { +"options": {}, +"pineconeIndex": { +"__rl": true, +"mode": "list", +"value": "n8n-demo", +"cachedResultName": "n8n-demo" +} +}, +"credentials": { +"pineconeApi": { +"id": "bQTNry52ypGLqt47", +"name": "PineconeApi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "ea64a7a5-1fa5-4938-83a9-271929733a8e", +"name": "Generate Embeddings", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +480, +220 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "tQLWnWRzD8aebYvp", +"name": "OpenAi account" +} +}, +"typeVersion": 1.2 +}, +{ +"id": "65cbd4e3-91f6-441a-9ef1-528c3019e238", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-820, +-260 +], +"parameters": { +"width": 620, +"height": 320, +"content": "## RAG workflow in n8n\n\nThis is an example of how to use RAG techniques to create a chatbot with n8n. It is an API documentation chatbot that can answer questions about the GitHub API. It uses OpenAI for generating embeddings, the gpt-4o-mini LLM for generating responses and Pinecone as a vector database.\n\n### Before using this template\n* create OpenAI and Pinecone accounts\n* obtain API keys OpenAI and Pinecone \n* configure credentials in n8n for both\n* ensure you have a Pinecone index named \"n8n-demo\" or adjust the workflow accordingly." +}, +"typeVersion": 1 +} +], +"active": false, +"pinData": {}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "2908105f-c20c-4183-bb9d-26e3559b9911", +"connections": { +"HTTP Request": { +"main": [ +[ +{ +"node": "Pinecone Vector Store", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Vector Store Tool": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"OpenAI Chat Model1": { +"ai_languageModel": [ +[ +{ +"node": "Vector Store Tool", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Default Data Loader": { +"ai_document": [ +[ +{ +"node": "Pinecone Vector Store", +"type": "ai_document", +"index": 0 +} +] +] +}, +"Generate Embeddings": { +"ai_embedding": [ +[ +{ +"node": "Pinecone Vector Store", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"Window Buffer Memory": { +"ai_memory": [ +[ +{ +"node": "AI Agent", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"When chat message received": { +"main": [ +[ +{ +"node": "AI Agent", +"type": "main", +"index": 0 +} +] +] +}, +"Generate User Query Embedding": { +"ai_embedding": [ +[ +{ +"node": "Pinecone Vector Store (Querying)", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"Pinecone Vector Store (Querying)": { +"ai_vectorStore": [ +[ +{ +"node": "Vector Store Tool", +"type": "ai_vectorStore", +"index": 0 +} +] +] +}, +"Recursive Character Text Splitter": { +"ai_textSplitter": [ +[ +{ +"node": "Default Data Loader", +"type": "ai_textSplitter", +"index": 0 +} +] +] +}, +"When clicking ‘Test workflow’": { +"main": [ +[ +{ +"node": "HTTP Request", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with OpenAI Assistant (by adding a memory).txt b/Chat with OpenAI Assistant (by adding a memory).txt new file mode 100644 index 0000000..dbebc3c --- /dev/null +++ b/Chat with OpenAI Assistant (by adding a memory).txt @@ -0,0 +1,335 @@ +{ +"meta": { +"instanceId": "cb484ba7b742928a2048bf8829668bed5b5ad9787579adea888f05980292a4a7" +}, +"nodes": [ +{ +"id": "087ae6e2-b333-4a30-9010-c78050203961", +"name": "OpenAI Assistant", +"type": "@n8n/n8n-nodes-langchain.openAiAssistant", +"position": [ +1340, +460 +], +"parameters": { +"text": "=## Our Previous Conversation:\n{{ $json[\"messages\"].map(m => `\nHuman: ${m.human}\nAI Assistant: ${m.ai}\n`) }}\n## Current message:\n{{ $('Chat Trigger').item.json.chatInput }}", +"options": {}, +"assistantId": "asst_HDSAnzsp4WqY4UC1iI9auH5z" +}, +"credentials": { +"openAiApi": { +"id": "VQtv7frm7eLiEDnd", +"name": "OpenAi account 7" +} +}, +"typeVersion": 1 +}, +{ +"id": "3793b10a-ebb7-42ec-8b9b-7fa3a353d9a3", +"name": "Calculator", +"type": "@n8n/n8n-nodes-langchain.toolCalculator", +"position": [ +1500, +640 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "7bee2882-bb9e-402e-ba42-9b1ed0e1264b", +"name": "Chat Memory Manager", +"type": "@n8n/n8n-nodes-langchain.memoryManager", +"position": [ +760, +460 +], +"parameters": {}, +"typeVersion": 1, +"alwaysOutputData": true +}, +{ +"id": "5c66e482-819e-47e7-90be-779e92364e2a", +"name": "Chat Memory Manager1", +"type": "@n8n/n8n-nodes-langchain.memoryManager", +"position": [ +1720, +460 +], +"parameters": { +"mode": "insert", +"messages": { +"messageValues": [ +{ +"type": "user", +"message": "={{ $('Chat Trigger').item.json.chatInput }}" +}, +{ +"type": "ai", +"message": "={{ $json.output }}" +} +] +} +}, +"typeVersion": 1, +"alwaysOutputData": true +}, +{ +"id": "b96bf629-bd21-4528-8988-e63c5af89fd7", +"name": "Aggregate", +"type": "n8n-nodes-base.aggregate", +"position": [ +1140, +460 +], +"parameters": { +"options": {}, +"aggregate": "aggregateAllItemData", +"destinationFieldName": "messages" +}, +"typeVersion": 1, +"alwaysOutputData": true +}, +{ +"id": "95001be1-f046-47e3-a58c-25bff170ba06", +"name": "Edit Fields", +"type": "n8n-nodes-base.set", +"position": [ +2320, +460 +], +"parameters": { +"fields": { +"values": [ +{ +"name": "output", +"stringValue": "={{ $('OpenAI Assistant').item.json.output }}" +} +] +}, +"options": {} +}, +"typeVersion": 3.2 +}, +{ +"id": "4ea04793-c7fb-4b81-abf7-49590aa76ca7", +"name": "Limit", +"type": "n8n-nodes-base.limit", +"position": [ +2100, +460 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "16921f74-d420-445a-9e09-19a6116a3267", +"name": "Chat Trigger", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +460, +460 +], +"webhookId": "1f83e8ac-d465-454a-8327-cef7f0149cb1", +"parameters": { +"public": true, +"options": { +"loadPreviousSession": "memory" +} +}, +"typeVersion": 1 +}, +{ +"id": "c0826494-779a-4c2d-93c9-746150ac9482", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +740, +400 +], +"parameters": { +"color": 7, +"width": 514.8706020514577, +"height": 196.64941360686112, +"content": "Read contents of the chat from memory" +}, +"typeVersion": 1 +}, +{ +"id": "4ce4594d-070a-4985-9c5d-fcd4ebc4a627", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1320, +400 +], +"parameters": { +"color": 7, +"width": 298.02823821086326, +"height": 196.64941360686112, +"content": "Call the assistant, passing in the previous chat messages" +}, +"typeVersion": 1 +}, +{ +"id": "49885b3b-de77-4c02-a35e-d188fee38831", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1700, +400 +], +"parameters": { +"color": 7, +"width": 298.02823821086326, +"height": 196.64941360686112, +"content": "Add the latest chat messages to the memory" +}, +"typeVersion": 1 +}, +{ +"id": "f45e8589-d61b-440a-ae89-31ded2738ef7", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +2080, +400 +], +"parameters": { +"color": 7, +"width": 356.0564764217267, +"height": 196.64941360686112, +"content": "Return the model output" +}, +"typeVersion": 1 +}, +{ +"id": "3b72a676-aaa2-472a-b055-1fed03f52101", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +360, +640 +], +"parameters": { +"height": 300.48941882630095, +"content": "## Try me out\n1. In the OpenAI Assistant node, make sure your OpenAI credentials are set and choose an assistant to use (you'll need to create one if you don't have one already)\n2. Click the 'Chat' button below\n\n - In the first message, tell the AI what your name is\n - In a second message, ask the AI what your name is" +}, +"typeVersion": 1 +}, +{ +"id": "a2250328-e4ce-4ac6-b4fe-658ab173bc28", +"name": "Window Buffer Memory", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +1280, +880 +], +"parameters": { +"sessionKey": "={{ $('Chat Trigger').item.json.sessionId }}123", +"contextWindowLength": 20 +}, +"typeVersion": 1.1 +} +], +"pinData": {}, +"connections": { +"Limit": { +"main": [ +[ +{ +"node": "Edit Fields", +"type": "main", +"index": 0 +} +] +] +}, +"Aggregate": { +"main": [ +[ +{ +"node": "OpenAI Assistant", +"type": "main", +"index": 0 +} +] +] +}, +"Calculator": { +"ai_tool": [ +[ +{ +"node": "OpenAI Assistant", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Chat Trigger": { +"main": [ +[ +{ +"node": "Chat Memory Manager", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Assistant": { +"main": [ +[ +{ +"node": "Chat Memory Manager1", +"type": "main", +"index": 0 +} +] +] +}, +"Chat Memory Manager": { +"main": [ +[ +{ +"node": "Aggregate", +"type": "main", +"index": 0 +} +] +] +}, +"Chat Memory Manager1": { +"main": [ +[ +{ +"node": "Limit", +"type": "main", +"index": 0 +} +] +] +}, +"Window Buffer Memory": { +"ai_memory": [ +[ +{ +"node": "Chat Trigger", +"type": "ai_memory", +"index": 0 +}, +{ +"node": "Chat Memory Manager", +"type": "ai_memory", +"index": 0 +}, +{ +"node": "Chat Memory Manager1", +"type": "ai_memory", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with OpenAIs GPT via a simple Telegram Bot.txt b/Chat with OpenAIs GPT via a simple Telegram Bot.txt new file mode 100644 index 0000000..01c1dfb --- /dev/null +++ b/Chat with OpenAIs GPT via a simple Telegram Bot.txt @@ -0,0 +1,122 @@ +{ +"meta": { +"instanceId": "014363851c6b81282e1489df62d7f66bb7c99af5dcb6c1032b3a83a1d72baee4" +}, +"nodes": [ +{ +"id": "0b4eb8e4-e98b-4f67-b134-914a5aa46b4d", +"name": "Telegram Trigger", +"type": "n8n-nodes-base.telegramTrigger", +"position": [ +960, +400 +], +"webhookId": "9c8b833c-7aa7-430d-8fc0-47936f695ddf", +"parameters": { +"updates": [ +"message" +], +"additionalFields": {} +}, +"credentials": { +"telegramApi": { +"id": "4lzd2F9cNrnR7j0j", +"name": "Telegram account" +} +}, +"typeVersion": 1.1 +}, +{ +"id": "339246f2-76cb-44c4-8828-da0cb5d3ad5e", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +1100, +600 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "m3YyjGXFLLWwcnk7", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "70a981e2-7833-473b-a27a-fedf860901cb", +"name": "AI Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +1200, +400 +], +"parameters": { +"text": "=Respond to this as a helpful assistant with emojis: {{ $json.message.text }}", +"options": {} +}, +"typeVersion": 1.2 +}, +{ +"id": "fb6ff65b-56b4-44c4-978a-b9a5c3d535d6", +"name": "Telegram", +"type": "n8n-nodes-base.telegram", +"position": [ +1560, +400 +], +"parameters": { +"text": "={{ $json.output }}", +"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}", +"additionalFields": { +"appendAttribution": false +} +}, +"credentials": { +"telegramApi": { +"id": "4lzd2F9cNrnR7j0j", +"name": "Telegram account" +} +}, +"typeVersion": 1.1 +} +], +"pinData": {}, +"connections": { +"AI Agent": { +"main": [ +[ +{ +"node": "Telegram", +"type": "main", +"index": 0 +} +] +] +}, +"Telegram Trigger": { +"main": [ +[ +{ +"node": "AI Agent", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with PDF docs using AI (quoting sources).txt b/Chat with PDF docs using AI (quoting sources).txt new file mode 100644 index 0000000..b51f002 --- /dev/null +++ b/Chat with PDF docs using AI (quoting sources).txt @@ -0,0 +1,598 @@ +{ +"meta": { +"instanceId": "cb484ba7b742928a2048bf8829668bed5b5ad9787579adea888f05980292a4a7", +"templateId": "1960" +}, +"nodes": [ +{ +"id": "296a935f-bd02-44bc-9e1e-3e4d6a307e38", +"name": "When clicking \"Execute Workflow\"", +"type": "n8n-nodes-base.manualTrigger", +"position": [ +260, +240 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "61a38c00-f196-4b01-9274-c5e0f4c511bc", +"name": "Embeddings OpenAI", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +1060, +460 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "VQtv7frm7eLiEDnd", +"name": "OpenAi account 7" +} +}, +"typeVersion": 1 +}, +{ +"id": "816066bd-02e8-4de2-bcee-ab81d890435a", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +426.9261940355327, +60.389291053299075 +], +"parameters": { +"color": 7, +"width": 1086.039382705461, +"height": 728.4168721167887, +"content": "## 1. Setup: Fetch file from Google Drive, split it into chunks and insert into a vector database\nNote that running this part multiple times will insert multiple copies into your DB" +}, +"typeVersion": 1 +}, +{ +"id": "30cd81ad-d658-4c33-9a38-68e33b74cdae", +"name": "Default Data Loader", +"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", +"position": [ +1240, +460 +], +"parameters": { +"options": { +"metadata": { +"metadataValues": [ +{ +"name": "file_url", +"value": "={{ $json.file_url }}" +}, +{ +"name": "file_name", +"value": "={{ $('Add in metadata').item.json.file_name }}" +} +] +} +}, +"dataType": "binary" +}, +"typeVersion": 1 +}, +{ +"id": "718f09e0-67be-41a6-a90d-f58e64ffee4d", +"name": "Set file URL in Google Drive", +"type": "n8n-nodes-base.set", +"position": [ +480, +240 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "50025ff5-1b53-475f-b150-2aafef1c4c21", +"name": "file_url", +"type": "string", +"value": " https://drive.google.com/file/d/11Koq9q53nkk0F5Y8eZgaWJUVR03I4-MM/view" +} +] +} +}, +"typeVersion": 3.3 +}, +{ +"id": "8f536a96-a6b1-4291-9cac-765759c396a8", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-40, +140 +], +"parameters": { +"height": 350.7942096493649, +"content": "# Try me out\n1. In Pinecone, create an index with 1536 dimensions and select it in the two vector store nodes\n2. Populate Pinecone by clicking the 'test workflow' button below\n3. Click the 'chat' button below and enter the following:\n\n_Which email provider does the creator of Bitcoin use?_" +}, +"typeVersion": 1 +}, +{ +"id": "ec7c9407-93c3-47a6-90f2-6e6056f5af84", +"name": "Add in metadata", +"type": "n8n-nodes-base.code", +"position": [ +900, +240 +], +"parameters": { +"mode": "runOnceForEachItem", +"jsCode": "// Add a new field called 'myNewField' to the JSON of the item\n$input.item.json.file_name = $input.item.binary.data.fileName;\n$input.item.json.file_ext = $input.item.binary.data.fileExtension;\n$input.item.json.file_url = $('Set file URL in Google Drive').item.json.file_url\n\nreturn $input.item;" +}, +"typeVersion": 2 +}, +{ +"id": "ab3131d5-4b04-48b4-b5d5-787e3ed18917", +"name": "Download file", +"type": "n8n-nodes-base.googleDrive", +"position": [ +680, +240 +], +"parameters": { +"fileId": { +"__rl": true, +"mode": "url", +"value": "={{ $json.file_url }}" +}, +"options": {}, +"operation": "download" +}, +"credentials": { +"googleDriveOAuth2Api": { +"id": "176", +"name": "Google Drive account (David)" +} +}, +"typeVersion": 3 +}, +{ +"id": "764a865c-7efe-4eec-a34c-cc87c5f085b1", +"name": "Chat Trigger", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +260, +960 +], +"webhookId": "1727c687-aed0-49cf-96af-e7796819fbb3", +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "36cd9a8d-7d89-49b3-8a81-baa278201a21", +"name": "Prepare chunks", +"type": "n8n-nodes-base.code", +"position": [ +1080, +960 +], +"parameters": { +"jsCode": "let out = \"\"\nfor (const i in $input.all()) {\n let itemText = \"--- CHUNK \" + i + \" ---\\n\"\n itemText += $input.all()[i].json.document.pageContent + \"\\n\"\n itemText += \"\\n\"\n out += itemText\n}\n\nreturn {\n 'context': out\n};" +}, +"typeVersion": 2 +}, +{ +"id": "6356bce2-9aae-43ed-97ce-a27cbfb80df9", +"name": "Embeddings OpenAI2", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +700, +1180 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "VQtv7frm7eLiEDnd", +"name": "OpenAi account 7" +} +}, +"typeVersion": 1 +}, +{ +"id": "8fb697ea-f2e5-4105-b6c8-ab869c2e5ab2", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +1320, +1180 +], +"parameters": { +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "VQtv7frm7eLiEDnd", +"name": "OpenAi account 7" +} +}, +"typeVersion": 1 +}, +{ +"id": "9a2b0152-d008-42cb-bc10-495135d5ef45", +"name": "Set max chunks to send to model", +"type": "n8n-nodes-base.set", +"position": [ +480, +960 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "236047ff-75a2-47fd-b338-1e9763c4015e", +"name": "chunks", +"type": "number", +"value": 4 +} +] +}, +"includeOtherFields": true +}, +"typeVersion": 3.3 +}, +{ +"id": "f2ab813f-0f0c-4d3a-a1de-7896ad736698", +"name": "Structured Output Parser", +"type": "@n8n/n8n-nodes-langchain.outputParserStructured", +"position": [ +1500, +1180 +], +"parameters": { +"jsonSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"answer\": {\n \"type\": \"string\"\n },\n \"citations\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"number\"\n }\n }\n }\n}" +}, +"typeVersion": 1 +}, +{ +"id": "ada2a38b-0f6e-4115-97c0-000e97a5e62e", +"name": "Compose citations", +"type": "n8n-nodes-base.set", +"position": [ +1680, +960 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "67ecefcf-a30c-4cc4-89ca-b9b23edd6585", +"name": "citations", +"type": "array", +"value": "={{ $json.citations.map(i => '[' + $('Get top chunks matching query').all()[$json.citations].json.document.metadata.file_name + ', lines ' + $('Get top chunks matching query').all()[$json.citations].json.document.metadata['loc.lines.from'] + '-' + $('Get top chunks matching query').all()[$json.citations].json.document.metadata['loc.lines.to'] + ']') }}" +} +] +}, +"includeOtherFields": true +}, +"typeVersion": 3.3 +}, +{ +"id": "8e115308-532e-4afd-b766-78e54c861f33", +"name": "Generate response", +"type": "n8n-nodes-base.set", +"position": [ +1900, +960 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "d77956c4-0ff4-4c64-80c2-9da9d4c8ad34", +"name": "text", +"type": "string", +"value": "={{ $json.answer }} {{ $if(!$json.citations.isEmpty(), \"\\n\" + $json.citations.join(\"\"), '') }}" +} +] +} +}, +"typeVersion": 3.3 +}, +{ +"id": "40c5f9d8-38da-41ac-ab99-98f6010ba8bf", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +428.71587064297796, +840 +], +"parameters": { +"color": 7, +"width": 1693.989843925635, +"height": 548.5086735412393, +"content": "## 2. Chat with file, getting citations in reponse" +}, +"typeVersion": 1 +}, +{ +"id": "ef357a2b-bc8d-43f7-982f-73c3a85a60be", +"name": "Answer the query based on chunks", +"type": "@n8n/n8n-nodes-langchain.chainLlm", +"position": [ +1300, +960 +], +"parameters": { +"text": "=Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. Important: In your response, also include the the indexes of the chunks you used to generate the answer.\n\n{{ $json.context }}\n\nQuestion: {{ $(\"Chat Trigger\").first().json.chatInput }}\nHelpful Answer:", +"promptType": "define", +"hasOutputParser": true +}, +"typeVersion": 1.4 +}, +{ +"id": "cbb1b60c-b396-4f0e-8dc6-dfa41dbb178e", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +442.5682587140436, +150.50554725042372 +], +"parameters": { +"color": 7, +"width": 179.58883583572606, +"height": 257.75985739596473, +"content": "Will fetch the Bitcoin whitepaper, but you can change this" +}, +"typeVersion": 1 +}, +{ +"id": "1a5511b9-5a24-40d5-a5b1-830376226e4e", +"name": "Get top chunks matching query", +"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone", +"position": [ +700, +960 +], +"parameters": { +"mode": "load", +"topK": "={{ $json.chunks }}", +"prompt": "={{ $json.chatInput }}", +"options": {}, +"pineconeIndex": { +"__rl": true, +"mode": "list", +"value": "test-index", +"cachedResultName": "test-index" +} +}, +"credentials": { +"pineconeApi": { +"id": "eDN8BmzFKMhUNsia", +"name": "PineconeApi account (David)" +} +}, +"typeVersion": 1 +}, +{ +"id": "d8d210cf-f12e-4e82-9b28-f531d2ff14a6", +"name": "Add to Pinecone vector store", +"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone", +"position": [ +1120, +240 +], +"parameters": { +"mode": "insert", +"options": {}, +"pineconeIndex": { +"__rl": true, +"mode": "list", +"value": "test-index", +"cachedResultName": "test-index" +} +}, +"credentials": { +"pineconeApi": { +"id": "eDN8BmzFKMhUNsia", +"name": "PineconeApi account (David)" +} +}, +"typeVersion": 1 +}, +{ +"id": "c501568b-fb49-487d-bced-757e3d7ed13c", +"name": "Recursive Character Text Splitter", +"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", +"position": [ +1240, +620 +], +"parameters": { +"chunkSize": 3000, +"chunkOverlap": 200 +}, +"typeVersion": 1 +} +], +"pinData": {}, +"connections": { +"Chat Trigger": { +"main": [ +[ +{ +"node": "Set max chunks to send to model", +"type": "main", +"index": 0 +} +] +] +}, +"Download file": { +"main": [ +[ +{ +"node": "Add in metadata", +"type": "main", +"index": 0 +} +] +] +}, +"Prepare chunks": { +"main": [ +[ +{ +"node": "Answer the query based on chunks", +"type": "main", +"index": 0 +} +] +] +}, +"Add in metadata": { +"main": [ +[ +{ +"node": "Add to Pinecone vector store", +"type": "main", +"index": 0 +} +] +] +}, +"Compose citations": { +"main": [ +[ +{ +"node": "Generate response", +"type": "main", +"index": 0 +} +] +] +}, +"Embeddings OpenAI": { +"ai_embedding": [ +[ +{ +"node": "Add to Pinecone vector store", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "Answer the query based on chunks", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Embeddings OpenAI2": { +"ai_embedding": [ +[ +{ +"node": "Get top chunks matching query", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"Default Data Loader": { +"ai_document": [ +[ +{ +"node": "Add to Pinecone vector store", +"type": "ai_document", +"index": 0 +} +] +] +}, +"Structured Output Parser": { +"ai_outputParser": [ +[ +{ +"node": "Answer the query based on chunks", +"type": "ai_outputParser", +"index": 0 +} +] +] +}, +"Set file URL in Google Drive": { +"main": [ +[ +{ +"node": "Download file", +"type": "main", +"index": 0 +} +] +] +}, +"Get top chunks matching query": { +"main": [ +[ +{ +"node": "Prepare chunks", +"type": "main", +"index": 0 +} +] +] +}, +"Set max chunks to send to model": { +"main": [ +[ +{ +"node": "Get top chunks matching query", +"type": "main", +"index": 0 +} +] +] +}, +"Answer the query based on chunks": { +"main": [ +[ +{ +"node": "Compose citations", +"type": "main", +"index": 0 +} +] +] +}, +"When clicking \"Execute Workflow\"": { +"main": [ +[ +{ +"node": "Set file URL in Google Drive", +"type": "main", +"index": 0 +} +] +] +}, +"Recursive Character Text Splitter": { +"ai_textSplitter": [ +[ +{ +"node": "Default Data Loader", +"type": "ai_textSplitter", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with Postgresql Database.txt b/Chat with Postgresql Database.txt new file mode 100644 index 0000000..a5bde80 --- /dev/null +++ b/Chat with Postgresql Database.txt @@ -0,0 +1,283 @@ +{ +"id": "eOUewYsEzJmQixI6", +"meta": { +"instanceId": "77c4feba8f41570ef06dc76ece9a6ded0f0d44f7f1477a64c2d71a8508c11faa", +"templateCredsSetupCompleted": true +}, +"name": "Chat with Postgresql Database", +"tags": [], +"nodes": [ +{ +"id": "6501a54f-a68c-452d-b353-d7e871ca3780", +"name": "When chat message received", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +-300, +-80 +], +"webhookId": "cf1de04f-3e38-426c-89f0-3bdb110a5dcf", +"parameters": { +"options": {} +}, +"typeVersion": 1.1 +}, +{ +"id": "cd32221b-2a36-408d-b57e-8115fcd810c9", +"name": "AI Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +0, +-80 +], +"parameters": { +"agent": "openAiFunctionsAgent", +"options": { +"systemMessage": "You are DB assistant. You need to run queries in DB aligned with user requests.\n\nRun custom SQL query to aggregate data and response to user. Make sure every table has schema prefix to it in sql query which you can get from `Get DB Schema and Tables List` tool.\n\nFetch all data to analyse it for response if needed.\n\n## Tools\n\n- Execute SQL query - Executes any sql query generated by AI\n- Get DB Schema and Tables List - Lists all the tables in database with its schema name\n- Get Table Definition - Gets the table definition from db using table name and schema name" +} +}, +"typeVersion": 1.7 +}, +{ +"id": "8accbeeb-7eaf-4e9e-aabc-de8ab3a0459b", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +-60, +160 +], +"parameters": { +"model": { +"__rl": true, +"mode": "list", +"value": "gpt-4o-mini" +}, +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "48uG61Ilo8jndw3r", +"name": "Your OpenAI Account Credentials" +} +}, +"typeVersion": 1.2 +}, +{ +"id": "11f2013f-a080-4c9e-8773-c90492e2c628", +"name": "Get Table Definition", +"type": "n8n-nodes-base.postgresTool", +"position": [ +780, +140 +], +"parameters": { +"query": "select\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n tc.constraint_type,\n ccu.table_name AS referenced_table,\n ccu.column_name AS referenced_column\nfrom\n information_schema.columns c\nLEFT join\n information_schema.key_column_usage kcu\n ON c.table_name = kcu.table_name\n AND c.column_name = kcu.column_name\nLEFT join\n information_schema.table_constraints tc\n ON kcu.constraint_name = tc.constraint_name\n AND tc.constraint_type = 'FOREIGN KEY'\nLEFT join\n information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\nwhere\n c.table_name = '{{ $fromAI(\"table_name\") }}'\n AND c.table_schema = '{{ $fromAI(\"schema_name\") }}'\norder by\n c.ordinal_position", +"options": {}, +"operation": "executeQuery", +"descriptionType": "manual", +"toolDescription": "Get table definition to find all columns and types" +}, +"credentials": { +"postgres": { +"id": "nGI61D0TEEZz18rr", +"name": "Your Postgresql Database Credentials" +} +}, +"typeVersion": 2.5 +}, +{ +"id": "760bc9bc-0057-4088-b3f0-3ee37b3519df", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-300, +-240 +], +"parameters": { +"color": 5, +"width": 560, +"height": 120, +"content": "### 👨‍🎤 Setup\n1. Add your **postgresql** and **OpenAI** credentials.\n2. Click **Chat** button and start asking questions to your database.\n3. Activate the workflow and you can make the chat publicly available." +}, +"typeVersion": 1 +}, +{ +"id": "0df33341-c859-4a54-b6d9-a99670e8d76d", +"name": "Chat History", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +120, +160 +], +"parameters": {}, +"typeVersion": 1.3 +}, +{ +"id": "4938b22e-f187-4ca0-b9f1-60835e823799", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +360, +300 +], +"parameters": { +"color": 7, +"width": 562, +"height": 156, +"content": "🛠️ Tools Used:\n1. Execute SQL Query: Used to execute any query generated by the agent.\n2. Get DB Schema and Tables List: It returns the list of all the tables with its schema name.\n3. Get Table Definition: It returns table details like column names, foreign keys and more of a particular table in a schema." +}, +"typeVersion": 1 +}, +{ +"id": "39780c78-4fbc-403e-a220-aa6a4b06df8c", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-100, +300 +], +"parameters": { +"color": 7, +"width": 162, +"height": 99, +"content": "👆 You can exchange this with any other chat model of your choice." +}, +"typeVersion": 1 +}, +{ +"id": "28a5692c-5003-46cb-9a09-b7867734f446", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +100, +300 +], +"parameters": { +"color": 7, +"width": 162, +"height": 159, +"content": "👆 You can change how many number of messages to keep using `Context Window Length` option. It's 5 by default." +}, +"typeVersion": 1 +}, +{ +"id": "c18ced71-6330-4ba0-9c52-1bb5852b3039", +"name": "Execute SQL Query", +"type": "n8n-nodes-base.postgresTool", +"position": [ +380, +140 +], +"parameters": { +"query": "{{ $fromAI(\"sql_query\", \"SQL Query\") }}", +"options": {}, +"operation": "executeQuery", +"descriptionType": "manual", +"toolDescription": "Get all the data from Postgres, make sure you append the tables with correct schema. Every table is associated with some schema in the database." +}, +"credentials": { +"postgres": { +"id": "nGI61D0TEEZz18rr", +"name": "Your Postgresql Database Credentials" +} +}, +"typeVersion": 2.5 +}, +{ +"id": "557623c6-e499-48a6-a066-744f64f8b6f3", +"name": "Get DB Schema and Tables List", +"type": "n8n-nodes-base.postgresTool", +"position": [ +580, +140 +], +"parameters": { +"query": "SELECT \n table_schema,\n table_name\nFROM information_schema.tables\nWHERE table_type = 'BASE TABLE'\n AND table_schema NOT IN ('pg_catalog', 'information_schema')\nORDER BY table_schema, table_name;", +"options": {}, +"operation": "executeQuery", +"descriptionType": "manual", +"toolDescription": "Get list of all tables with their schema in the database" +}, +"credentials": { +"postgres": { +"id": "nGI61D0TEEZz18rr", +"name": "Your Postgresql Database Credentials" +} +}, +"typeVersion": 2.5 +} +], +"active": false, +"pinData": {}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "10c7c74e-b383-4ac7-8cb2-c9a15a2818fe", +"connections": { +"Chat History": { +"ai_memory": [ +[ +{ +"node": "AI Agent", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"Execute SQL Query": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Get Table Definition": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"When chat message received": { +"main": [ +[ +{ +"node": "AI Agent", +"type": "main", +"index": 0 +} +] +] +}, +"Get DB Schema and Tables List": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with a Google Sheet using AI.txt b/Chat with a Google Sheet using AI.txt new file mode 100644 index 0000000..c09bd37 --- /dev/null +++ b/Chat with a Google Sheet using AI.txt @@ -0,0 +1,616 @@ +{ +"id": "ZVUQL1bUQ8gBCZTl", +"meta": { +"instanceId": "23e6ce638471979c8a2c72a9fb50e44f4f2bfd5a9fc2f5b7f5c842b9abeb9393" +}, +"name": "Chat with Google Sheet", +"tags": [], +"nodes": [ +{ +"id": "89af21df-1125-4df6-9d43-a643e02bb53f", +"name": "Execute Workflow Trigger", +"type": "n8n-nodes-base.executeWorkflowTrigger", +"position": [ +540, +1240 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "f571d0cc-eb43-46c9-bdd5-45abc51dfbe7", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +461.9740563285368, +970.616715060075 +], +"parameters": { +"color": 7, +"width": 1449.2963504228514, +"height": 612.0936015224503, +"content": "### Sub-workflow: Custom tool\nThis can be called by the agent above. It returns three different types of data from the Google Sheet, which can be used together for more complex queries without returning the whole sheet (which might be too big for GPT to handle)" +}, +"typeVersion": 1 +}, +{ +"id": "8761e314-c1f2-4edd-88ea-bfeb02dc8f1a", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +460, +460 +], +"parameters": { +"color": 7, +"width": 927.5, +"height": 486.5625, +"content": "### Main workflow: AI agent using custom tool" +}, +"typeVersion": 1 +}, +{ +"id": "e793b816-68d9-42ef-b9b0-6fe22aa375e8", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +300, +540 +], +"parameters": { +"width": 185.9375, +"height": 183.85014518022527, +"content": "## Try me out\n\nClick the 'Chat' button at the bottom and enter:\n\n_Which is our biggest customer?_" +}, +"typeVersion": 1 +}, +{ +"id": "f895d926-0f70-415b-9492-c3ecf186e761", +"name": "Get Google sheet contents", +"type": "n8n-nodes-base.googleSheets", +"position": [ +980, +1240 +], +"parameters": { +"options": {}, +"sheetName": { +"__rl": true, +"mode": "url", +"value": "={{ $json.sheetUrl }}" +}, +"documentId": { +"__rl": true, +"mode": "url", +"value": "={{ $json.sheetUrl }}" +} +}, +"credentials": { +"googleSheetsOAuth2Api": { +"id": "cTLaIZBSFJlHuZNs", +"name": "Google Sheets account" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "daca1624-6c35-473a-bf3a-5fa0686a0a62", +"name": "Set Google Sheet URL", +"type": "n8n-nodes-base.set", +"position": [ +760, +1240 +], +"parameters": { +"fields": { +"values": [ +{ +"name": "sheetUrl", +"stringValue": "https://docs.google.com/spreadsheets/d/1GjFBV8HpraNWG_JyuaQAgTb3zUGguh0S_25nO0CMd8A/edit#gid=736425281" +} +] +}, +"options": {} +}, +"typeVersion": 3.2 +}, +{ +"id": "68edca41-0196-47d8-9378-31fed0a70918", +"name": "Get column names", +"type": "n8n-nodes-base.set", +"position": [ +1460, +1060 +], +"parameters": { +"fields": { +"values": [ +{ +"name": "response", +"stringValue": "={{ Object.keys($json) }}" +} +] +}, +"include": "none", +"options": {} +}, +"executeOnce": true, +"typeVersion": 3.2 +}, +{ +"id": "7a9dea08-f9e9-4139-842a-9066a9cf04ea", +"name": "Prepare output", +"type": "n8n-nodes-base.code", +"position": [ +1720, +1240 +], +"parameters": { +"jsCode": "return {\n 'response': JSON.stringify($input.all().map(x => x.json))\n}" +}, +"typeVersion": 2 +}, +{ +"id": "616eebc5-5c5c-4fa1-b13f-61a477742c72", +"name": "List columns tool", +"type": "@n8n/n8n-nodes-langchain.toolWorkflow", +"position": [ +940, +780 +], +"parameters": { +"name": "list_columns", +"fields": { +"values": [ +{ +"name": "operation", +"stringValue": "column_names" +} +] +}, +"workflowId": "={{ $workflow.id }}", +"description": "=List all column names in customer data\n\nCall this tool to find out what data is available for each customer. It should be called first at the beginning to understand which columns are available for querying." +}, +"typeVersion": 1 +}, +{ +"id": "891ad3a8-72f0-45ad-8777-1647a7342c00", +"name": "Get customer tool", +"type": "@n8n/n8n-nodes-langchain.toolWorkflow", +"position": [ +1220, +780 +], +"parameters": { +"name": "get_customer", +"fields": { +"values": [ +{ +"name": "operation", +"stringValue": "row" +} +] +}, +"workflowId": "={{ $workflow.id }}", +"description": "=Get all columns for a given customer\n\nThe input should be a stringified row number of the customer to fetch; only single string inputs are allowed. Returns a JSON object with all the column names and their values." +}, +"typeVersion": 1 +}, +{ +"id": "0f3ca6ff-fc01-4f33-b1a7-cb82a0ec5c88", +"name": "Get column values tool", +"type": "@n8n/n8n-nodes-langchain.toolWorkflow", +"position": [ +1080, +780 +], +"parameters": { +"name": "column_values", +"fields": { +"values": [ +{ +"name": "operation", +"stringValue": "column_values" +} +] +}, +"workflowId": "={{ $workflow.id }}", +"description": "=Get the specified column value for all customers\n\nUse this tool to find out which customers have a certain value for a given column. Returns an array of JSON objects, one per customer. Each JSON object includes the column being requested plus the row_number column. Input should be a single string representing the name of the column to fetch.\n" +}, +"typeVersion": 1 +}, +{ +"id": "deef6eb4-2a11-4490-ad56-bc1ea9077843", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +900, +740.8693557231958 +], +"parameters": { +"color": 7, +"width": 432.3271051132649, +"height": 179.21380662202682, +"content": "These tools all call the sub-workflow below" +}, +"typeVersion": 1 +}, +{ +"id": "94e4dbe5-dc41-4879-bffc-ec8f5341f3b5", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +723, +1172 +], +"parameters": { +"width": 179.99762227826224, +"height": 226.64416053838073, +"content": "Change the URL of the Google Sheet here" +}, +"typeVersion": 1 +}, +{ +"id": "dbb887f0-93a7-466e-9c9f-8aa4e7da935d", +"name": "Prepare column data", +"type": "n8n-nodes-base.set", +"position": [ +1460, +1240 +], +"parameters": { +"fields": { +"values": [ +{ +"name": "={{ $('Execute Workflow Trigger').item.json.query }}", +"stringValue": "={{ $json[$('Execute Workflow Trigger').item.json.query] }}" +}, +{ +"name": "row_number", +"stringValue": "={{ $json.row_number }}" +} +] +}, +"include": "none", +"options": {} +}, +"typeVersion": 3.2 +}, +{ +"id": "041d32ca-e59a-4b67-a3e6-4e2f19e3de72", +"name": "Filter", +"type": "n8n-nodes-base.filter", +"position": [ +1460, +1400 +], +"parameters": { +"options": { +"looseTypeValidation": true +}, +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "loose" +}, +"combinator": "and", +"conditions": [ +{ +"id": "bf712098-97e4-42cb-8e08-2ee32d19d3e7", +"operator": { +"type": "number", +"operation": "equals" +}, +"leftValue": "={{ $json.row_number }}", +"rightValue": "={{ $('Execute Workflow Trigger').item.json.query }}" +} +] +} +}, +"typeVersion": 2, +"alwaysOutputData": true +}, +{ +"id": "69b9e70a-9104-4731-9f16-8324a3f7e423", +"name": "Check operation", +"type": "n8n-nodes-base.switch", +"position": [ +1200, +1240 +], +"parameters": { +"rules": { +"values": [ +{ +"outputKey": "col names", +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"operator": { +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $('Execute Workflow Trigger').item.json.operation }}", +"rightValue": "column_names" +} +] +}, +"renameOutput": true +}, +{ +"outputKey": "col values", +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "b7968ce7-0d20-43d0-bcca-7b66e0aec715", +"operator": { +"name": "filter.operator.equals", +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $('Execute Workflow Trigger').item.json.operation }}", +"rightValue": "column_values" +} +] +}, +"renameOutput": true +}, +{ +"outputKey": "rows", +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "de3bb9b5-edc6-4448-839e-eda07b72144a", +"operator": { +"name": "filter.operator.equals", +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $('Execute Workflow Trigger').item.json.operation }}", +"rightValue": "row" +} +] +}, +"renameOutput": true +} +] +}, +"options": {} +}, +"typeVersion": 3 +}, +{ +"id": "d955e499-5a3e-45a3-9fc8-266e2f687ecc", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +800, +780 +], +"parameters": { +"model": "gpt-3.5-turbo-0125", +"options": { +"temperature": 0 +} +}, +"credentials": { +"openAiApi": { +"id": "58qWzMjeNE8GjMmI", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "28fbda0b-1e01-4f59-af5b-fe02eba899b1", +"name": "Chat Trigger", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +620, +560 +], +"webhookId": "2b9d9c42-adf4-425d-b0a5-e4f60c750e63", +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "c89614f4-d8b1-4f7b-9e7c-856e3f89eadb", +"name": "AI Agent", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +900, +560 +], +"parameters": { +"agent": "reActAgent", +"options": { +"suffix": "Begin! Use `list_columns` tool first to determine which columns are available.\n\n\tQuestion: {input}\n\tThought:{agent_scratchpad}", +"returnIntermediateSteps": false +} +}, +"typeVersion": 1.3 +} +], +"active": false, +"pinData": { +"Execute Workflow Trigger": [ +{ +"json": { +"query": "222", +"operation": "row" +} +} +] +}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "94885609-92bb-498c-9628-35d9044593e7", +"connections": { +"Filter": { +"main": [ +[ +{ +"node": "Prepare output", +"type": "main", +"index": 0 +} +] +] +}, +"Chat Trigger": { +"main": [ +[ +{ +"node": "AI Agent", +"type": "main", +"index": 0 +} +] +] +}, +"Check operation": { +"main": [ +[ +{ +"node": "Get column names", +"type": "main", +"index": 0 +} +], +[ +{ +"node": "Prepare column data", +"type": "main", +"index": 0 +} +], +[ +{ +"node": "Filter", +"type": "main", +"index": 0 +} +] +] +}, +"Get column names": { +"main": [ +[ +{ +"node": "Prepare output", +"type": "main", +"index": 0 +} +] +] +}, +"Get customer tool": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"List columns tool": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "AI Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Prepare column data": { +"main": [ +[ +{ +"node": "Prepare output", +"type": "main", +"index": 0 +} +] +] +}, +"Set Google Sheet URL": { +"main": [ +[ +{ +"node": "Get Google sheet contents", +"type": "main", +"index": 0 +} +] +] +}, +"Get column values tool": { +"ai_tool": [ +[ +{ +"node": "AI Agent", +"type": "ai_tool", +"index": 0 +} +] +] +}, +"Execute Workflow Trigger": { +"main": [ +[ +{ +"node": "Set Google Sheet URL", +"type": "main", +"index": 0 +} +] +] +}, +"Get Google sheet contents": { +"main": [ +[ +{ +"node": "Check operation", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with local LLMs using n8n and Ollama.txt b/Chat with local LLMs using n8n and Ollama.txt new file mode 100644 index 0000000..27e31a4 --- /dev/null +++ b/Chat with local LLMs using n8n and Ollama.txt @@ -0,0 +1,116 @@ +{ +"id": "af8RV5b2TWB2LclA", +"meta": { +"instanceId": "95f2ab28b3dabb8da5d47aa5145b95fe3845f47b20d6343dd5256b6a28ba8fab", +"templateCredsSetupCompleted": true +}, +"name": "Chat with local LLMs using n8n and Ollama", +"tags": [], +"nodes": [ +{ +"id": "475385fa-28f3-45c4-bd1a-10dde79f74f2", +"name": "When chat message received", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +700, +460 +], +"webhookId": "ebdeba3f-6b4f-49f3-ba0a-8253dd226161", +"parameters": { +"options": {} +}, +"typeVersion": 1.1 +}, +{ +"id": "61133dc6-dcd9-44ff-85f2-5d8cc2ce813e", +"name": "Ollama Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOllama", +"position": [ +900, +680 +], +"parameters": { +"options": {} +}, +"credentials": { +"ollamaApi": { +"id": "MyYvr1tcNQ4e7M6l", +"name": "Local Ollama" +} +}, +"typeVersion": 1 +}, +{ +"id": "3e89571f-7c87-44c6-8cfd-4903d5e1cdc5", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +160, +80 +], +"parameters": { +"width": 485, +"height": 473, +"content": "## Chat with local LLMs using n8n and Ollama\nThis n8n workflow allows you to seamlessly interact with your self-hosted Large Language Models (LLMs) through a user-friendly chat interface. By connecting to Ollama, a powerful tool for managing local LLMs, you can send prompts and receive AI-generated responses directly within n8n.\n\n### How it works\n1. When chat message received: Captures the user's input from the chat interface.\n2. Chat LLM Chain: Sends the input to the Ollama server and receives the AI-generated response.\n3. Delivers the LLM's response back to the chat interface.\n\n### Set up steps\n* Make sure Ollama is installed and running on your machine before executing this workflow.\n* Edit the Ollama address if different from the default.\n" +}, +"typeVersion": 1 +}, +{ +"id": "9345cadf-a72e-4d3d-b9f0-d670744065fe", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1040, +660 +], +"parameters": { +"color": 6, +"width": 368, +"height": 258, +"content": "## Ollama setup\n* Connect to your local Ollama, usually on http://localhost:11434\n* If running in Docker, make sure that the n8n container has access to the host's network in order to connect to Ollama. You can do this by passing `--net=host` option when starting the n8n Docker container" +}, +"typeVersion": 1 +}, +{ +"id": "eeffdd4e-6795-4ebc-84f7-87b5ac4167d9", +"name": "Chat LLM Chain", +"type": "@n8n/n8n-nodes-langchain.chainLlm", +"position": [ +920, +460 +], +"parameters": {}, +"typeVersion": 1.4 +} +], +"active": false, +"pinData": {}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "3af03daa-e085-4774-8676-41578a4cba2d", +"connections": { +"Ollama Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "Chat LLM Chain", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"When chat message received": { +"main": [ +[ +{ +"node": "Chat LLM Chain", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Chat with your event schedule from Google Sheets in Telegram.txt b/Chat with your event schedule from Google Sheets in Telegram.txt new file mode 100644 index 0000000..394683c --- /dev/null +++ b/Chat with your event schedule from Google Sheets in Telegram.txt @@ -0,0 +1,678 @@ +{ +"id": "bV0JTA5NtRZxiD1q", +"meta": { +"instanceId": "98bf0d6aef1dd8b7a752798121440fb171bf7686b95727fd617f43452393daa3", +"templateCredsSetupCompleted": true +}, +"name": "Telegram-bot AI Da Nang", +"tags": [], +"nodes": [ +{ +"id": "ae5f9ca6-6bba-4fe8-b955-6c615d8a522f", +"name": "SendTyping", +"type": "n8n-nodes-base.telegram", +"position": [ +-1780, +-260 +], +"webhookId": "26ea953e-93d9-463e-ad90-95ea8ccb449f", +"parameters": { +"chatId": "={{ $('telegramInput').item.json.message.chat.id }}", +"operation": "sendChatAction" +}, +"credentials": { +"telegramApi": { +"id": "V3EtQBeqEvnOtl9p", +"name": "Telegram account" +} +}, +"typeVersion": 1.2 +}, +{ +"id": "244e7be3-2caa-46f7-8628-d063a3b84c12", +"name": "SetResponse", +"type": "n8n-nodes-base.set", +"notes": "Assemble response etc.", +"position": [ +40, +-420 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "fba8dc48-1484-4aae-8922-06fcae398f05", +"name": "responseMessage", +"type": "string", +"value": "={{ $json.output }}" +}, +{ +"id": "df8243e6-6a24-4bad-8807-63d75c828150", +"name": "", +"type": "string", +"value": "" +} +] +}, +"includeOtherFields": true +}, +"notesInFlow": true, +"typeVersion": 3.4 +}, +{ +"id": "192aa194-f131-4ba3-8842-7c88da1a6129", +"name": "Settings", +"type": "n8n-nodes-base.set", +"position": [ +-1260, +-420 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "6714203d-04b3-4a3c-9183-09cddcffdfe8", +"name": "scheduleURL", +"type": "string", +"value": "https://docs.google.com/spreadsheets/d/1BJFS9feEy94_WgIgzWZttBwzjp09siOw1xuUgq4yuI4" +} +] +}, +"includeOtherFields": true +}, +"typeVersion": 3.4 +}, +{ +"id": "1c52cdf5-da32-4c76-a294-5ec2109dbf39", +"name": "Schedule", +"type": "n8n-nodes-base.googleSheets", +"position": [ +-980, +-420 +], +"parameters": { +"options": {}, +"sheetName": { +"__rl": true, +"mode": "list", +"value": "gid=0", +"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1BJFS9feEy94_WgIgzWZttBwzjp09siOw1xuUgq4yuI4/edit#gid=0", +"cachedResultName": "Schedule" +}, +"documentId": { +"__rl": true, +"mode": "url", +"value": "={{ $json.scheduleURL }}" +} +}, +"credentials": { +"googleSheetsOAuth2Api": { +"id": "XeXufn5uZvHp3lcX", +"name": "Google Sheets account 2" +} +}, +"typeVersion": 4.5 +}, +{ +"id": "eff88417-4ce6-4809-8693-dc63e00fff20", +"name": "ScheduleToMarkdown", +"type": "n8n-nodes-base.code", +"position": [ +-800, +-420 +], +"parameters": { +"jsCode": "// Get all rows from the input (each item has a \"json\" property)\nconst rows = items.map(item => item.json);\n\n// If no data, return an appropriate message\nif (rows.length === 0) {\n return [{ json: { markdown: \"No data available.\" } }];\n}\n\n// Use the keys from the first row as the header columns\nconst headers = Object.keys(rows[0]);\n\n// Build the markdown table string\nlet markdown = \"\";\n\n// Create the header row\nmarkdown += `| ${headers.join(\" | \")} |\\n`;\n\n// Create the separator row (using dashes for markdown)\nmarkdown += `| ${headers.map(() => '---').join(\" | \")} |\\n`;\n\n// Add each data row to the table\nrows.forEach(row => {\n // Ensure we output something for missing values\n const rowValues = headers.map(header => row[header] !== undefined ? row[header] : '');\n markdown += `| ${rowValues.join(\" | \")} |\\n`;\n});\n\nconst result = { 'binary': {}, 'json': {} };\n\n// Convert the markdown string to a binary buffer\nconst binaryData = Buffer.from(markdown, 'utf8');\n/*\n// Attach the binary data to the first item under a binary property named 'data'\nresult.binary = {\n data: {\n data: binaryData,\n mimeType: 'text/markdown',\n }\n};\n*/\n// Optionally, also return the markdown string in the json property if needed\nresult.json.markdown = markdown;\n\nreturn result;" +}, +"typeVersion": 2 +}, +{ +"id": "04fab70c-493a-4c5d-adfb-0d9e8a5b7382", +"name": "ScheduleBot", +"type": "@n8n/n8n-nodes-langchain.agent", +"position": [ +-480, +-420 +], +"parameters": { +"text": "={{ $('Settings').first().json.inputMessage }}", +"options": { +"systemMessage": "=You are a helpful assistant that helps members of a meetup group with scheduling their meetups and answering questions about them.\n\nThe current version of the schedule in tabular format is the following:\n\n {{ $json.markdown }}\n\n" +}, +"promptType": "define" +}, +"typeVersion": 1.7 +}, +{ +"id": "be29d3ec-8211-4f23-82f2-83a1aa3aad5b", +"name": "n8nChatSettings", +"type": "n8n-nodes-base.set", +"position": [ +-1580, +-520 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "1ecb3515-c1a2-4d69-adec-5b4d74e32056", +"name": "inputMessage", +"type": "string", +"value": "={{ $json.chatInput }}" +}, +{ +"id": "424b9697-94cb-4c38-953c-992436832684", +"name": "chatId", +"type": "string", +"value": "={{ $json.sessionId }}" +}, +{ +"id": "e23988e2-7c3d-4e38-9d5d-0c4b0c94d127", +"name": "mode", +"type": "string", +"value": "n8n" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "b7078c59-b6e6-4002-831f-96e56278ab61", +"name": "telegramChatSettings", +"type": "n8n-nodes-base.set", +"position": [ +-1580, +-260 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "1ecb3515-c1a2-4d69-adec-5b4d74e32056", +"name": "inputMessage", +"type": "string", +"value": "={{ $('telegramInput').item.json.message.text }}" +}, +{ +"id": "424b9697-94cb-4c38-953c-992436832684", +"name": "chatId", +"type": "string", +"value": "={{ $('telegramInput').item.json.message.chat.id }}" +}, +{ +"id": "e23988e2-7c3d-4e38-9d5d-0c4b0c94d127", +"name": "mode", +"type": "string", +"value": "telegram" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "1ba6ad37-f1e5-440d-bf10-569038c27bce", +"name": "telegramInput", +"type": "n8n-nodes-base.telegramTrigger", +"position": [ +-1960, +-260 +], +"webhookId": "f56e8e22-975e-4f9a-a6f9-253ebc63668d", +"parameters": { +"updates": [ +"message" +], +"additionalFields": {} +}, +"credentials": { +"telegramApi": { +"id": "V3EtQBeqEvnOtl9p", +"name": "Telegram account" +} +}, +"typeVersion": 1.1 +}, +{ +"id": "56a52e8a-714f-4e7a-8a13-e915e9dc29c4", +"name": "n8nInput", +"type": "@n8n/n8n-nodes-langchain.chatTrigger", +"position": [ +-1960, +-520 +], +"webhookId": "f4ab7d4a-5cdd-425a-bbbb-e3bb94719266", +"parameters": { +"options": {} +}, +"typeVersion": 1.1 +}, +{ +"id": "961f67f0-bd44-4e7f-9f2f-c2f02f3176ce", +"name": "Switch", +"type": "n8n-nodes-base.switch", +"position": [ +220, +-420 +], +"parameters": { +"rules": { +"values": [ +{ +"outputKey": "n8n mode", +"conditions": { +"options": { +"version": 2, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"operator": { +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $('Settings').first().json.mode }}", +"rightValue": "n8n" +} +] +}, +"renameOutput": true +}, +{ +"outputKey": "telegram mode", +"conditions": { +"options": { +"version": 2, +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "e7d6a994-48e3-44bb-b662-862d9bf9c53b", +"operator": { +"name": "filter.operator.equals", +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $('Settings').first().json.mode }}", +"rightValue": "telegram" +} +] +}, +"renameOutput": true +} +] +}, +"options": {} +}, +"typeVersion": 3.2 +}, +{ +"id": "57056425-37ba-417d-9a2d-977a81d378ab", +"name": "telegramResponse", +"type": "n8n-nodes-base.telegram", +"position": [ +500, +-280 +], +"webhookId": "ff71ba7e-affa-4952-90a5-6bb7f37a5598", +"parameters": { +"text": "={{ $json.responseMessage }}", +"chatId": "={{ $('Settings').first().json.chatId }}", +"additionalFields": {} +}, +"credentials": { +"telegramApi": { +"id": "V3EtQBeqEvnOtl9p", +"name": "Telegram account" +} +}, +"typeVersion": 1.2 +}, +{ +"id": "2962a77f-5727-43be-93fb-b0751b63c6ac", +"name": "n8nResponse", +"type": "n8n-nodes-base.noOp", +"position": [ +500, +-520 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "0932484f-707b-412b-b9cb-431a8ae64447", +"name": "LLM", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter", +"position": [ +-600, +-220 +], +"parameters": { +"options": {} +}, +"credentials": { +"openRouterApi": { +"id": "bs7tPtvgDTJNGAFJ", +"name": "OpenRouter account" +} +}, +"typeVersion": 1 +}, +{ +"id": "65948d2c-71b2-4df0-97db-ed216ed7c691", +"name": "Memory", +"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", +"position": [ +-500, +-220 +], +"parameters": { +"sessionKey": "={{ $('Settings').first().json.chatId }}", +"sessionIdType": "customKey" +}, +"typeVersion": 1.3 +}, +{ +"id": "50566274-cf7c-496f-a166-b45eb3114da3", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-2000, +-600 +], +"parameters": { +"color": 2, +"width": 620, +"height": 240, +"content": "## Chat input triggered inside n8n\nUsed for testing and debugging" +}, +"typeVersion": 1 +}, +{ +"id": "9dc636fb-cc86-4236-8eb9-952a4ab0ef68", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-2000, +-340 +], +"parameters": { +"color": 2, +"width": 620, +"height": 240, +"content": "## Chat input triggered by Telegram\nUsed for live chat within Telegram" +}, +"typeVersion": 1 +}, +{ +"id": "0429d589-3e80-4b26-96a0-01554899a3e7", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +420, +-340 +], +"parameters": { +"color": 5, +"width": 360, +"height": 240, +"content": "## Chat response to Telegram" +}, +"typeVersion": 1 +}, +{ +"id": "9eeccee0-c6a0-40c6-9b7d-1f672bf0fdb9", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +420, +-600 +], +"parameters": { +"color": 5, +"width": 360, +"height": 240, +"content": "## Chat response inside n8n" +}, +"typeVersion": 1 +}, +{ +"id": "acb8e550-be94-41b7-904a-641b3b87e928", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-40, +-600 +], +"parameters": { +"color": 7, +"width": 440, +"height": 500, +"content": "## Prepare response\nDecide to which chat the response will go." +}, +"typeVersion": 1 +}, +{ +"id": "42ce6eac-165b-463d-822e-355aff030525", +"name": "Sticky Note5", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-620, +-600 +], +"parameters": { +"color": 3, +"width": 560, +"height": 500, +"content": "## AI Processing\nChat input → Chat output" +}, +"typeVersion": 1 +}, +{ +"id": "33c45fcc-3aa5-4cd3-b393-e1723560dfeb", +"name": "Sticky Note6", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-1040, +-600 +], +"parameters": { +"color": 4, +"width": 400, +"height": 500, +"content": "## Retrieve Data\nGet schedule from Google Spreadsheet and convert it to a Markdown-Table as context for the LLM" +}, +"typeVersion": 1 +}, +{ +"id": "6e1017e3-bf9d-4056-a64f-c94476bd1f43", +"name": "Sticky Note7", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-1360, +-600 +], +"parameters": { +"color": 7, +"width": 300, +"height": 500, +"content": "## Normalize input\nTransfer the chat data into a unified set of variables" +}, +"typeVersion": 1 +} +], +"active": true, +"pinData": {}, +"settings": { +"executionOrder": "v1" +}, +"versionId": "9078c996-e932-40c0-882e-1eb261ca1535", +"connections": { +"LLM": { +"ai_languageModel": [ +[ +{ +"node": "ScheduleBot", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Memory": { +"ai_memory": [ +[ +{ +"node": "ScheduleBot", +"type": "ai_memory", +"index": 0 +} +] +] +}, +"Switch": { +"main": [ +[ +{ +"node": "n8nResponse", +"type": "main", +"index": 0 +} +], +[ +{ +"node": "telegramResponse", +"type": "main", +"index": 0 +} +] +] +}, +"Schedule": { +"main": [ +[ +{ +"node": "ScheduleToMarkdown", +"type": "main", +"index": 0 +} +] +] +}, +"Settings": { +"main": [ +[ +{ +"node": "Schedule", +"type": "main", +"index": 0 +} +] +] +}, +"n8nInput": { +"main": [ +[ +{ +"node": "n8nChatSettings", +"type": "main", +"index": 0 +} +] +] +}, +"SendTyping": { +"main": [ +[ +{ +"node": "telegramChatSettings", +"type": "main", +"index": 0 +} +] +] +}, +"ScheduleBot": { +"main": [ +[ +{ +"node": "SetResponse", +"type": "main", +"index": 0 +} +] +] +}, +"SetResponse": { +"main": [ +[ +{ +"node": "Switch", +"type": "main", +"index": 0 +} +] +] +}, +"telegramInput": { +"main": [ +[ +{ +"node": "SendTyping", +"type": "main", +"index": 0 +} +] +] +}, +"n8nChatSettings": { +"main": [ +[ +{ +"node": "Settings", +"type": "main", +"index": 0 +} +] +] +}, +"telegramResponse": { +"main": [ +[] +] +}, +"ScheduleToMarkdown": { +"main": [ +[ +{ +"node": "ScheduleBot", +"type": "main", +"index": 0 +} +] +] +}, +"telegramChatSettings": { +"main": [ +[ +{ +"node": "Settings", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/ChatGPT Automatic Code Review in Gitlab MR.txt b/ChatGPT Automatic Code Review in Gitlab MR.txt new file mode 100644 index 0000000..fb5251d --- /dev/null +++ b/ChatGPT Automatic Code Review in Gitlab MR.txt @@ -0,0 +1,405 @@ +{ +"nodes": [ +{ +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +880, +540 +], +"parameters": { +"content": "## Edit your own prompt ⬇️\n" +}, +"typeVersion": 1 +}, +{ +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-380, +580 +], +"parameters": { +"content": "## Filter comments and customize your trigger words ⬇️" +}, +"typeVersion": 1 +}, +{ +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-120, +560 +], +"parameters": { +"content": "## Replace your gitlab URL and token ⬇️" +}, +"typeVersion": 1 +}, +{ +"name": "Webhook", +"type": "n8n-nodes-base.webhook", +"position": [ +-540, +760 +], +"webhookId": "6cfd2f23-6f45-47d4-9fe0-8f6f1c05829a", +"parameters": { +"path": "e21095c0-1876-4cd9-9e92-a2eac737f03e", +"options": {}, +"httpMethod": "POST" +}, +"typeVersion": 1.1 +}, +{ +"name": "Code", +"type": "n8n-nodes-base.code", +"position": [ +720, +540 +], +"parameters": { +"mode": "runOnceForEachItem", +"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nvar diff = $input.item.json.gitDiff\n\nlet lines = diff.trimEnd().split('\\n');\n\nlet originalCode = '';\nlet newCode = '';\n\nlines.forEach(line => {\n console.log(line)\n if (line.startsWith('-')) {\n originalCode += line + \"\\n\";\n } else if (line.startsWith('+')) {\n newCode += line + \"\\n\";\n } else {\n originalCode += line + \"\\n\";\n newCode += line + \"\\n\";\n }\n});\n\nreturn {\n originalCode:originalCode,\n newCode:newCode\n};\n\n" +}, +"typeVersion": 2 +}, +{ +"name": "Split Out1", +"type": "n8n-nodes-base.splitOut", +"position": [ +140, +740 +], +"parameters": { +"options": {}, +"fieldToSplitOut": "changes" +}, +"typeVersion": 1 +}, +{ +"name": "OpenAI Chat Model1", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +900, +860 +], +"parameters": { +"options": { +"baseURL": "" +} +}, +"typeVersion": 1 +}, +{ +"name": "Get Changes1", +"type": "n8n-nodes-base.httpRequest", +"position": [ +-60, +740 +], +"parameters": { +"url": "=https://gitlab.com/api/v4/projects/{{ $json[\"body\"][\"project_id\"] }}/merge_requests/{{ $json[\"body\"][\"merge_request\"][\"iid\"] }}/changes", +"options": {}, +"sendHeaders": true, +"headerParameters": { +"parameters": [ +{ +"name": "PRIVATE-TOKEN" +} +] +} +}, +"typeVersion": 4.1 +}, +{ +"name": "Skip File Change1", +"type": "n8n-nodes-base.if", +"position": [ +340, +740 +], +"parameters": { +"options": {}, +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"operator": { +"type": "boolean", +"operation": "false", +"singleValue": true +}, +"leftValue": "={{ $json.renamed_file }}", +"rightValue": "" +}, +{ +"operator": { +"type": "boolean", +"operation": "false", +"singleValue": true +}, +"leftValue": "={{ $json.deleted_file }}", +"rightValue": "" +}, +{ +"operator": { +"type": "string", +"operation": "startsWith" +}, +"leftValue": "={{ $json.diff }}", +"rightValue": "@@" +} +] +} +}, +"typeVersion": 2 +}, +{ +"name": "Parse Last Diff Line1", +"type": "n8n-nodes-base.code", +"position": [ +540, +540 +], +"parameters": { +"mode": "runOnceForEachItem", +"jsCode": "const parseLastDiff = (gitDiff) => {\n gitDiff = gitDiff.replace(/\\n\\\\ No newline at end of file/, '')\n \n const diffList = gitDiff.trimEnd().split('\\n').reverse();\n const lastLineFirstChar = diffList?.[0]?.[0];\n const lastDiff =\n diffList.find((item) => {\n return /^@@ \\-\\d+,\\d+ \\+\\d+,\\d+ @@/g.test(item);\n }) || '';\n\n const [lastOldLineCount, lastNewLineCount] = lastDiff\n .replace(/@@ \\-(\\d+),(\\d+) \\+(\\d+),(\\d+) @@.*/g, ($0, $1, $2, $3, $4) => {\n return `${+$1 + +$2},${+$3 + +$4}`;\n })\n .split(',');\n \n if (!/^\\d+$/.test(lastOldLineCount) || !/^\\d+$/.test(lastNewLineCount)) {\n return {\n lastOldLine: -1,\n lastNewLine: -1,\n gitDiff,\n };\n }\n\n\n const lastOldLine = lastLineFirstChar === '+' ? null : (parseInt(lastOldLineCount) || 0) - 1;\n const lastNewLine = lastLineFirstChar === '-' ? null : (parseInt(lastNewLineCount) || 0) - 1;\n\n return {\n lastOldLine,\n lastNewLine,\n gitDiff,\n };\n};\n\nreturn parseLastDiff($input.item.json.diff)\n" +}, +"typeVersion": 2 +}, +{ +"name": "Post Discussions1", +"type": "n8n-nodes-base.httpRequest", +"position": [ +1280, +720 +], +"parameters": { +"url": "=https://gitlab.com/api/v4/projects/{{ $('Webhook').item.json[\"body\"][\"project_id\"] }}/merge_requests/{{ $('Webhook').item.json[\"body\"][\"merge_request\"][\"iid\"] }}/discussions", +"method": "POST", +"options": {}, +"sendBody": true, +"contentType": "multipart-form-data", +"sendHeaders": true, +"bodyParameters": { +"parameters": [ +{ +"name": "body", +"value": "={{ $('Basic LLM Chain1').item.json[\"text\"] }}" +}, +{ +"name": "position[position_type]", +"value": "text" +}, +{ +"name": "position[old_path]", +"value": "={{ $('Split Out1').item.json.old_path }}" +}, +{ +"name": "position[new_path]", +"value": "={{ $('Split Out1').item.json.new_path }}" +}, +{ +"name": "position[start_sha]", +"value": "={{ $('Get Changes1').item.json.diff_refs.start_sha }}" +}, +{ +"name": "position[head_sha]", +"value": "={{ $('Get Changes1').item.json.diff_refs.head_sha }}" +}, +{ +"name": "position[base_sha]", +"value": "={{ $('Get Changes1').item.json.diff_refs.base_sha }}" +}, +{ +"name": "position[new_line]", +"value": "={{ $('Parse Last Diff Line1').item.json.lastNewLine || '' }}" +}, +{ +"name": "position[old_line]", +"value": "={{ $('Parse Last Diff Line1').item.json.lastOldLine || '' }}" +} +] +}, +"headerParameters": { +"parameters": [ +{ +"name": "PRIVATE-TOKEN" +} +] +} +}, +"typeVersion": 4.1 +}, +{ +"name": "Need Review1", +"type": "n8n-nodes-base.if", +"position": [ +-320, +760 +], +"parameters": { +"options": {}, +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"operator": { +"name": "filter.operator.equals", +"type": "string", +"operation": "equals" +}, +"leftValue": "={{ $json.body.object_attributes.note }}", +"rightValue": "+0" +} +] +} +}, +"typeVersion": 2 +}, +{ +"name": "Basic LLM Chain1", +"type": "@n8n/n8n-nodes-langchain.chainLlm", +"position": [ +880, +720 +], +"parameters": { +"prompt": "=File path:{{ $('Skip File Change1').item.json.new_path }}\n\n```Original code\n {{ $json.originalCode }}\n```\nchange to\n```New code\n {{ $json.newCode }}\n```\nPlease review the code changes in this section:", +"messages": { +"messageValues": [ +{ +"message": "# Overview:\n You are a senior programming expert Bot, responsible for reviewing code changes and providing review recommendations.\n At the beginning of the suggestion, it is necessary to clearly make a decision to \"reject\" or \"accept\" the code change, and rate the change in the format \"Change Score: Actual Score\", with a score range of 0-100 points.\n Then, point out the existing problems in concise language and a stern tone.\n If you feel it is necessary, you can directly provide the modified content.\n Your review proposal must use rigorous Markdown format." +} +] +} +}, +"typeVersion": 1.2 +}, +{ +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1200, +540 +], +"parameters": { +"content": "## Replace your gitlab URL and token ⬇️" +}, +"typeVersion": 1 +} +], +"pinData": {}, +"connections": { +"Code": { +"main": [ +[ +{ +"node": "Basic LLM Chain1", +"type": "main", +"index": 0 +} +] +] +}, +"Webhook": { +"main": [ +[ +{ +"node": "Need Review1", +"type": "main", +"index": 0 +} +] +] +}, +"Split Out1": { +"main": [ +[ +{ +"node": "Skip File Change1", +"type": "main", +"index": 0 +} +] +] +}, +"Get Changes1": { +"main": [ +[ +{ +"node": "Split Out1", +"type": "main", +"index": 0 +} +] +] +}, +"Need Review1": { +"main": [ +[ +{ +"node": "Get Changes1", +"type": "main", +"index": 0 +} +] +] +}, +"Basic LLM Chain1": { +"main": [ +[ +{ +"node": "Post Discussions1", +"type": "main", +"index": 0 +} +] +] +}, +"Skip File Change1": { +"main": [ +[ +{ +"node": "Parse Last Diff Line1", +"type": "main", +"index": 0 +} +] +] +}, +"OpenAI Chat Model1": { +"ai_languageModel": [ +[ +{ +"node": "Basic LLM Chain1", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Parse Last Diff Line1": { +"main": [ +[ +{ +"node": "Code", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file diff --git a/Customer Insights with Qdrant, Python and Information Extractor.txt b/Customer Insights with Qdrant, Python and Information Extractor.txt new file mode 100644 index 0000000..77dafc9 --- /dev/null +++ b/Customer Insights with Qdrant, Python and Information Extractor.txt @@ -0,0 +1,1150 @@ +{ +"meta": { +"instanceId": "408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9" +}, +"nodes": [ +{ +"id": "63501cc8-77c9-4037-9f70-da23b6d20b03", +"name": "When clicking ‘Test workflow’", +"type": "n8n-nodes-base.manualTrigger", +"position": [ +280, +440 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "00de989c-d9e9-4b42-b5db-7097800a6017", +"name": "Zip Entries", +"type": "n8n-nodes-base.set", +"position": [ +1380, +360 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "833a554d-2b39-4160-9348-18b17b28ce30", +"name": "data", +"type": "array", +"value": "={{ \n $json.review_author.map((review_author, idx) => ({\n review_author,\n review_author_reviews_count: $json.review_author_reviews_count[idx].replace(' reviews', '').toInt(),\n review_country: $json.review_country[idx],\n review_date: $json.review_date[idx].toDate(),\n review_date_of_experience: $json.review_date_of_experience[idx].replace('Date of experience: ', '').toDate(),\n review_rating: $json.review_rating[idx].toInt(),\n review_text: $json.review_text[idx],\n review_title: $json.review_title[idx],\n review_url: $('Get TrustPilot Page').params.url.match(/https:\\/\\/[^/]+/) + $json.review_url[idx],\n }))\n}}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "9290e116-c001-49d5-ae4c-d91cd246f2c2", +"name": "Extract Reviews", +"type": "n8n-nodes-base.html", +"position": [ +1140, +520 +], +"parameters": { +"options": { +"trimValues": true +}, +"operation": "extractHtmlContent", +"extractionValues": { +"values": [ +{ +"key": "review_author", +"cssSelector": "[data-service-review-card-paper] [data-consumer-name-typography]", +"returnArray": true +}, +{ +"key": "review_rating", +"attribute": "data-service-review-rating", +"cssSelector": "[data-service-review-rating]", +"returnArray": true, +"returnValue": "attribute" +}, +{ +"key": "review_title", +"cssSelector": "[data-service-review-title-typography]", +"returnArray": true +}, +{ +"key": "review_text", +"cssSelector": "[data-service-review-text-typography]", +"returnArray": true +}, +{ +"key": "review_date_of_experience", +"cssSelector": "[data-service-review-date-of-experience-typography]", +"returnArray": true +}, +{ +"key": "review_date", +"attribute": "datetime", +"cssSelector": "[data-service-review-date-time-ago]", +"returnArray": true, +"returnValue": "attribute" +}, +{ +"key": "review_country", +"cssSelector": "[data-consumer-country-typography]", +"returnArray": true +}, +{ +"key": "review_author_reviews_count", +"cssSelector": "[data-consumer-reviews-count-typography]", +"returnArray": true +}, +{ +"key": "review_url", +"attribute": "href", +"cssSelector": "a[data-review-title-typography]", +"returnArray": true, +"returnValue": "attribute" +} +] +} +}, +"typeVersion": 1.2 +}, +{ +"id": "4aa3e50d-fcce-48a7-8237-c12f8592f69e", +"name": "Reviews to List", +"type": "n8n-nodes-base.splitOut", +"position": [ +1380, +520 +], +"parameters": { +"options": {}, +"fieldToSplitOut": "data" +}, +"typeVersion": 1 +}, +{ +"id": "a6b9abf9-a17a-4f30-9f90-6183770c4933", +"name": "Default Data Loader", +"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", +"position": [ +1980, +520 +], +"parameters": { +"options": { +"metadata": { +"metadataValues": [ +{ +"name": "review_author", +"value": "={{ $json.review_author }}" +}, +{ +"name": "review_author_reviews_count", +"value": "={{ $json.review_author_reviews_count }}" +}, +{ +"name": "review_country", +"value": "={{ $json.review_country }}" +}, +{ +"name": "review_date", +"value": "={{ $json.review_date }}" +}, +{ +"name": "review_date_of_experience", +"value": "={{ $json.review_date_of_experience }}" +}, +{ +"name": "review_rating", +"value": "={{ $json.review_rating }}" +}, +{ +"name": "review_date_month", +"value": "={{ $json.review_date.toDateTime().format('M') }}" +}, +{ +"name": "review_date_year", +"value": "={{ $json.review_date.toDateTime().format('yyyy') }}" +}, +{ +"name": "review_date_of_experience_month", +"value": "={{ $json.review_date_of_experience.toDateTime().format('M') }}" +}, +{ +"name": "review_date_of_experience_year", +"value": "={{ $json.review_date_of_experience.toDateTime().format('yyyy') }}" +}, +{ +"name": "company_id", +"value": "={{ $('Set Variables').item.json.companyId }}" +}, +{ +"name": "review_url", +"value": "={{ $json.review_url }}" +} +] +} +}, +"jsonData": "={{ $json.review_title }}\n{{ $json.review_text }}", +"jsonMode": "expressionData" +}, +"typeVersion": 1 +}, +{ +"id": "afd8907c-9a59-4dcc-94c5-2114fb2a7d5d", +"name": "Recursive Character Text Splitter", +"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", +"position": [ +1980, +660 +], +"parameters": { +"options": {}, +"chunkSize": 4000 +}, +"typeVersion": 1 +}, +{ +"id": "e22d92b8-e8e9-42aa-9d02-2e70234f11ed", +"name": "Embeddings OpenAI", +"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", +"position": [ +1860, +520 +], +"parameters": { +"model": "text-embedding-3-small", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "f0ea6b63-c96d-4b3f-8a21-d0f2dbb4efc3", +"name": "Set Variables", +"type": "n8n-nodes-base.set", +"position": [ +520, +440 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "2e58a9fa-a14d-4a6c-8cc8-8ec947c791fb", +"name": "companyId", +"type": "string", +"value": "www.freddiesflowers.com" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "0188986f-fbe9-4c06-892a-3cb71b52a309", +"name": "Get Payload of Points", +"type": "n8n-nodes-base.httpRequest", +"position": [ +1740, +1120 +], +"parameters": { +"url": "=http://qdrant:6333/collections/trustpilot_reviews/points", +"method": "POST", +"options": {}, +"jsonBody": "={{\n {\n \"ids\": $json.points,\n \"with_payload\": true\n }\n}}", +"sendBody": true, +"specifyBody": "json", +"authentication": "predefinedCredentialType", +"nodeCredentialType": "qdrantApi" +}, +"credentials": { +"qdrantApi": { +"id": "NyinAS3Pgfik66w5", +"name": "QdrantApi account" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "5fc6e0b6-507f-4cfd-951b-be3709b86ac2", +"name": "Clusters To List", +"type": "n8n-nodes-base.splitOut", +"position": [ +1480, +1120 +], +"parameters": { +"options": {}, +"fieldToSplitOut": "output" +}, +"typeVersion": 1 +}, +{ +"id": "f21369b9-1dd5-4b35-a1f3-00fd67794051", +"name": "OpenAI Chat Model", +"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", +"position": [ +2140, +1340 +], +"parameters": { +"model": "gpt-4o-mini", +"options": {} +}, +"credentials": { +"openAiApi": { +"id": "8gccIjcuf3gvaoEr", +"name": "OpenAi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "b0075699-6513-4781-b5de-81d1ab81dfe1", +"name": "Only Clusters With 3+ points", +"type": "n8n-nodes-base.filter", +"position": [ +1480, +1300 +], +"parameters": { +"options": {}, +"conditions": { +"options": { +"leftValue": "", +"caseSensitive": true, +"typeValidation": "strict" +}, +"combinator": "and", +"conditions": [ +{ +"id": "328f806c-0792-4d90-9bee-a1e10049e78f", +"operator": { +"type": "array", +"operation": "lengthGt", +"rightType": "number" +}, +"leftValue": "={{ $json.points }}", +"rightValue": 2 +} +] +} +}, +"typeVersion": 2 +}, +{ +"id": "f6a6209c-d269-4238-8e92-230df7b41df9", +"name": "Set Variables1", +"type": "n8n-nodes-base.set", +"position": [ +519, +1220 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "2e58a9fa-a14d-4a6c-8cc8-8ec947c791fb", +"name": "companyId", +"type": "string", +"value": "={{ $json.companyId }}" +}, +{ +"id": "37cf8af2-6f0f-40b1-b822-c9bd6a620a3c", +"name": "review_date_from", +"type": "string", +"value": "={{ $today.startOf('month').toISO() }}" +}, +{ +"id": "8d72f739-f832-4c25-b62a-2ae70ad2b1e7", +"name": "review_date_to", +"type": "string", +"value": "={{ $today.endOf('month').toISO() }}" +} +] +} +}, +"typeVersion": 3.4 +}, +{ +"id": "85cb48b1-0ab9-4f88-88f3-82fcfb041ebe", +"name": "Find Reviews", +"type": "n8n-nodes-base.httpRequest", +"position": [ +896, +1160 +], +"parameters": { +"url": "=http://qdrant:6333/collections/trustpilot_reviews/points/scroll", +"method": "POST", +"options": {}, +"jsonBody": "={\n \"limit\": 500,\n \"filter\":{\n \"must\": [\n {\n \"key\": \"metadata.company_id\",\n \"match\": { \"value\": \"{{ $('Set Variables1').item.json.companyId }}\" }\n },\n {\n \"key\": \"metadata.review_date\",\n \"range\": {\n \"gte\": \"{{ $('Set Variables1').item.json.review_date_from }}\",\n \"gt\": null,\n \"lt\": null,\n \"lte\": \"{{ $('Set Variables1').item.json.review_date_to }}\"\n }\n }\n ]\n },\n \"with_vector\":true\n}", +"sendBody": true, +"specifyBody": "json", +"authentication": "predefinedCredentialType", +"nodeCredentialType": "qdrantApi" +}, +"credentials": { +"qdrantApi": { +"id": "NyinAS3Pgfik66w5", +"name": "QdrantApi account" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "69bbd197-c78f-4dae-9300-fe23d4d49855", +"name": "Prep Output For Export", +"type": "n8n-nodes-base.set", +"position": [ +2720, +1203 +], +"parameters": { +"mode": "raw", +"options": {}, +"jsonOutput": "={{ {\n ...$json.output,\n \"CompanyID\": $('Set Variables1').item.json.companyId,\n \"From\": $('Set Variables1').item.json.review_date_from,\n \"To\": $('Set Variables1').item.json.review_date_to,\n \"Number of Responses\": $('Get Payload of Points').item.json.result.length,\n \"Raw Responses\": $('Get Payload of Points').item.json.result.map(item =>\n [\n item.payload.metadata.review_date,\n item.payload.metadata.review_author,\n item.payload.metadata.review_rating,\n item.payload.content.replaceAll('\"', '\\\"').replaceAll('\\n', ' '),\n item.payload.metadata.review_url,\n ]\n ).join('\\n')\n} }}\n" +}, +"typeVersion": 3.4 +}, +{ +"id": "d77daa23-6acf-4daa-bf4c-33da4d05a54c", +"name": "Export To Sheets", +"type": "n8n-nodes-base.googleSheets", +"position": [ +2940, +1203 +], +"parameters": { +"columns": { +"value": {}, +"schema": [ +{ +"id": "CompanyID", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "CompanyID", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "From", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "From", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "To", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "To", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "Insight", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "Insight", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "Sentiment", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "Sentiment", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "Suggested Improvements", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "Suggested Improvements", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "Number of Responses", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "Number of Responses", +"defaultMatch": false, +"canBeUsedToMatch": true +}, +{ +"id": "Raw Responses", +"type": "string", +"display": true, +"removed": false, +"required": false, +"displayName": "Raw Responses", +"defaultMatch": false, +"canBeUsedToMatch": true +} +], +"mappingMode": "autoMapInputData", +"matchingColumns": [] +}, +"options": {}, +"operation": "append", +"sheetName": { +"__rl": true, +"mode": "name", +"value": "=Sheet1" +}, +"documentId": { +"__rl": true, +"mode": "id", +"value": "=1wAwWCcIZod00IGtxwTbTgjIRbKHu3Yl9wYWJ8GeT2Os" +} +}, +"credentials": { +"googleSheetsOAuth2Api": { +"id": "XHvC7jIRR8A2TlUl", +"name": "Google Sheets account" +} +}, +"typeVersion": 4.4 +}, +{ +"id": "1f60c3a5-a47a-4313-9b29-8ea652d573f7", +"name": "Clear Existing Reviews", +"type": "n8n-nodes-base.httpRequest", +"position": [ +760, +440 +], +"parameters": { +"url": "http://qdrant:6333/collections/trustpilot_reviews/points/delete", +"method": "POST", +"options": {}, +"jsonBody": "={\n \"filter\": {\n \"must\": [\n {\n \"key\": \"metadata.company_id\",\n \"match\": {\n \"value\": \"{{ $('Set Variables').item.json.companyId }}\"\n }\n }\n ]\n }\n}", +"sendBody": true, +"specifyBody": "json", +"authentication": "predefinedCredentialType", +"nodeCredentialType": "qdrantApi" +}, +"credentials": { +"qdrantApi": { +"id": "NyinAS3Pgfik66w5", +"name": "QdrantApi account" +} +}, +"typeVersion": 4.2 +}, +{ +"id": "61c3117c-757c-45dd-b9d5-1122b793be30", +"name": "Trigger Insights", +"type": "n8n-nodes-base.executeWorkflow", +"position": [ +2660, +440 +], +"parameters": { +"options": {}, +"workflowId": "={{ $workflow.id }}" +}, +"typeVersion": 1 +}, +{ +"id": "d3c6e81f-34bb-4be9-b869-2c219b87c4fb", +"name": "Prep Values For Trigger", +"type": "n8n-nodes-base.set", +"position": [ +2460, +440 +], +"parameters": { +"options": {}, +"assignments": { +"assignments": [ +{ +"id": "24dd90ad-390f-444e-ba6c-8c06a41e836e", +"name": "companyId", +"type": "string", +"value": "={{ $('Set Variables').item.json.companyId }}" +} +] +} +}, +"executeOnce": true, +"typeVersion": 3.4 +}, +{ +"id": "64af9cc7-a194-4427-ba78-d9a1136b962f", +"name": "Execute Workflow Trigger", +"type": "n8n-nodes-base.executeWorkflowTrigger", +"position": [ +316, +1220 +], +"parameters": {}, +"typeVersion": 1 +}, +{ +"id": "7b6ba502-36c2-41e6-9d67-781d0d40a569", +"name": "Sticky Note", +"type": "n8n-nodes-base.stickyNote", +"position": [ +186.9455564469605, +263.2301011325764 +], +"parameters": { +"color": 7, +"width": 787.3314861380661, +"height": 465.52420584035275, +"content": "## Step 1. Starting Fresh\nFor this demo, we'll clear any existing records in our Qdrant vector store for the selected company. We do this using the Qdrant's delete points API." +}, +"typeVersion": 1 +}, +{ +"id": "a99389d4-8ea6-4379-b725-f30e92b0d29e", +"name": "Sticky Note1", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1006.3778510483207, +148.50042906971555 +], +"parameters": { +"color": 7, +"width": 638.5221986278162, +"height": 580.2538779032135, +"content": "## Step 2. Scraping TrustPilot For Company Reviews\n[Read more about HTTP Request Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)\n\nWe'll scrape at the most recent 3 pages of reviews for illustrative purposes but we could easily scrape them all if required. The HTML node offers a convenient way to extract data from the returned html pages and using it, we'll retrieve all the reviews data." +}, +"typeVersion": 1 +}, +{ +"id": "139ccadd-9135-4681-b2eb-403b8d8bd710", +"name": "Get TrustPilot Page", +"type": "n8n-nodes-base.httpRequest", +"position": [ +1140, +360 +], +"parameters": { +"url": "=https://uk.trustpilot.com/review/{{ $('Set Variables').item.json.companyId }}?sort=recency", +"options": { +"pagination": { +"pagination": { +"parameters": { +"parameters": [ +{ +"name": "page", +"value": "={{ $pageCount + 1 }}" +} +] +}, +"maxRequests": 3, +"limitPagesFetched": true +} +} +} +}, +"executeOnce": false, +"typeVersion": 4.2 +}, +{ +"id": "1c71db65-713b-4c31-9c11-5ff678fb327a", +"name": "Sticky Note2", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1680, +140 +], +"parameters": { +"color": 7, +"width": 638.5221986278162, +"height": 689.8000993522735, +"content": "## Step 3. Store Reviews in Qdrant\n[Learn more about the Qdrant Vector Store](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreqdrant/)\n\nVector databases are a great way to store data if you're interested in perform similiarity searches which applies here as we want to group similar reviews to find patterns. Qdrant is a powerful vector database and tool of choice because of its robust API implementation and advanced filtering capabilities." +}, +"typeVersion": 1 +}, +{ +"id": "a4f82a1b-5a76-46b6-a7a3-84ab09b46699", +"name": "Qdrant Vector Store", +"type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant", +"position": [ +1860, +360 +], +"parameters": { +"mode": "insert", +"options": {}, +"qdrantCollection": { +"__rl": true, +"mode": "id", +"value": "=trustpilot_reviews" +} +}, +"credentials": { +"qdrantApi": { +"id": "NyinAS3Pgfik66w5", +"name": "QdrantApi account" +} +}, +"typeVersion": 1 +}, +{ +"id": "cbad9e73-c5b3-474c-95ef-7269addc4e62", +"name": "Sticky Note3", +"type": "n8n-nodes-base.stickyNote", +"position": [ +216, +1000 +], +"parameters": { +"color": 7, +"width": 543.4265511994403, +"height": 453.31956386852846, +"content": "## Step 5. The Insight Subworkflow\n[Learn more about Workflow Triggers](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflowtrigger)\n\nThis subworkflow takes the companyId to find the relevant records in our Qdrant vector store. It also takes a \"from\" and \"to\" date to scope the insights to a particular range - doing this we can say something like \"we only want insights for the past month of reviews\". " +}, +"typeVersion": 1 +}, +{ +"id": "9c530716-63f4-4368-8d0e-0cdbe8f5b08e", +"name": "Sticky Note4", +"type": "n8n-nodes-base.stickyNote", +"position": [ +780, +920 +], +"parameters": { +"color": 7, +"width": 557.7420442679241, +"height": 526.2781960611934, +"content": "## Step 6. Apply Clustering Algorithm to Reviews\n[Read more about using Python in n8n](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code)\n\nWe'll retrieve our vectors embeddings for the desired company reviews and perform an advanced clustering algorithm on them. This powerful echnique allows us to quickly group similar embeddings into clusters which we can then use to discover popular feedback, opinions and pain-points!" +}, +"typeVersion": 1 +}, +{ +"id": "9790b3a5-cc7c-4e12-8038-fc661c8226f8", +"name": "Sticky Note5", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1360, +920 +], +"parameters": { +"color": 7, +"width": 598.5585287222906, +"height": 605.9905193915599, +"content": "## Step 7. Fetch Reviews By Cluster\n[Learn more about using the Code Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/)\n\nWith the Qdrant point IDs grouped and returned by our code node, all that's left is to fetch the payload of each. Note that the clustering algorithm isn't perfect and may require some tweaking depending on your data." +}, +"typeVersion": 1 +}, +{ +"id": "267057b6-9727-4a45-9d87-5429da42f48e", +"name": "Sticky Note7", +"type": "n8n-nodes-base.stickyNote", +"position": [ +1980, +969 +], +"parameters": { +"color": 7, +"width": 587.6069484146701, +"height": 552.9535170892194, +"content": "## Step 8. Getting Insights from Grouped Reviews\n[Read more about using Information Extractor Node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.information-extractor)\n\nNext, we'll use our state-of-the-art LLM to generate insights on our reviews. Doing it this way, we'll able to pull more granular results addressing many key topics within the reviews." +}, +"typeVersion": 1 +}, +{ +"id": "b8cc07d0-ffa3-425f-ae74-76dcb68fa88f", +"name": "Sticky Note8", +"type": "n8n-nodes-base.stickyNote", +"position": [ +2600, +980 +], +"parameters": { +"color": 7, +"width": 572.5638733479158, +"height": 464.4019616956416, +"content": "## Step 9. Write To Insights Sheet\nFinally, our completed insights to appended to the Insights Sheet we created earlier in the workflow.\n\nYou can find a sample sheet here: https://docs.google.com/spreadsheets/d/e/2PACX-1vQ6ipJnXWXgr5wlUJnhioNpeYrxaIpsRYZCwN3C-fFXumkbh9TAsA_JzE0kbv7DcGAVIP7az0L46_2P/pubhtml" +}, +"typeVersion": 1 +}, +{ +"id": "0dac0854-7106-44e3-bd68-fad7b201a6bc", +"name": "Sticky Note6", +"type": "n8n-nodes-base.stickyNote", +"position": [ +2340, +240 +], +"parameters": { +"color": 7, +"width": 519.6419932444072, +"height": 429.11782776909047, +"content": "## Step 4. Trigger Insights SubWorkflow\n[Learn more about Workflow Triggers](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow)\n\nA subworkflow is used to trigger the analysis for the survey. This separation is optional but used here to better demonstrate the two part process." +}, +"typeVersion": 1 +}, +{ +"id": "4aa7e73e-c29d-41df-b2f8-a62109285ccb", +"name": "Sticky Note9", +"type": "n8n-nodes-base.stickyNote", +"position": [ +460, +380 +], +"parameters": { +"width": 226.36363118160727, +"height": 327.0249036433755, +"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n### 🚨 Set company here!\nTrustpilot must recognise it as part of the url." +}, +"typeVersion": 1 +}, +{ +"id": "4d895cf9-452c-401e-a6f3-b9d3a359a96d", +"name": "Apply K-means Clustering Algorithm", +"type": "n8n-nodes-base.code", +"position": [ +1116, +1160 +], +"parameters": { +"language": "python", +"pythonCode": "import numpy as np\nfrom sklearn.cluster import KMeans\n\n# get vectors for all answers\npoint_ids = [item.id for item in _input.first().json.result.points]\nvectors = [item.vector.to_py() for item in _input.first().json.result.points]\nvectors_array = np.array(vectors)\n\n# apply k-means clustering where n_clusters = 5\n# this is a max and we'll discard some of these clusters later\nkmeans = KMeans(n_clusters=min(len(vectors), 5), random_state=42).fit(vectors_array)\nlabels = kmeans.labels_\nunique_labels = set(labels)\n\n# Extract and print points in each cluster\nclusters = {}\nfor label in set(labels):\n clusters[label] = vectors_array[labels == label]\n\n# return Qdrant point ids for each cluster\n# we'll use these ids to fetch the payloads from the vector store.\noutput = []\nfor cluster_id, cluster_points in clusters.items():\n points = [point_ids[i] for i in range(len(labels)) if labels[i] == cluster_id]\n output.append({\n \"id\": f\"Cluster {cluster_id}\",\n \"total\": len(cluster_points),\n \"points\": points\n })\n\nreturn {\"json\": {\"output\": output } }" +}, +"typeVersion": 2 +}, +{ +"id": "95c57019-d9d7-4d9f-93dd-21d3d9708861", +"name": "Sticky Note10", +"type": "n8n-nodes-base.stickyNote", +"position": [ +-260, +40 +], +"parameters": { +"width": 400.381109509268, +"height": 612.855812336249, +"content": "## Try It Out!\n\n### This workflow generates highly-detailed customer insights from Trustpilot reviews. Works best when dealing with a large number of reviews.\n\n* Import Trustpilot reviews and vectorise in Qdrant vectorstore.\n* Identify clusters of popular topics in reviews using K-means clustering algorithm. \n* Each valid cluster is analysed and summarised by LLM.\n* Export LLM response and cluster results back into sheet.\n\nCheck out the reference google sheet here: https://docs.google.com/spreadsheets/d/e/2PACX-1vQ6ipJnXWXgr5wlUJnhioNpeYrxaIpsRYZCwN3C-fFXumkbh9TAsA_JzE0kbv7DcGAVIP7az0L46_2P/pubhtml\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!" +}, +"typeVersion": 1 +}, +{ +"id": "9bba9480-792e-48e3-ad9f-8809ce3aba09", +"name": "Customer Insights Agent", +"type": "@n8n/n8n-nodes-langchain.informationExtractor", +"position": [ +2140, +1180 +], +"parameters": { +"text": "=The {{ $json.result.length }} reviews were:\n{{\n$json.result.map(item =>\n`* ${item.payload.metadata.review_author} gave ${item.payload.metadata.review_rating} stars: \"${item.payload.content.replaceAll('\"', '\\\"').replaceAll('\\n', ' ')}\"`\n).join('\\n')\n}}", +"options": { +"systemPromptTemplate": "=You help summarise a selection of trustpilot reviews for a company called \"{{ $json.result[0].payload.metadata.company_id }}\".\nThe {{ $json.result.length }} reviews were selected because their contents were similar in context.\n\nYour task is to: \n* summarise the given reviews into a short paragraph. Provide an insight from this summary and what we could learn from the reviews.\n* determine if the overall sentiment of all the listed responses to be either strongly negative, negative, neutral, positive or strongly positive." +}, +"schemaType": "fromJson", +"jsonSchemaExample": "{\n\t\"Insight\": \"\",\n \"Sentiment\": \"\",\n \"Suggested Improvements\": \"\"\n}" +}, +"typeVersion": 1 +}, +{ +"id": "4488deb9-27f6-4f9d-b17e-9b5e7a1bba33", +"name": "Sticky Note12", +"type": "n8n-nodes-base.stickyNote", +"position": [ +180, +760 +], +"parameters": { +"color": 5, +"width": 323.2987132716669, +"height": 80, +"content": "### Run this once! \nIf for any reason you need to run more than once, be sure to clear the existing data first." +}, +"typeVersion": 1 +}, +{ +"id": "5cb3bd73-1e77-4eba-9d2e-634fdc374330", +"name": "Sticky Note11", +"type": "n8n-nodes-base.stickyNote", +"position": [ +780, +1480 +], +"parameters": { +"color": 5, +"width": 323.2987132716669, +"height": 110.05160146874424, +"content": "### First Time Running?\nThere is a slight delay on first run because the code node has to download the required packages." +}, +"typeVersion": 1 +} +], +"pinData": {}, +"connections": { +"Zip Entries": { +"main": [ +[ +{ +"node": "Reviews to List", +"type": "main", +"index": 0 +} +] +] +}, +"Find Reviews": { +"main": [ +[ +{ +"node": "Apply K-means Clustering Algorithm", +"type": "main", +"index": 0 +} +] +] +}, +"Set Variables": { +"main": [ +[ +{ +"node": "Clear Existing Reviews", +"type": "main", +"index": 0 +} +] +] +}, +"Set Variables1": { +"main": [ +[ +{ +"node": "Find Reviews", +"type": "main", +"index": 0 +} +] +] +}, +"Extract Reviews": { +"main": [ +[ +{ +"node": "Zip Entries", +"type": "main", +"index": 0 +} +] +] +}, +"Reviews to List": { +"main": [ +[ +{ +"node": "Qdrant Vector Store", +"type": "main", +"index": 0 +} +] +] +}, +"Clusters To List": { +"main": [ +[ +{ +"node": "Only Clusters With 3+ points", +"type": "main", +"index": 0 +} +] +] +}, +"Embeddings OpenAI": { +"ai_embedding": [ +[ +{ +"node": "Qdrant Vector Store", +"type": "ai_embedding", +"index": 0 +} +] +] +}, +"OpenAI Chat Model": { +"ai_languageModel": [ +[ +{ +"node": "Customer Insights Agent", +"type": "ai_languageModel", +"index": 0 +} +] +] +}, +"Default Data Loader": { +"ai_document": [ +[ +{ +"node": "Qdrant Vector Store", +"type": "ai_document", +"index": 0 +} +] +] +}, +"Get TrustPilot Page": { +"main": [ +[ +{ +"node": "Extract Reviews", +"type": "main", +"index": 0 +} +] +] +}, +"Qdrant Vector Store": { +"main": [ +[ +{ +"node": "Prep Values For Trigger", +"type": "main", +"index": 0 +} +] +] +}, +"Get Payload of Points": { +"main": [ +[ +{ +"node": "Customer Insights Agent", +"type": "main", +"index": 0 +} +] +] +}, +"Clear Existing Reviews": { +"main": [ +[ +{ +"node": "Get TrustPilot Page", +"type": "main", +"index": 0 +} +] +] +}, +"Prep Output For Export": { +"main": [ +[ +{ +"node": "Export To Sheets", +"type": "main", +"index": 0 +} +] +] +}, +"Customer Insights Agent": { +"main": [ +[ +{ +"node": "Prep Output For Export", +"type": "main", +"index": 0 +} +] +] +}, +"Prep Values For Trigger": { +"main": [ +[ +{ +"node": "Trigger Insights", +"type": "main", +"index": 0 +} +] +] +}, +"Execute Workflow Trigger": { +"main": [ +[ +{ +"node": "Set Variables1", +"type": "main", +"index": 0 +} +] +] +}, +"Only Clusters With 3+ points": { +"main": [ +[ +{ +"node": "Get Payload of Points", +"type": "main", +"index": 0 +} +] +] +}, +"Recursive Character Text Splitter": { +"ai_textSplitter": [ +[ +{ +"node": "Default Data Loader", +"type": "ai_textSplitter", +"index": 0 +} +] +] +}, +"When clicking ‘Test workflow’": { +"main": [ +[ +{ +"node": "Set Variables", +"type": "main", +"index": 0 +} +] +] +}, +"Apply K-means Clustering Algorithm": { +"main": [ +[ +{ +"node": "Clusters To List", +"type": "main", +"index": 0 +} +] +] +} +} +} \ No newline at end of file