בתרגול זה נמשיך את עבודתנו עם סוכני n8n ו-AI. לאחר שבנינו סוכן שירות לקוחות למלון, אנו מתקדמים כעת לאתגר מורכב יותר: בניית סוכן מומחה לחוקי הגולף.
בניגוד לתרגול הקודם, המידע שלנו הפעם הוא מסמך ארוך, מובנה וצפוף (כל חוקי הגולף). אינדוקס פשוט המפצל את הטקסט באופן שרירותי (למשל, כל 1000 תווים) אינו יעיל, מכיוון שהוא "שובר" חוקים באמצע ויוצר חלקי מידע (Chunks) לא קוהרנטיים. סוכן שיקבל מידע כזה יתקשה לתת תשובות מדויקות.
לכן, בתרגול זה נלמד שלוש טכניקות RAG (Retrieval-Augmented Generation) מתקדמות:
- אינדוקס חכם: נשתמש בקוד כדי לפצל את המסמך ליחידות לוגיות (כל חוק בנפרד) לפני שליחתו ל-Pinecone.
- Reranking: נשתמש ב-Cohere Reranking כדי לשפר את הרלוונטיות. נביא מ-Pinecone מספר רב של תוצאות פוטנציאליות, וניתן ל-Cohere לדרג ולהחזיר לנו את ה-3 הרלוונטיות ביותר.
- סינון Metadata: נטפל בשאילתות ספציפיות (למשל, "מה אומר חוק 27?") על ידי חילוץ "ישות" (מספר החוק) מהשאלה, ושימוש בה לסינון התוצאות ב-Pinecone עוד לפני הדירוג.
שימו לב – תרגול זה מובנה מאוד והוא מהווה בסיס למחקר וללימוד דרך ״לכלוך הידיים״ בהמשך הדרך. חשוב להכיר את החלקים השונים בתרגול ובמערכת. עם זאת – בכל פרק וסעיף, הרגישו חופשי לחקור יותר לעומק ולסקור גם מושגים שונים ואפשרויות שונות שלא הוזכרו במפורש. נתקעתם? לא נורא – חזרו להוראות המקוריות, ותמיד אפשר להתחיל פרויקט חדש ונקי, ולהתנסות מראש הפרק הנוכחי.
בהצלחה!
פרק 1: אינדוקס חכם מבוסס קוד
בפרק זה ניקח את מסמך חוקי הגולף (PDF), נשתמש ב-Code Node כדי לפצל אותו ליחידות לוגיות (כלל נפרד לכל פריט), ורק אז נבצע אינדוקס ל-Pinecone, תוך שמירת מספר החוק ושם החוק כשדות Metadata.
-
הורדת קובץ בסיס הידע וחילוץ הטקסט:
- צרו Workflow חדש ב-n8n.
- הוסיפו טריגר Manual Trigger.
- לצורך הורדת קובץ חוקי הגולף, חברו לטריגר בלוק HTTP Request, השאירו את המתודה
GET, ובשורת הכתובת (URL) הכניסו את הכתובת הבאה:
https://img.bluegolf.org/files/gtjga/Rules_of_Golf_Simplified.pdf - בדקו את הצעד ע״י לחיצה על "Execute Step" וצפיה בפלט הבינארי של הבלוק.
- חברו אליו בלוק Extract from File עם הפעולה Extract from PDF ובדקו את הצעד.
-
יצירת הקוד לפיצול החוקים:
- חברו לסוף השרשרת בלוק Code. אם תתבקשו לבחור את שפת הקוד, בחרו ב Javascript.
- כדי לכתוב את הלוגיקה בבלוק ה-Code, ניעזר בחלון ה Ask AI או באפליקציית Ai Chat חיצונית. לצורך כך אנחנו ממליצים על Claude, אבל אפשר לעבוד גם עם ChatGPT או Gemini.
- הדביקו את הבקשה הבאה. היא מבקשת ממנו לקחת את הטקסט שחילצנו מקובץ חוקי הגולף כקלט, ולפצל אותו לפריטים נפרדים בכל פעם שהוא מזהה תבנית של "Rule X".
שימו לב: אם בחרתם להשתמש בצ׳אט Ai חיצוני – עליכם להעתיק את תוכן שדה ה-textמהבלוק הקודם, ולהדביק אותו בגוף השיחה, לפני הבקשה שלכם.
help me write a code node for n8n It is going to receive the JSON below as an input, and I want it to split out each rule as it's own item.
It should split after each time the text says "Rule X"
for every item set the following fields:
* fullText – the full text of the specific rule itself, including the rule title line
* ruleNumber – number of the rule as written in the text
* ruleTitle – only the name, without the prefix "Rule X – "
-
בדיקת הקוד שנוצר:
- אם השתמשתם ב Ask-AI – שימו לב לקוד שנוצר. אם השתמשתם בצ׳אט Ai חיצוני – הדביקו את הקוד שנוצר בחלון הקוד של הבלוק.
- הריצו את הצעד ובדקו את התוצאה שהתקבלה בפלט. אתם אמורים לראות רשימת פריטי JSON, כאשר כל אובייקט מכיל את השדות:
ruleTitleruleNumberfullText
להלן דוגמא לפלט תקין:
[ { "ruleNumber": "1", "ruleTitle": "The Game", "fullText": "Rule 1 – The Game\n1. You start..." }, { "ruleNumber": "2", "ruleTitle": "Match Play", "fullText": "Rule 2 – Match Play\n1. It’s “Me/Us” vers..." }, . . . ] - חשוב: בבדיקת הפלט – בדקו שהמבנה והסדר נשמרים עד סוף הפלט. לפעמים נדרשים מספר נסיונות בניסוחים שונים על מנת לקבל את המבנה הרצוי.
קיצור דרך:אם לא הצלחתם לאחר מספר נסיונות לקבל את הפלט הרצוי, העתיקו את הקוד הבא (נוצר באמצעות Claude) והדביקו אותו בחלון ה Code של הבלוק:
// n8n Code Node - Split Golf Rules // This code takes the input text and splits it into separate items for each rule // Get the input text from the first item const inputText = $input.first().json.text; // Split the text by "Rule" pattern, keeping the "Rule" text with each section const ruleSections = inputText.split(/(?=Rule \d+)/); // Remove the first empty element (everything before the first "Rule") const cleanedSections = ruleSections.filter(section => section.trim().startsWith('Rule')); // Create output items - one for each rule const outputItems = cleanedSections.map((ruleText, index) => { // Extract rule number from the text const ruleMatch = ruleText.match(/Rule (\d+)/); const ruleNumber = ruleMatch ? ruleMatch[1] : (index + 1).toString(); // Extract rule title (everything between "Rule X –" and the first numbered item) const titleMatch = ruleText.match(/Rule \d+ – (.+?)(?=\n1\.|\n\d+\.)/); const ruleTitle = titleMatch ? titleMatch[1].trim() : 'Unknown Rule'; return { json: { ruleNumber: ruleNumber, ruleTitle: ruleTitle, fullText: ruleText.trim(), originalIndex: index } }; }); return outputItems;
-
ביצוע האינדוקס:
- הוסיפו Pinecone Vector Store והגדירו אותו לפעולת Add documents to vector store. חברו אותו לפלט של בלוק הקוד.
- חברו לבלוק ה Pinecone מודל Embedding של Embeddings OpenAI מסוג
text-embedding-3-small - חברו לבלוק ה Pinecone, ליציאת ה-"Document", יחידת טעינת מסמכים (Document Loader) מסוג Default Data Loader.
- בהגדרות ה Data Loader, ודאו את הפרטים הבאים:
- Type of Data: בחרו ב
JSON - Mode: בחרו ב
Specific Data - Data: גררו לכאן את נתון ה
fullTextמתוך פלט הבלוק הקודם. שימו לב לביטוי שמתקבל. - Text Splitting: בחרו ב
Simple
- Type of Data: בחרו ב
- תחת Options, הוסיפו אפשרות Metadata, לחצו על Add property, והגדירו:
- Name: כתבו
ruleNumber - Value: גררו את שדה ה
ruleNumberמתוך פלט הבלוק הקודם. שימו לב לביטוי שמתקבל.
זה מגדיר ל Pinecone לשמור, בנוסף לטקסט המלא של כל פריט, גם את השדה ruleNumber, שישמש אותנו בהמשך לדיוק החיפוש.
- Name: כתבו
- צאו מהגדרות ה Data Loader וחזרו לחלון ההגדרות של Pinecone. תחת Options הוסיפו את האפשרות Pinecone Namespace וקבעו את הערך ל
Golf Rules.
- הפעילו את תהליך האינדוקס פעם אחת בלבד כדי למלא את מסד הנתונים הווקטורי.
- תהליך זה עשוי לקחת מספר דקות. בסיום – גשו ל Pinecone ובדקו את הנתונים שהתקבלו. שימו לב לפרמטר
ruleNumberשהתווסף לכל פריט שנשמר באינדקס.
-
בניית הסוכן ובדיקה ראשונית:
כעת נקים סוכן RAG מבוסס Pinecone באותו ה-Workflow, לצורך בדיקה ראשונית.
- עקבו שוב אחר ההוראות בתרגול הקודם להקמת הסוכן הראשוני שלנו, ובצעו שלב אחר שלב. תוכלו גם להעתיק את המבנה שכבר יצרתם בתרגול הקודם, ולהדביק אותו בתוך ה Workflow שלנו.
שימו לב לשינוי הנדרש:
- בכלי ה-Pinecone Vector Store – ודאו שאתם פונים ל Pinecone Namespace המתאים (
Golf Rules).
- בכלי ה-Pinecone Vector Store – ודאו שאתם פונים ל Pinecone Namespace המתאים (
- הפעילו את ענף הסוכן – פתחו שיחה חדשה.
- שאלו את הסוכן שאלה כללית על גולף (למשל, "מה קורה אם הכדור פוגע בי?").
- הסוכן אמור לענות, אך ייתכן שהתשובות עדיין לא אופטימליות, כי `Limit=3` עשוי לפספס מידע רלוונטי.
- עקבו שוב אחר ההוראות בתרגול הקודם להקמת הסוכן הראשוני שלנו, ובצעו שלב אחר שלב. תוכלו גם להעתיק את המבנה שכבר יצרתם בתרגול הקודם, ולהדביק אותו בתוך ה Workflow שלנו.
פרק 2: שיפור רלוונטיות עם Cohere Reranker
הבעיה בשלב הקודם היא שהסתמכנו רק על החיפוש הווקטורי של Pinecone. כעת, נשדרג את ה-Flow: נבקש מ-Pinecone הרבה תוצאות (למשל 20), וניתן למודל ייעודי של Cohere (בתפקיד "Reranker") לדרג אותן מחדש ולהחזיר רק את ה-3 הרלוונטיות ביותר לשאלת המשתמש.
-
הוספת Cohere Reranker:
- בהגדרות כלי ה Pinecone Vector Store, מצאו והפעילו את האפשרות Rerank Results. בתחתית הכלי נוספת יציאה חדשה – Reranker.
- לחצו על יציאת ה Reranker ומהגלריה – בחרו ב-Reranker Cohere.
- הגדירו את ה-Credentials שלכם (API Key של Cohere).
- ב-Cohere, ודאו את ההגדרות הבאות:
- Model: בחרו
rerank-v3.5 - Top N: בחרו ב-3. זהו מספר התוצאות הכי רלוונטיות – שהמדרג יחזיר.
- Model: בחרו
-
שינוי הגדרות ה-Pinecone Retrieve:
- חזרו לכלי ה-Pinecone Vector Store.
- שנו את הערך Limit ל-20.
- זה יגרום ל-Pinecone להחזיר את 20 התוצאות הכי קרובות וקטורית, מה שנותן ל-Reranker "בשר" לעבוד איתו.
-
בדיקה חוזרת
- אפסו את השיחה ושאלו את הסוכן עוד שאלות על חוקי הגולף (היעזרו במסמך עצמו לצורך כך).
- התשובות אמורות להיות כעת מדויקות ורלוונטיות הרבה יותר, מכיוון שהן עברו שכבת סינון נוספת שהבינה את הכוונה של השאלה ולא הסתמכה רק על קרבה טכנית-וקטורית.
- באילו הבדלים הבחנתם?
פרק 3: טיפול בשאילתות ספציפיות עם Metadata
ה-Flow שלנו מצוין לשאלות כלליות, אבל מה קורה אם המשתמש שואל "תסביר לי בבקשה את חוק מספר 27"? ה-Reranker עלול להתבלבל מ"רעש" של חוקים אחרים ש״נראים״ דומים מבחינה טכנית-וקטורית ולהחזיר תשובה שגויה, או לחילופין – לבצע חיפוש ארוך ומיותר בבסיס הנתונים.
הפתרון: לזהות את הבקשה לחוק ספציפי, ולסנן ב-Pinecone באמצעות ה-Metadata שיצרנו בפרק 1.
-
זיהוי הבעיה:
- הפעילו את ה-Flow הקיים ושאלו במפורש: "מה אומר חוק 27?" או "תסביר לי את חוק מספר 14".
- שימו לב שהסוכן עשוי להחזיר מידע מחוקים אחרים, או מידע כללי מדי, מכיוון שהחיפוש הראשוני (Limit=20) עדיין מביא תוצאות לא רלוונטיות שמבלבלות את ה-Reranker.
- התשובה שתתקבל – שגויה או לא מדויקת. אפשרות אחרת היא שתתקבל תשובה מדויקת – אבל רק לאחר תהליך ארוך מדי (ויקר מדי) של חיפוש ועיבוד מידע רב.
-
חילוץ מספר החוק (Metadata Extraction):
- נשנה מעט את ה-Flow של הסוכן. נתקו את טריגר ה Chat וחברו אותו לבלוק חדש של Ai Agent. אל תמחקו את ה Flow הקודם שיצרתם. נשתמש בו מיד.
- תנו לבלוק הסוכן החדש את השם "Metadata Agent". הסוכן הזה ישמש אותנו אך ורק לחילוץ מספר החוק מתוך שאלת המשתמש.
- חברו לסוכן החדש מודל שיחה (Chat Model) מינימלי כלשהו (כמו
gpt-4.1-miniשל OpenAI). - הגדירו לו הוראת מערכת (System Prompt) כדי לבצע את המשימה ולהחזיר את מספר החוק בלבד:
# Overview Your job is to understand the rule number that the human is requesting and output only the number. ## Example Input - what's rule number 27? Output - 27
שימו לב לדוגמא (##Example) – במקרים של משימה מאוד ספציפית כמו זו, הדוגמאות ממחישות למודל את מהות המשימה באופן אפקטיבי יותר מההסבר עצמו. - בדיקה ראשונית: בעוד טריגר ה-Chat מחובר לסוכן ה Metadata בלבד, פתחו ואפסו את חלון הצ׳אט ושאלו שאלה כמו "Explain rule 17". שימו לב לפלט שמתקבל מהסוכן – אם מופיע עוד טקסט פרט למספר עצמו, שנו את הוראות המערכת ותנו עוד דוגמאות.
-
הגדרת פילטר דינמי ב-Pinecone:
- כעת נשתמש במספר החוק שחילצנו בסוכן הראשון, ונמשיך את מהלך השיחה. חברו את סוכן ה Metadata לסוכן השיחה הרגיל.
- כיוון שסוכן השיחה כבר לא מחובר באופן ישיר לטריגר ה Chat – יש להגדיר את הקלט שלו באופן הבא:
- Source for Prompt (User Message): בחרו
Define below - Prompt (User Message): גררו את נתון ה-
chatInputמטריגר ה-Chat לשדה זה ושימו לב לביטוי שמתקבל:
{{ $('When chat message received').item.json.chatInput }}
- Source for Prompt (User Message): בחרו
- הכנסו להגדרות של כלי ה-Pinecone Vector Store, ותחת Options הוסיפו את האפשרות Metadata Filter.
- הגדירו את הפילטר באופן הבא:
- Name: כתבו
ruleNumber - Value: גררו את נתון ה-
outputמתוך ה-Metadata Agent
- Name: כתבו
-
בדיקת ה-Flow השלם:
- כעת ה-Flow שלנו מורכב מ 4 מודלי שפה בעלי תפקידים שונים:
- מודל שיחה מינימלי בשלב סוכן ה Metadata לחילוץ מספר החוק
- מודל שיחה גדול יותר, המשמש כ״מוח״ לסוכן השיחה הראשי
- מודל Embedding לעיבוד שאלת המשתמש, ושליחתו לחיפוש ב Pinecone
- מודל Reranking של Cohere, לביצוע דירוג והתאמה משופרת של תוצאות החיפוש לשאלת המשתמש
- נסו לשאול שוב: "Explain rule 27".
- ה-LLM הראשון יחלץ את מספר החוק – 27
- סוכן השיחה יגש ל-Pinecone ויחפס תוצאות רלוונטיות תוך הקפדה על הסינון –
ruleNumber=27 - ה-Reranker יקבל מקטעי טקסט מחוק 27 וידרג את 3 הרלוונטיות ביותר לשאלה
- הסוכן יקבל מידע נקי ומדויק ויענה תשובה מושלמת.
- נסו לשאול שאלה כללית: "מה קורה כשהכדור אבד?". במקרה הזה הסינון שהגדרנו כבר לא רלוונטי ונצטרך לעבוד בשיטה הקודמת – ללא הסינון.
על מנת לבחור את שיטת המענה המתאימה ביותר – נלמד בתרגולים הבאים להגדיר עבודת צוות של סוכנים, במבנים היררכיים שונים.
- כעת ה-Flow שלנו מורכב מ 4 מודלי שפה בעלי תפקידים שונים:
פרק 4: תרגול פתוח והמשך מחקר
כעת, לאחר שבניתם סוכן RAG מתקדם, נסו לחקור רעיונות נוספים כדי לשפר אותו:
-
טיפול בשגיאות (Error Handling):
- מה קורה אם ה-LLM שמחלץ metadata נכשל ומחזיר טקסט במקום JSON? ה-Workflow ייכשל.
- נסו להוסיף בלוק Code אחרי ה-LLM המחלץ, והגדירו לו Error Handling (למשל, "Continue on Fail (using error output)") כדי שה-Workflow ימשיך גם אם החילוץ נכשל.
-
חילוץ Metadata מורכב יותר:
- שפרו את ה-Code Node מפרק 1 כך שיחלץ גם תתי-סעיפים (למשל, `ruleNumber: "27.1a"`).
- שנו את ה-LLM המחלץ (מפרק 3) כך שידע לחלץ גם תתי-סעיפים מהשאלות.
-
שימוש ב-Function Calling במקום חילוץ:
במקום להשתמש ב-LLM נפרד רק לחילוץ, האם אפשר להשתמש בסוכן הראשי (ה-Chat Model הסופי) עם Function Calling?
- הגדירו לסוכן הראשי Tool (כלי) מסוג Code בשם
Get Golf Rule Context. - הכלי יקבל פרמטר אופציונלי:
rule_number. - כשהסוכן יזהה בקשה לחוק ספציפי, הוא יקרא לכלי עם הפרמטר. כדי לבצע את הסינון בפועל – הסוכן ישתמש בכלי Pinecone נוסף עם סינון, כאשר החיפוש הרגיל יתבצע בלעדיו.
- אם הסוכן לא יזהה מספר חוק, הוא יקרא לכלי ללא הפרמטר, וה-Pinecone לא יסנן.
- הגדירו לסוכן הראשי Tool (כלי) מסוג Code בשם
בסיום תרגול זה, בניתם בהצלחה תהליך RAG מתקדם ומלא. למדתם כיצד לעבד מידע מורכב (Chunking חכם), לשפר רלוונטיות (Reranking), ולטפל בכוונה ספציפית של משתמש (Metadata Filtering). טכניקות אלו חיוניות לבניית סוכני AI חכמים באמת, המסוגלים לתת תשובות מדויקות ממסדי ידע גדולים ומורכבים.