Darmowy szablon automatyzacji

Dokument Q&A Chatbot z Gemini AI i Supabase Vector Search dla Telegrama

177
1 mies. temu
28
bloków


Telegram AI Assistant z Google Gemini i Supabase

Ten template tworzy inteligentnego asystenta AI na Telegramie, który odpowiada na pytania użytkowników w oparciu o przesłane dokumenty. Rozwiązanie wykorzystuje moc Google Gemini do przetwarzania tekstu oraz Supabase do przechowywania i wyszukiwania danych.

Kluczowe funkcje

  • Inteligentne przetwarzanie HTML dla lepszego formatowania wiadomości
  • Automatyczne dzielenie długich odpowiedzi na fragmenty
  • Integracja z Google Gemini do tworzenia embeddingów i generowania odpowiedzi
  • Przechowywanie danych w Supabase Vector Database
  • Automatyczne przetwarzanie dokumentów PDF

Demo działania

Zobacz bot w akcji na YouTube. Film demonstruje podstawowe funkcje i interakcje z użytkownikiem.

Jak to działa

  1. Użytkownik przesyła dokument PDF przez bota Telegram
  2. Workflow przetwarza plik, tworzy embeddingi przy użyciu Google Gemini
  3. Embeddingi są przechowywane w tabeli wektorowej Supabase
  4. Gdy użytkownik zadaje pytanie, system wyszukuje odpowiednie fragmenty dokumentu
  5. Google Gemini generuje odpowiedź na podstawie znalezionych fragmentów
  6. Bot wysyła sformatowaną odpowiedź z powrotem do użytkownika na Telegramie

Konfiguracja

Proces konfiguracji zajmuje około 15-20 minut:

  1. Zaimportuj workflow do swojej instancji n8n
  2. Skonfiguruj dane dostępowe dla Telegrama, Google Gemini i Supabase
  3. Przygotuj tabelę wektorową w Supabase używając dostarczonego skryptu SQL
  4. Aktywuj workflow

Szczegółowe instrukcje konfiguracji, w tym informacje o kluczach API i ustawieniach poszczególnych węzłów, znajdują się w notatkach w workflow.

Przykłady zastosowań

Ten template automatyzacji znajdzie zastosowanie w wielu scenariuszach biznesowych i edukacyjnych. Oto kilka potencjalnych zastosowań:

  • Wirtualni asystenci obsługujący dokumentację techniczną
  • Systemy FAQ dla klientów oparte na dokumentach firmowych
  • Edukacyjne boty pomagające w nauce z materiałów PDF
  • Narzędzia wsparcia technicznego analizujące dokumentację produktów
  • Systemy wyszukiwania informacji w wewnętrznych bazach wiedzy
  • Automatyczne generowanie streszczeń i odpowiedzi na pytania z długich dokumentów
  • Narzędzia dla badaczy do analizy artykułów naukowych


   Skopiuj kod szablonu   
{"id":"LL0TBxEbXoK2zhqp","meta":{"instanceId":"af80dcc2dbd3882359ca17a5fe5b2d4bd4ca3cf3cbe39546ecc263e2e97807e5","templateId":"self-building-ai-agent","templateCredsSetupCompleted":true},"name":"AI Document Assistant via Telegram + Supabase","tags":[{"id":"Fo1OtHUY0RXxPbjJ","name":"google-gemini","createdAt":"2025-05-01T23:10:32.399Z","updatedAt":"2025-05-01T23:10:32.399Z"},{"id":"HcgCSAB27xdCFyCf","name":"vectorstore","createdAt":"2025-05-01T23:10:13.148Z","updatedAt":"2025-05-01T23:10:13.148Z"},{"id":"NFkP0TdshXJdwIOG","name":"chatbot","createdAt":"2025-05-01T23:09:53.855Z","updatedAt":"2025-05-01T23:09:53.855Z"},{"id":"QXeMQNrN4XlEXs1I","name":"telegram","createdAt":"2025-05-01T23:09:23.634Z","updatedAt":"2025-05-01T23:09:23.634Z"},{"id":"RLZgltwJo60sK1Dm","name":"embeddings","createdAt":"2025-05-01T23:10:20.621Z","updatedAt":"2025-05-01T23:10:20.621Z"},{"id":"fMH2im2pHJBOzkXp","name":"document-qa","createdAt":"2025-05-01T23:10:07.948Z","updatedAt":"2025-05-01T23:10:07.948Z"},{"id":"ghpuX9kkAqpLyIVR","name":"n8n-ai","createdAt":"2025-05-01T23:10:38.373Z","updatedAt":"2025-05-01T23:10:38.373Z"},{"id":"tSHEttl48VrqMYiV","name":"supabase","createdAt":"2025-05-01T23:10:16.583Z","updatedAt":"2025-05-01T23:10:16.583Z"}],"nodes":[{"id":"0213dfab-a1b2-42c9-9ab1-8a0f1de4c4c0","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[480,40],"parameters":{"options":{},"modelName":"models/gemini-2.5-flash-preview-04-17"},"credentials":{"googlePalmApi":{"id":"QuysglXiB421WI90","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"9c166f83-8ea4-4dc7-8ea2-92ec186c9f32","name":"OpenWeatherMap","type":"n8n-nodes-base.openWeatherMapTool","position":[740,-100],"parameters":{"cityName":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('City', ``, 'string') }}"},"credentials":{"openWeatherMapApi":{"id":"MCzSGdWHBJE7l1aN","name":"OpenWeatherMap account"}},"typeVersion":1},{"id":"aa0abeff-b5e9-497b-9d9c-8f79721a5c11","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[480,-320],"parameters":{"text":"={{ $json.message.text }}","options":{"systemMessage":"=4. If the user sends you a message starting with / sign, it means this is a Telegram bot command. For example, all users send /start command as their first message. Try to figure out what these commands mean and reply accodringly.nUser can only send pdf files and text messages and let them know that this type is not supported if it was not a PDF file or text.nAt first let them know that they can ask questions about sent PDF files you can use your own capabilities as well. nGenerate a detailed, well-structured response ,nFormat the response strictly using Telegram's supported HTML syntax. Use tags like , , , , , ,
 (with optional  inside), , and
where appropriate.nnStructure the content logically using paragraphs and distinct sections. **Be mindful that this text might need to be split into multiple messages due to character limits (Telegram's limit is around 4096 characters per message). Try to make sections or paragraphs relatively self-contained where possible to facilitate splitting.**nn**Ensure all <, >, and & symbols within the *text content* (i.e., not part of an HTML tag or entity) are replaced with the corresponding HTML entities: < with <, > with >, and & with &.**nnMaintain proper nesting of HTML tags according to Telegram's rules. While the final splitting will be handled by a script, aim for a structure that is easy to break into logical parts without leaving tags improperly open mid-message."},"promptType":"define","hasOutputParser":true},"typeVersion":1.9},{"id":"72b85aff-4fe7-4705-a07c-463f381cb806","name":"Telegram Trigger","type":"n8n-nodes-base.telegramTrigger","position":[-20,100],"webhookId":"d4f286b2-8094-40e3-aeb2-813eb1895ecf","parameters":{"updates":["message"],"additionalFields":{}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2},{"id":"ea716dba-2856-40a8-ad73-86132f52dda8","name":"Telegram","type":"n8n-nodes-base.telegram","onError":"continueErrorOutput","position":[1540,-320],"webhookId":"137d8d2f-a941-4803-8646-8932525360c3","parameters":{"text":"={{ $json.text }}","chatId":"={{ $json.chatId }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2,"alwaysOutputData":true},{"id":"59a22620-0d26-4e19-940a-5c07efccbdfa","name":"Think","type":"@n8n/n8n-nodes-langchain.toolThink","position":[640,-100],"parameters":{},"typeVersion":1},{"id":"7bb66887-c9c6-4057-bbc0-306d1e20ea12","name":"Embeddings Google Gemini","type":"@n8n/n8n-nodes-langchain.embeddingsGoogleGemini","position":[840,340],"parameters":{"modelName":"models/text-embedding-004"},"credentials":{"googlePalmApi":{"id":"QuysglXiB421WI90","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"668db8fd-3d5f-433a-8ccb-4bea237107ce","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[1220,460],"parameters":{"options":{}},"typeVersion":1},{"id":"d1495354-bfc0-4ef1-9102-dc3577580d5b","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[1440,620],"parameters":{"options":{}},"typeVersion":1},{"id":"6a8e5ce6-4c52-4ca0-962f-045ea42dac7c","name":"Extract from File","type":"n8n-nodes-base.extractFromFile","position":[1020,480],"parameters":{"options":{},"operation":"pdf"},"typeVersion":1,"alwaysOutputData":true},{"id":"3f4a9da9-0364-4861-a6f3-33b1d5c501e0","name":"Answer questions with a vector store","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[860,-60],"parameters":{"description":"Use this data if the user's question appears to reference an uploaded file, document content, or specific information that might be stored in prior user documents. If not relevant, ignore this source."},"typeVersion":1.1},{"id":"933a93c7-9401-4bac-9b9c-395866b46d61","name":"Supabase Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreSupabase","position":[760,80],"parameters":{"options":{"queryName":"match_documents"},"tableName":{"__rl":true,"mode":"list","value":"user_knowledge_base","cachedResultName":"user_knowledge_base"}},"credentials":{"supabaseApi":{"id":"jq6dt73fwyUImYqH","name":"Supabase account"}},"typeVersion":1.1},{"id":"5f37c202-a1ca-4ee0-9de0-267349adffbd","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[360,200],"parameters":{"color":5,"width":1625,"height":779,"content":"✅ Scenario 2 – Document Upload and EmbeddingnnFlow for downloading a document sent via Telegram, extracting its text, generating embeddings, and inserting them into Supabase Vector Store."},"typeVersion":1},{"id":"6e9c1070-90bc-4ab7-a8a0-62461bede708","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[360,-420],"parameters":{"color":5,"width":1625,"height":599,"content":"✅ Scenario 1 – Chatbot InteractionnnFlow for handling user messages sent to the bot. Includes accessing weather data, answering questions based on user-uploaded documents, and running code using a code execution tool."},"typeVersion":1},{"id":"3b211a14-6813-459f-8d23-b40fc0eb4bd6","name":"Telegram - Embedding Complete","type":"n8n-nodes-base.telegram","position":[1760,320],"webhookId":"4eaead72-f9a7-49a3-95ca-b3bc8f6b9a95","parameters":{"text":"=✅ Document saved!nFeel free to start asking questions about it.","chatId":"={{ $('Command Router').item.json.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2},{"id":"05703266-aaed-491d-87a6-ed7f96a9c49a","name":"Supabase - Save Embeddings","type":"@n8n/n8n-nodes-langchain.vectorStoreSupabase","position":[1200,320],"parameters":{"mode":"insert","options":{},"tableName":{"__rl":true,"mode":"list","value":"user_knowledge_base","cachedResultName":"user_knowledge_base"}},"credentials":{"supabaseApi":{"id":"jq6dt73fwyUImYqH","name":"Supabase account"}},"typeVersion":1.1,"alwaysOutputData":false},{"id":"3b7db0e6-b551-4698-921a-306e837ceffc","name":"Command Router","type":"n8n-nodes-base.switch","position":[160,100],"parameters":{"rules":{"values":[{"outputKey":"document","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"895b32db-777d-4d8e-b1d3-596cc9863d09","operator":{"type":"boolean","operation":"exists","singleValue":true},"leftValue":"={{ $json.message.document }}","rightValue":"={{ $json.message.document }}"}]},"renameOutput":true},{"outputKey":"text","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"26c12573-8e00-4832-8410-73d2d739c455","operator":{"type":"boolean","operation":"exists","singleValue":true},"leftValue":"={{ $json.message.text }}","rightValue":""}]},"renameOutput":true}]},"options":{"fallbackOutput":"extra"},"looseTypeValidation":true},"typeVersion":3.2},{"id":"fa06fc6c-3661-4065-81fc-09f93d6a4a25","name":"Telegram - Download file","type":"n8n-nodes-base.telegram","position":[600,540],"webhookId":"11b8f884-34bc-401c-8978-b28507d96e40","parameters":{"fileId":"={{ $('Telegram Trigger').item.json.message.document.file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2},{"id":"756a36aa-187d-48ca-894c-f8c9a79a4794","name":"Aggregate","type":"n8n-nodes-base.aggregate","notes":"This is used to flag the end of progress—no real aggregation.","position":[1580,320],"parameters":{"options":{},"fieldsToAggregate":{"fieldToAggregate":[{}]}},"notesInFlow":true,"typeVersion":1},{"id":"3b49f357-5d21-4710-bd32-3218d23b1bd9","name":"Fallback- No formatting","type":"n8n-nodes-base.telegram","notes":"This is used if, even after HTML formatting,g Telegram wasn't able to process the text, so we send it without formatting.","position":[1740,-260],"webhookId":"dd2182fe-0b11-4d96-9838-30d60bf8c229","parameters":{"text":"={{ $('Manual Mapping').item.json.text }}","chatId":"={{ $('Manual Mapping').item.json.chatId }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"notesInFlow":true,"typeVersion":1.2},{"id":"eafdbacb-17e5-4de6-a4e9-b986140353e5","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[1120,-320],"parameters":{"options":{},"fieldToSplitOut":"output"},"typeVersion":1},{"id":"538be3ed-4bd6-4295-ac11-e4d46b943f5a","name":"Simple Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[540,-100],"parameters":{"sessionKey":"={{ $('Telegram Trigger').item.json.message.from.id }}","sessionIdType":"customKey"},"typeVersion":1.3},{"id":"0afca77d-0e08-4f04-a6d3-b107c1dd54f9","name":"Handle formatting and split","type":"n8n-nodes-base.code","notes":"This is used to prevent Markdown issues in Telegram while sending messages.","position":[900,-320],"parameters":{"language":"python","pythonCode":"import renimport htmlnngemini_output_text = _('AI Agent').first().json.output;n# Regex to match any HTML tag <...>nHTML_TAG_PATTERN = re.compile(r'(<[^>]*?>)', re.IGNORECASE)nn# List of UNSUPPORTED Telegram HTML tag namesnUNSUPPORTED_TAG_NAMES = [n 'p', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol',n 'table', 'thead', 'tbody', 'tr', 'td', 'th', 'div', 'br', 'font',n 'span', # Span is unsupported *unless* it has the specific classn 'a' # A is unsupported *unless* it has the href attributen # Add more unsupported tags if you encounter themn]nn# Regex to match unsupported opening or closing tags based on the names listn# This pattern is simplified and might misinterpret complex attributesnUNSUPPORTED_TAG_PATTERN = re.compile(r'<\/?(' + '|'.join(UNSUPPORTED_TAG_NAMES) + r')\b[^>]*?>', re.IGNORECASE)nn# Regex to match a span tag *without* the class="tg-spoiler" attributen# This tries to capture the tag and its content to remove bothnUNSUPPORTED_SPAN_FULL_PATTERN = re.compile(r']*?>.*?<\/span>', re.IGNORECASE | re.DOTALL) # DOTALL allows . to match newlinesnn# Regex to match an a tag *without* an href attributen# This tries to capture the tag and its content to remove bothnUNSUPPORTED_A_FULL_PATTERN = re.compile(r']*href=)[^>]*?>.*?<\/a>', re.IGNORECASE | re.DOTALL)nnn# --- Cleaning Function (Regex Only) ---nndef unescape_common_html_entities(text):n """n Unescapes a limited set of common HTML entities in text.n Does NOT use html.unescape for maximum compatibility with "no external library" rule.n """n # Order matters: & must be replaced first!n text = text.replace('&', '&')n text = text.replace('<', '<')n text = text.replace('>', '>')n text = text.replace('"', '"')n text = text.replace(''', "'")n # Add more common entities here if needed, e.g., text = text.replace(' ', ' ')n return textnnndef clean_html_regex_only(html_string):n """n Cleans HTML string using regex: removes unsupported tags and escapes text content.n Handles ' and other basic entities.n WARNING: This is a regex-based approach and is NOT as robust as using an HTML parser.n It may fail on complex or malformed HTML.nn Args:n html_string (str): The input HTML string.nn Returns:n str: The cleaned HTML string.n """n # 1. Remove unsupported tags and their content where specific attributes are missingn # Process specific full patterns firstn cleaned_text = UNSUPPORTED_SPAN_FULL_PATTERN.sub('', html_string)n cleaned_text = UNSUPPORTED_A_FULL_PATTERN.sub('', cleaned_text)nn # 2. Remove remaining unsupported opening/closing tags, leaving content behindn cleaned_text = UNSUPPORTED_TAG_PATTERN.sub('', cleaned_text)nn # 3. Split the remaining string into tags and text segmentsn # This pattern captures the tags themselves so we can differentiate them from textn parts = HTML_TAG_PATTERN.split(cleaned_text)nn cleaned_parts = []n for part in parts:n if not part:n continuenn if HTML_TAG_PATTERN.fullmatch(part):n # If the part is a tag (matches the full tag pattern)n # We assume at this point it's a supported tag due to previous removal steps.n # Keep the tag as is.n cleaned_parts.append(part)n else:n # If the part is text contentn # 1. Unescape common HTML entities (like ') that might be in the textn unescaped_text = unescape_common_html_entities(part)nn # 2. Escape the literal characters <, >, & that are *in* the text contentn # This ensures only the characters themselves are escaped, not entities.n # Need to escape & first to avoid issues with '&' if it resulted from unescaping or was original.n re_escaped_text = unescaped_text.replace('&', '&').replace('<', '<').replace('>', '>')nn cleaned_parts.append(re_escaped_text)nn # Join the processed parts back into a single stringn return "".join(cleaned_parts)nn# --- Splitting Logic ---nSPLIT_PATTERN_REGEX_ONLY = re.compile(r'(<\/blockquote>|<\/pre>|\n\n|\s{2,}|(?<=[.!?])\s+|<[a-z]+[^>]*?>|<\/[a-z]+>)', flags=re.IGNORECASE)nnndef split_telegram_message_regex_only(text, max_length=4096):n """n Splits text into multiple messages based on character count and basic patterns.n Operates on text already cleaned by clean_html_regex_only.n Does NOT guarantee HTML tag integrity across splits due to lack of parsing.nn Args:n text (str): The input text (preferably cleaned by clean_html_regex_only).n max_length (int): The maximum length for each message part.nn Returns:n list: A list of strings, where each string is a message part.n """n if len(text) <= max_length:n return [text]nn messages = []n current_chunk = ""nn # Split by the defined patternn parts = SPLIT_PATTERN_REGEX_ONLY.split(text)nn for part in parts:n # Handle parts that are None (can happen with split) or just short whitespacen if part is None or (not part.strip() and len(part) < 2 and part != '\n\n'):n if part is not None and len(part) > 0: # Keep meaningful whitespace splits like \n\nn if len(current_chunk) + len(part) <= max_length:n current_chunk += partn else:n # Split happens within meaningful whitespace, finalize chunkn if current_chunk.strip(): # Only add if chunk has contentn messages.append(current_chunk.strip())n current_chunk = part # Start new chunk with the whitespacen continue # Skip to next partnnn # Check if adding the current part exceeds the max lengthn if len(current_chunk) + len(part) > max_length:n # If the current chunk is empty or only whitespace after stripping,n # it means the 'part' itself is too long to fit in a new chunk.n if not current_chunk.strip():n # Handle very long individual parts (e.g., a huge code block line, a very long word, a single huge tag)n # Hard split the long part. WARNING: This can break tags, words, or escape sequences.n while len(part) > max_length:n messages.append(part[:max_length])n part = part[max_length:]n if part.strip():n current_chunk = part # Remaining part starts a new chunkn else:n current_chunk = "" # If remainder is just whitespace, clearn else:n # The current part makes the chunk too long, finalize the current chunkn messages.append(current_chunk.strip())n # Start a new chunk with the current partn current_chunk = part # Keep original part for the new chunknn else:n # Add the current part to the chunkn current_chunk += partnn # Add the last chunkn if current_chunk.strip(): # Only add if the final chunk has contentn messages.append(current_chunk.strip())nn # Clean up any empty messages that might have been createdn messages = [msg for msg in messages if msg.strip()]nn return messagesn ncleaned_html_regex = clean_html_regex_only(gemini_output_text)nmessage_parts_regex = split_telegram_message_regex_only(cleaned_html_regex)nnreturn dict({'output': message_parts_regex })"},"typeVersion":2},{"id":"dbea9e13-6ad4-4eb3-8da1-9db9e2116283","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[2000,-420],"parameters":{"width":1960,"height":3520,"content":"# 🤖 Telegram AI Assistant for Your Documents (n8n + Supabase + Gemini)nnThis project transforms a standard **Telegram bot** into your dedicated AI assistant – designed to understand and answer questions based on **your own documents**. It seamlessly integrates the power of **Google Gemini** for advanced language capabilities and **Supabase's vector database** for efficient, intelligent document retrieval. Built entirely within the no-code platform **n8n**, it allows you to deploy a sophisticated document chatbot without writing a single line of code.nnSimply upload any PDF document to the bot, and instantly gain the ability to chat with it, querying its contents as if it were a knowledgeable expert on your uploaded files.nn---n## 📹 Watch the Bot in Actionnn[![𝗨𝗻𝗹𝗲𝗮𝘀𝗵𝗶𝗻𝗴 𝗔𝗜 𝗼𝗻 𝗠𝘆 𝗕𝗼𝗼𝗸𝘀𝗵𝗲𝗹𝗳: 𝗙𝗹𝗼𝘄 𝗣𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 𝗣𝗼𝘄𝗲𝗿𝘀 𝗮 𝗡𝗲𝘅𝘁-𝗟𝗲𝘃𝗲𝗹 𝗧𝗲𝗹𝗲𝗴𝗿𝗮𝗺 𝗕𝗼𝘁🤖](https://img.youtube.com/vi/r_KGyJApy5M/maxresdefault.jpg)](https://www.youtube.com/watch?v=r_KGyJApy5M)nn**▶️ Click the image above to watch a live demo on YouTube.** nnThis video provides a live demonstration of the bot's core features and how it interacts. See a quick walkthrough of its capabilities and user flow.nn---nn## ✨ Ignite Your Workflow: Use CasesnnThis project empowers two core interactions:nn### 1. Conversational AI Interface (User Inquiry → Telegram Bot → Intelligent Answers)n- Users pose questions directly to the Telegram bot.n- The bot generates relevant, informative answers using the cutting-edge capabilities of the Google Gemini LLM.n- Leveraging a powerful vector search mechanism, it can pull specific, contextual information from previously uploaded documents to provide highly relevant and informed responses.n- (Optional) Augment answers with real-time data, like current **weather information**.nn### 2. Effortless Document Integration (User Upload PDF → Processing → Searchable Knowledge)n- Users upload a PDF document directly to the bot.n- The workflow automatically parses the document content, converts it into numerical representations called embeddings using Gemini's embedding models.n- These embeddings, alongside the document's text content, are then securely stored in a dedicated **Supabase vector table**, creating a searchable knowledge base.n- Immediately after successful processing, the document becomes part of the bot's memory, enabling users to ask questions about its contents via the standard chat interface.nn---n## 🧠 Core Intelligence Featuresnn- ✅ **Pure No-Code**: Developed and managed entirely within the intuitive [n8n](https://n8n.io) automation platform.n- 📄 **Seamless PDF Integration**: Easily upload and process PDF documents to expand the bot's knowledge.n- 🧠 **Powered by Google Gemini**: Utilizes Gemini for both generating document embeddings and formulating intelligent conversational responses.n- 🗂 **Vector Database Memory (Supabase)**: Employs **Supabase as a robust vector database** for storing and efficiently searching document embeddings, providing the bot with long-term memory about your content.n- **⚡️ Rapid & Private Retrieval**: The vector search allows for swift identification and retrieval of the most relevant document snippets based on the user's query. This approach enhances response speed and significantly improves data privacy, as **the original document content remains securely stored in your Supabase instance, and only the user's query and the retrieved relevant chunks are sent to the LLM for generating a response.**n- 🧹 **Intelligent HTML Post-processing**: Cleans the LLM's responses by removing HTML tags not supported by Telegram while preserving essential formatting and correctly escaping special characters in the text content.n- 📤 **Adaptive Message Chunking**: Splits lengthy AI-generated answers into multiple messages that adhere to Telegram's 4096-character limit, ensuring the full response is delivered cleanly.n- 🌦️ **Dynamic Weather Data**: (Optional) Integrates with OpenWeatherMap to provide current weather information upon request.n- **📝 Note on Usage**: This workflow is designed primarily for **personal, single-user** scenarios. It processes each message independently and **does not include multi-user session management**, making it unsuitable for public deployment where different users require separate conversational contexts. For a session-based Telegram bot implemented in Python, you may refer to this project, which is a multi-model telegram bot: [https://github.com/mohamadghaffari/gemini-tel-bot](https://github.com/mohamadghaffari/gemini-tel-bot).n---nn## 🛠 Getting Started: Setupnn### 1. Deploy the Workflow in n8nnn- Click the "Use this workflow" button on the n8n template page.n- This will open the workflow directly in your n8n instance, ready for configuration.nnn### 2. Connect Your Services: Configure CredentialsnnCreate API credentials for the following services within your n8n instance:nn| Service          | Purpose                          |n|------------------|------------------------------------|n| Telegram API     | Receiving user messages & sending replies |n| Google Gemini    | Generating embeddings & LLM responses |n| Supabase         | Storing & searching document vectors |n| OpenWeatherMap   | (Optional) Fetching weather data    |nn### 3. Prepare Your Supabase Knowledge BasennSet up a vector-enabled table in your Supabase project to store your document embeddings. Execute the following SQL commands in your Supabase SQL Editor:nn``` sqln-- Enable the pgvector extension to work with embedding vectorsncreate extension vector;nn-- Create a table to store your documents and their embeddingsncreate table user_knowledge_base (n  id bigserial primary key,n  content text, -- Stores the text chunk from the documentn  metadata jsonb, -- Stores document information (e.g., filename, page number)n  embedding vector(768) -- Stores the vector representation (embedding) generated by Gemini. Adjust dimension if using a different model.n);nn-- Create a function to perform vector similarity search against your documentsncreate function match_documents (n  query_embedding vector(768),n  match_count int default null,n  filter jsonb DEFAULT '{}'n) returns table (n  id bigint,n  content text,n  metadata jsonb,n  similarity floatn)nlanguage plpgsqlnas $$n#variable_conflict use_columnnbeginn  return queryn  selectn    id,n    content,n    metadata,n    -- Calculate cosine similarity: 1 - cosine distance (using the '<=>' operator provided by pgvector)n    1 - (user_knowledge_base.embedding <=> query_embedding) as similarityn  from user_knowledge_basen  where metadata @> filter -- Optional: filter results based on metadatan  order by user_knowledge_base.embedding <=> query_embedding -- Order by similarity (closest first)n  limit match_count; -- Limit the number of resultsnend;n$$;n````nnThis sets up the necessary table and a function to perform vector similarity searches, allowing you to find document chunks most similar to a user's query.n-----nn## 📚 Integrated TechnologiesnnThis project brings together powerful tools:nn - [n8n](https://n8n.io) – The central hub for workflow automation and integration.n - [Telegram Bot API](https://core.telegram.org/bots/api) – The communication layer for user interaction.n - [Supabase](https://supabase.com/) + [pgvector Extension](https://www.google.com/search?q=https://supabase.com/docs/guides/ai/vector-embeddings) – Provides a scalable database with powerful vector search capabilities.n - [Google Gemini API](https://ai.google.dev/) – The intelligence engine for embeddings and text generation.n - [OpenWeatherMap API](https://openweathermap.org/api) – (Optional) For adding real-time weather features.nn-----n"},"typeVersion":1},{"id":"965ba2bd-747d-4718-a76e-9f7d685dcea4","name":"Manual Mapping","type":"n8n-nodes-base.set","position":[1320,-320],"parameters":{"options":{},"assignments":{"assignments":[{"id":"cdeb5bf1-c91c-44ae-bebd-ab3f4ba2561a","name":"text","type":"string","value":"={{ $json.output }}"},{"id":"7cd7d120-96fa-4539-b343-25bc9b75abb4","name":"chatId","type":"number","value":"={{ $('Command Router').item.json.message.from.id }}"}]}},"typeVersion":3.4},{"id":"c6a315f1-6f0b-4127-b377-b7b12975929f","name":"Unsupported message","type":"n8n-nodes-base.telegram","position":[500,760],"webhookId":"52f3456a-06ef-4799-b245-0293213dcc4b","parameters":{"text":"Unsupported command or file. 😓 Please upload a valid PDF document or ask your question regarding your files.","chatId":"={{ $('Command Router').item.json.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2},{"id":"375bd185-3836-4f25-8708-d6dcd79b2675","name":"Send processing document message","type":"n8n-nodes-base.telegram","position":[920,720],"webhookId":"32ade357-f14b-4d10-91f2-02c8aa6e198e","parameters":{"text":"=Processing document...nPlease wait...⏳","chatId":"={{ $('Command Router').item.json.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2},{"id":"d01f8b15-e495-46cf-bfdf-20b4399c23d7","name":"Send embedding Started message","type":"n8n-nodes-base.telegram","position":[1220,660],"webhookId":"32ade357-f14b-4d10-91f2-02c8aa6e198e","parameters":{"text":"=Document processed ✅ nNum of pages: {{ $json.numpages }} nCreator: {{ $json.info.Creator }}nTitle: {{ $json.info.Title }} nVersion: {{ $json.version }}","chatId":"={{ $('Command Router').item.json.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"jOxapcl3g1n1HrCE","name":"Telegram account"}},"typeVersion":1.2}],"active":true,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"749ec7d0-e135-478a-b02e-9241dbf4ab68","connections":{"Think":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"AI Agent":{"main":[[{"node":"Handle formatting and split","type":"main","index":0}]]},"Telegram":{"main":[[],[{"node":"Fallback- No formatting","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"Telegram - Embedding Complete","type":"main","index":0}]]},"Split Out":{"main":[[{"node":"Manual Mapping","type":"main","index":0}]]},"Simple Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Command Router":{"main":[[{"node":"Telegram - Download file","type":"main","index":0}],[{"node":"AI Agent","type":"main","index":0}],[{"node":"Unsupported message","type":"main","index":0}]]},"Manual Mapping":{"main":[[{"node":"Telegram","type":"main","index":0}]]},"OpenWeatherMap":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Telegram Trigger":{"main":[[{"node":"Command Router","type":"main","index":0}]]},"Extract from File":{"main":[[{"node":"Supabase - Save Embeddings","type":"main","index":0},{"node":"Send embedding Started message","type":"main","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Supabase - Save Embeddings","type":"ai_document","index":0}]]},"Supabase Vector Store":{"ai_vectorStore":[[{"node":"Answer questions with a vector store","type":"ai_vectorStore","index":0}]]},"Embeddings Google Gemini":{"ai_embedding":[[{"node":"Supabase - Save Embeddings","type":"ai_embedding","index":0},{"node":"Supabase Vector Store","type":"ai_embedding","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0},{"node":"Answer questions with a vector store","type":"ai_languageModel","index":0}]]},"Telegram - Download file":{"main":[[{"node":"Extract from File","type":"main","index":0},{"node":"Send processing document message","type":"main","index":0}]]},"Supabase - Save Embeddings":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Handle formatting and split":{"main":[[{"node":"Split Out","type":"main","index":0}]]},"Send embedding Started message":{"main":[[]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"Answer questions with a vector store":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]}}}
Planeta AI 2025 
magic-wandmenu linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram