Generative UI — ממשק שנבנה בזמן אמת לפי כוונת המשתמש

מאת צוות מדיה דיל · 12.08.2026 · Generative UI · 5 דק׳

מדריך ארכיטקטוני ל-Generative UI: איך סוכן AI בונה ממשק דינמי בזמן ריצה לפי כוונת המשתמש, במקום להחזיר טקסט חופשי או עמוד סטטי קבוע מראש.

משתמש פונה לצ'אטבוט שירות של חברת תעופה ומבקש "אני צריך לשנות טיסה לשבוע הבא". התשובה הנכונה היא לא פסקת טקסט שמסבירה איך להיכנס לאתר — היא טופס בחירת תאריכים, רשימת טיסות זמינות עם מחירים, וכפתור אישור, שמופיעים בתוך הצ'אט עצמו תוך שניות. זו בדיוק הבעיה שממשקים גנרטיביים באים לפתור: כשסוכן AI מבין את כוונת המשתמש, הוא לא צריך להסתפק בטקסט — הוא יכול לבנות בזמן אמת את רכיב הממשק המדויק שהמשימה דורשת. הרעיון הזה, Generative UI, הוא לא עוד שכבת עיצוב מעל צ'אטבוט; הוא שינוי בסיסי בחוזה שבין ה-Backend הסוכני ל-Frontend, וככזה הוא דורש ארכיטקטורה חדשה, לא רק ספריית קומפוננטות נוספת.

למה טקסט חופשי לא מספיק

מודל שפה שמייצר תשובה טקסטואלית בלבד למשימות אינטראקטיביות מכריח את המשתמש לתרגם בעצמו כוונה למבנה. "יש טיסה ב-10:30 במחיר 450 שקל, טיסה ב-14:15 במחיר 520 שקל..." זה טקסט שדורש מהמשתמש לקרוא, להשוות ולהקליד תשובה מנוסחת בחזרה — בזמן שטבלה עם כפתור בחירה הייתה פותרת את אותה בעיה בלחיצה אחת. ההבדל הזה מצטבר: בכל אינטראקציה שדורשת בחירה בין אפשרויות, מילוי כמה שדות, או אישור פעולה בלתי הפיכה, טקסט חופשי הוא הערוץ הכי לא יעיל להעברת מידע ולקבלת קלט.

Generative UI הופך את הכיוון: המודל לא רק מסביר מה אפשר לעשות, הוא פולט מבנה נתונים שמתאר אילו רכיבי ממשק צריך להציג, עם אילו נתונים ואילו פעולות אפשריות. ה-Frontend מקבל את המבנה הזה ומרנדר אותו לרכיבים אמיתיים — טפסים, כרטיסים, טבלאות, בוררי תאריך — שהמשתמש מתפעל ישירות. זה קרוב יותר לאופן שבו React Server Components מפרידים בין לוגיקת שרת לרינדור לקוח, רק שכאן ה"שרת" הוא מודל שפה שמחליט דינמית אילו קומפוננטות רלוונטיות, לא קובץ קוד סטטי שנקבע בזמן build.

מהמודל לרכיב: שכבת התיווך

הארכיטקטורה הבסיסית של Generative UI מורכבת משלוש שכבות. הראשונה היא המודל עצמו, שמאומן או מונחה (prompted) לפלוט לא פרוזה חופשית אלא JSON מובנה שמתאר כוונת ממשק — לרוב לפי סכימה מוגדרת מראש, בדומה לגישה שתיארנו במדריך על Structured Outputs. השנייה היא שכבת המיפוי (Component Registry), שמתרגמת כל "סוג רכיב" שהמודל ביקש (flight-picker, confirmation-card, date-range-form) לקומפוננטת React אמיתית וקבועה מראש בקוד. השלישית היא הרינדור עצמו, שמקבל את הפלט הממופה ומרכיב אותו לעץ קומפוננטות חי.

הנקודה הקריטית: המודל לעולם לא שולט ישירות ב-DOM ולא מייצר HTML או JavaScript חופשי. הוא בוחר מתוך אוצר מילים סגור של קומפוננטות מוכרות, עם props מסוימים בלבד. זה מונע קטגוריה שלמה של סיכוני אבטחה — הזרקת קוד, XSS — וגם שומר על עקביות עיצובית: כל כרטיס טיסה שהמודל "בוחר" להציג נראה ומתנהג בדיוק כמו כל כרטיס טיסה אחר באתר, כי זו אותה קומפוננטה בדיוק, רק עם נתונים שונים. מבחינה הנדסית זה גם הופך את הבדיקות לפשוטות בהרבה — בודקים את הקומפוננטה פעם אחת, ולא כל פלט אפשרי של המודל.

State, אינטראקטיביות ומחזור חיים

ממשק גנרטיבי לא נגמר ברינדור חד-פעמי. כשמשתמש בוחר טיסה מתוך הרשימה שנוצרה, הבחירה הזו צריכה לחזור למודל כהקשר חדש, כדי שהוא ימשיך את השיחה בהתאם. זה אומר שכל רכיב גנרטיבי הוא לא רק תיאור ויזואלי אלא גם "ערוץ קלט" בחזרה למנוע השיחה — לחיצה על כפתור בכרטיס טיסה לא רק מעדכנת state מקומי, היא שולחת event structured בחזרה ל-Backend, שמזין אותו כהודעת משתמש סמויה למודל.

זה יוצר אתגר אמיתי בניהול state: הממשק הגנרטיבי חי בתוך אפליקציה שכבר יש לה מנגנון state משלה (Redux, Zustand, React Query), וצריך להחליט איפה ה-state של הרכיבים הדינמיים חי — לוקאלית ברכיב, בחנות גלובלית, או בשרת בלבד. הבחירה הזו משפיעה ישירות על ביצועים ועל יכולת שחזור: אם המשתמש מרענן את הדף, האם הממשק שנוצר נשמר, או שהשיחה כולה מתאפסת? המלצה מעשית היא להתייחס למבנה הממשק שהמודל ייצר כאל נתון בר-serialization לכל דבר, ולנהל אותו באותה שכבת state כמו כל נתון אחר באפליקציה — עקרון שדומה למה שדנו בו במדריך ניהול State ב-Frontend.

עקביות עיצובית מול גמישות

הסכנה הגדולה ביותר ב-Generative UI היא שהמודל "יתפרע" ויבחר קומפוננטות בצורה לא עקבית — פעם יציג טופס עם שני שדות, פעם עם חמישה, בלי הגיון ברור. הפתרון הוא לא לתת למודל חופש מוחלט, אלא לספק לו design system מוגדר עם כללי בחירה ברורים: אילו קומפוננטות קיימות, מתי משתמשים בכל אחת, ואילו שילובים אסורים. זה בדיוק אותו עיקרון שעומד בבסיס Design Systems קלאסיים, רק שכאן "המעצב" שמחליט אילו רכיבים להרכיב יחד הוא המודל עצמו בזמן ריצה, ולא מפתח אנושי בזמן build.

מעשית, כדאי לבנות שכבת ולידציה בין פלט המודל לרינדור: אם המודל ביקש קומפוננטה שלא קיימת ברג'יסטרי, או שילוב props לא חוקי, המערכת צריכה ליפול בחזרה (fallback) לתשובת טקסט רגילה במקום לקרוס. זו לא בעיה תיאורטית — ברגע שמודל שפה מייצר פלט חופשי, יהיו מקרים שהוא יטעה בפורמט, וממשק ייצור חייב להיות עמיד לזה כמו לכל קלט לא אמין אחר. מומלץ גם לתעד לוג של כל מקרה כשל כזה, כי דפוסי הכשל חוזרים על עצמם ומצביעים בדרך כלל על אזור בסכימה שדורש הבהרה בפרומפט או צמצום באוצר המילים המותר.

מתי זה שווה את המורכבות

Generative UI הוא לא ברירת מחדל לכל ממשק — הוא פתרון לבעיה ספציפית: אינטראקציות שבהן המרחב האפשרי גדול מדי לתכנון מראש, אבל עדיין מבוסס על אוצר מילים סופי של רכיבי ממשק ידועים. עבור זרימות קבועות ופשוטות — התחברות, תשלום, הרשמה — ממשק סטטי בנוי מראש עדיין עדיף: הוא מהיר יותר, צפוי יותר, וקל יותר לבדוק. הערך האמיתי מתגלה בממשקי סוכן, כלי תמיכה מורכבים, ומערכות ניתוח נתונים שבהן כל שאילתה עשויה להצדיק ויזואליזציה שונה לגמרי.

יש גם מחיר ביצועים שכדאי להביא בחשבון מראש. רינדור דינמי מבוסס פלט מודל מוסיף שרשרת תלות שלא קיימת בממשק סטטי: קריאה למודל, המתנה לפלט מובנה, ולידציה, ורק אז רינדור בפועל. אם המשימה חוזרת על עצמה בצורה כמעט זהה בכל פעם, עדיף לבנות אותה כקומפוננטה קבועה ולתת לסוכן רק "לבחור להציג אותה", ולא לגרום לו לפרוט מחדש את כל מבנה השדות בכל קריאה. עקרון טוב לעבודה הוא לשמור טבלת "תבניות ידועות" שהמודל יכול להצביע עליהן במקום לבנות מבנה מלא מאפס בכל פעם, ולהשאיר בנייה חופשית מלאה רק למקרים שבאמת דורשים אותה. השקעה מוקדמת בסוויטת בדיקות regression שמריצה תרחישי כוונה מגוונים חוסכת המון זמן דיבוג בהמשך, כשמשתמשים אמיתיים ינסחו כוונות בדרכים שאף אחד לא צפה מראש.

תגיות: Generative UI · AI Agents · Component Registry · Structured Outputs · Design Systems · Frontend Architecture

← חזרה לבלוג · צור קשר