מעלים מסמך לאתר ורוצים לקבל כותרת מוצעת וסיווג לפי נושא. במסך יש כפתור אחד אבל מאחוריו מתרחש תהליך שלם. צריך לקלוט את הבקשה ולחלץ טקסט ואז להעביר אותו לעיבוד ולשמור את התוצאה. אם המסמך ארוך התהליך יכול להימשך גם אחרי שהדפדפן כבר קיבל תשובה מהשרת.
FastAPI היא מסגרת לפיתוח API ב־Python. היא מתאימה לבניית השירות שמקשר בין המסך לבין עבודת העיבוד. הממשק עצמו יכול להיכתב ב־JavaScript או ב־TypeScript. אין צורך שכל המערכת תשתמש באותה שפה כדי לעבוד כמוצר אחד.
כדי להבין איך החלקים מתחברים נשתמש בדוגמה של ארכיון מסמכים מקצועיים. העורך מוסיף מסמך והמערכת מציעה נושא ותקציר לצורך ארגון המאגר. המטרה אינה להחליף את קריאת המסמך בהחלטה אוטומטית. אנחנו רוצים תהליך שקל לעקוב אחריו ושאפשר לתקן בו מידע בלי להתחיל מחדש.
למה לבחור Python לחלק הזה של האתר
Python מציעה מערכת כלים רחבה לעבודה עם טקסט ונתונים ולחיבור למודלי AI. אם עיבוד המסמכים כבר נכתב בה הגיוני לעטוף אותו בשירות שהאתר יכול לפנות אליו. FastAPI מספקת דרך להגדיר את הפעולות ואת המידע שהן מקבלות ומחזירות.
לא כל אתר עם יכולת AI צריך שרת Python. אם המערכת רק מעבירה שאלה לשירות חיצוני אפשר לעשות זאת גם בשפות אחרות. ההחלטה נעשית מעניינת כשיש ספריות עיבוד או תהליכים שכבר מתאימים לסביבה הזאת. ההשוואה בין שפות לפיתוח אתרים והתפקיד של כל אחת מהן עוזרת להפריד בין בחירת שפה לבין בחירת מסגרת.
בארכיון שלנו אפשר להשאיר את תצוגת המסמכים ואת ניהול המסכים בממשק הקיים. שירות Python מטפל בעבודה על התוכן. החיבור ביניהם צריך להיות ברור מספיק כדי ששינוי במנוע הסיווג לא יחייב לשנות גם את כל העמודים באתר.
הבקשה הראשונה צריכה להיות מוגדרת היטב
נניח שהמסמך כבר נקלט במערכת ויש לו מזהה. כעת העורך מבקש לנתח אותו. הבקשה צריכה לציין על איזה מסמך עובדים ואיזו פעולה מבוקשת. אפשר להוסיף גם את רשימת הנושאים שמותר להציע. בלי הגדרה כזאת שני צדדים של האתר עלולים להבין אחרת את אותה בקשה.
FastAPI משתמשת במודלים של Pydantic לתיאור נתוני הקלט. המודל יכול להגדיר שדה חובה למזהה המסמך ושדה לפעולה המבוקשת. אפשר לקבוע סוגי נתונים ומגבלות ולהחליט אילו ערכים מותרים. כאשר הבקשה אינה מתאימה למבנה FastAPI יכולה להחזיר שגיאת אימות לפני שהקוד העסקי ממשיך לעיבוד.
זו בדיקה בזמן הריצה. היא שונה מבדיקת טיפוסים בזמן כתיבת הקוד. גם אם הממשק נכתב ב־TypeScript ונראה תקין בעורך השרת עדיין מקבל נתונים חיצוניים. ההבחנה בין שתי שכבות הבדיקה מוסברת גם במדריך על TypeScript בפיתוח אתרים.
חשוב להבין ש־Pydantic עשויה גם להמיר נתונים. מספר שנשלח כטקסט יכול להפוך למספר לפי סוג השדה. זה נוח במקומות מסוימים אך לא תמיד מתאים. מזהה מסמך שמתחיל באפסים צריך לעיתים להישאר טקסט כדי לשמור על צורתו. בחירת הטיפוס צריכה לתאר את משמעות המידע ולא רק את מה שנראה קל לשמור.
כשלא רוצים המרה אפשר להגדיר התנהגות מחמירה לשדות המתאימים. אין צורך להפוך את כל המודל למחמיר בלי להבין את ההשפעה. תאריכים ב־JSON ופרמטרים שמגיעים מתוך כתובת אינם בהכרח מיוצגים באותה צורה. המטרה היא לקבל מבנה ברור ולא להפתיע את מי שכבר משתמש ב־API.
גם התשובה היא חוזה
אחרי ניתוח המסמך הממשק צריך לדעת מה להציג. אפשר להחזיר מזהה מסמך ומצב עיבוד ולצדם תוצאה כשהיא מוכנה. עדיף להגדיר מבנה מסודר במקום להחזיר פעם טקסט חופשי ופעם אובייקט עם שדות אחרים.
מודל תגובה ב־FastAPI מאפשר לאמת את המבנה שמוחזר ולסנן אותו לפי השדות שהוגדרו. הוא גם משתלב בתיעוד ה־API. כך אפשר להשאיר פרטים פנימיים בתוך שירות העיבוד ולהחזיר לממשק רק את המידע שהוא צריך. אובייקט פנימי של ספריית הסיווג אינו חייב להפוך למבנה הציבורי של המערכת.
אם הקוד מחזיר נתונים שאינם מתאימים למודל התגובה זו תקלה בצד השרת. חשוב להבדיל בינה לבין בקשה לא תקינה של המשתמש. אם העורך שלח מזהה נכון אבל השירות שכח להחזיר מצב עיבוד אין סיבה לבקש ממנו להעלות את המסמך שוב.
לא כל שדה צריך להכיל תוצאה בכל שלב. בזמן שהעבודה ממתינה אין עדיין תקציר להציג. אפשר לתאר זאת במודל במקום להחזיר טקסט מלאכותי שנראה כמו תקציר ריק. הממשק יוכל להציג מצב המתנה ברור ורק לאחר ההשלמה לעבור לתצוגת התוצאה. כך ההבחנה נשמרת גם בנתונים ולא רק במראה של המסך.
במודל הסיווג כדאי להפריד בין נושא מוצע לבין נושא שאושר. אלו אינם שני שמות לאותו שדה. ההצעה מגיעה מתהליך העיבוד והבחירה המאושרת עשויה להגיע מעורך. ההפרדה מאפשרת לשפר בהמשך את המודל בלי למחוק תיקונים שאדם כבר ביצע.
קליטת המסמך אינה סיום הניתוח
פעולה קצרה יכולה להסתיים במסגרת הבקשה הרגילה. אבל בניתוח מסמכים עדיף לעיתים לקבל את העבודה ולתת לה מזהה. הדפדפן לא צריך להחזיק חיבור פתוח עד שכל שלב מסתיים. הוא יכול לבקש בהמשך את מצב העבודה לפי המזהה שקיבל.
בתכנון כזה תשובת 202 Accepted יכולה לציין שהבקשה התקבלה לעיבוד. היא אינה אומרת שהסיווג כבר הצליח. צריך לממש במערכת דרך נפרדת לבדיקת ההתקדמות. FastAPI לא יוצרת תור עבודות ומעקב מתמשך רק מפני שהוחזר הקוד הזה.
| מצב בדוגמת הארכיון | מה כבר קרה | מה הממשק יכול להציג |
|---|---|---|
| ממתין | בקשת העיבוד נשמרה | המסמך נוסף לתור |
| בעיבוד | העובד התחיל לחלץ או לנתח תוכן | הניתוח מתבצע |
| מוכן לבדיקה | התקבלה הצעה שנשמרה | נושא ותקציר לעיון העורך |
| נכשל | העבודה הסתיימה בלי תוצאה שמישה | הסבר על השלב שלא הושלם |
שמות המצבים הם החלטה של היישום ולא רשימה מובנית של FastAPI. כדאי לשמור אותם באופן שאפשר לקרוא גם אחרי רענון הדף. אם העורך חוזר לארכיון כעבור זמן הוא צריך למצוא את העבודה הקודמת ולא לראות מסך ריק כאילו לא העלה דבר.

מה async עושה בזמן שהמודל חושב
אם שירות Python ממתין לתשובה ממודל שנמצא בשרת אחר זו עבודת קלט ופלט. קוד אסינכרוני מאפשר להמשיך לטפל במשימות אחרות בזמן ההמתנה. כדי ליהנות מכך צריך להשתמש גם בספריות חיבור שתומכות בדרך העבודה הזאת.
המילה async לבדה אינה הופכת פונקציה לחישוב מקבילי. אם חילוץ הטקסט צורך הרבה זמן מעבד הוספת async להגדרת הפונקציה לא תקצר את החישוב. גם הפעלת ספרייה חוסמת מתוך פונקציה אסינכרונית עלולה לעכב את הטיפול במשימות אחרות.
FastAPI יודעת לעבוד גם עם פעולות שהוגדרו באמצעות def רגיל ומריצה פעולות נתיב כאלה במאגר תהליכונים. לעומת זאת פונקציית עזר רגילה שקוראים לה ישירות מתוך הקוד אינה מועברת לשם מעצמה. ההבחנה חשובה כשמחברים ספריית עיבוד קיימת ומצפים שהמסגרת תטפל בכל ההמתנה והחישוב.
בדוגמת הארכיון אפשר להפריד בין החיבור לשירות הסיווג לבין חילוץ הטקסט המקומי. לכל שלב בוחרים צורת הרצה לפי מה שהוא עושה. אין צורך להמיר כל פונקציה ל־async כדי שהפרויקט ייחשב מודרני.
מתי BackgroundTasks מספיקה ומתי צריך תור עבודה
BackgroundTasks מאפשרת להפעיל עבודה לאחר שליחת התשובה. זה שימושי לפעולה קטנה שאפשר לבצע באותו יישום. היא אינה מחייבת שהמשתמש ימתין למסך עד שהפעולה תסתיים.
אבל זהו מנגנון בתוך תהליך היישום ולא מערכת עמידה לניהול עבודות. אין בו מעצם השימוש שמירה של תור מתמשך או הבטחה שעבודה תחודש אחרי הפסקת התהליך. אם מסמך צריך להמשיך לעיבוד גם כשהשרת מופעל מחדש נדרש תכנון נוסף.
תור עבודות מתאים מאפשר להעביר את המשימה לעובד נפרד. הוא יכול לספק מנגנונים לניסיונות חוזרים ולמעקב בהתאם לכלי ולהגדרות שנבחרו. גם כאן צריך להחליט מה עושים במקרה של כישלון. תור אינו הופך כל ניסיון חוזר לפעולה נכונה באופן אוטומטי.
למשל אם הניתוח כבר נשמר והתקלה התרחשה רק בעדכון מצב העבודה אין צורך ליצור סיווג נוסף בכל ניסיון. מזהה קבוע ועבודה שניתן לחזור עליה בלי ליצור כפילויות עוזרים לשמור על סדר. במקרה שהמסמך השתנה כדאי להבחין בין עיבוד של הגרסה הישנה לבין בקשה חדשה עבור הגרסה המעודכנת.
כדאי לשמור גם באיזה שלב נעצרה העבודה. אם הטקסט חולץ בהצלחה אבל שירות הסיווג לא החזיר תשובה אפשר לעיתים לחדש רק את השלב השני. אין צורך לחלץ שוב את אותו תוכן בכל פעם. החלוקה הזאת עוזרת גם להסביר את המצב לעורך בלי להציג לו הודעת תקלה כללית שאינה אומרת דבר.
OpenAPI עוזר לשני צוותים לדבר על אותו שירות
FastAPI מייצרת תיאור OpenAPI על סמך הגדרת הפעולות והמודלים. התיאור יכול לשמש לתיעוד אינטראקטיבי ולהפקת קוד לקוח. מפתח הממשק יכול לראות אילו שדות צריך לשלוח ואיזה מבנה צפוי לחזור בלי לנחש מתוך שיחת צוות ישנה.
כאשר מפיקים קוד לקוח מהתיאור הזה כדאי לשלב את העדכון שלו בתהליך הפיתוח. שינוי בשם של שדה בתשובת השרת צריך להגיע גם לקוד שקורא אותו. בדרך הזאת קל יותר לזהות חוסר התאמה לפני שהעורך פותח מסמך ומגלה שהכותרת נעלמה. התיעוד נעשה חלק מהחיבור בין המערכות ולא רק עמוד שקוראים בתחילת הפרויקט.
שינוי במודל דורש גם מחשבה על מי שכבר משתמש ב־API. הוספת שדה חובה עלולה לשבור ממשק שעדיין שולח את המבנה הקודם. אפשר לתכנן מעבר הדרגתי או להשאיר גרסה קודמת לזמן מוגדר. ההחלטה תלויה בדרך שבה מעדכנים את הלקוחות ובמספר המערכות שמחוברות לשירות.
בארכיון המסמכים התיעוד צריך להבהיר גם את מהלך הפעולה. תשובת קבלה כוללת מזהה עבודה. פעולה אחרת מחזירה את מצבה. רק כאשר התוצאה מוכנה אפשר להציג את ההצעה לעורך. כל פעולה יכולה להיות מתועדת היטב בפני עצמה ועדיין לא להסביר את הרצף אם לא מתארים את הקשר ביניהן.
מסך התיעוד אינו ממשק המוצר למי שמנהל את הארכיון. הוא מציג פרטי API וכלי בדיקה למפתחים. עורך התוכן צריך רשימה ברורה והסבר על מה שממתין לו. אין סיבה שיצטרך להבין מבנה JSON כדי לאשר נושא למסמך.
בממשק Next.js אפשר לבחור אילו פניות לשירות יתבצעו בשרת ואילו יידרשו בעקבות פעולה בדפדפן. כדאי לשמור את ההחלטה הזאת עקבית עם מבנה האתר. המדריך על חלוקת העבודה בין שרת ללקוח ב־Next.js מסביר כיצד לחשוב על הגבול הזה.
סיווג שימושי שומר גם את הדרך לתיקון
תוצאה מוכנה אינה סוף חיי המסמך. עורך יכול לגלות שהנושא המוצע כללי מדי ולבחור נושא אחר. רצוי לשמור את הבחירה שלו בנפרד מההצעה המקורית. כך אפשר לחזור ולהבין מה תוקן גם אם מחליפים בהמשך את מודל הסיווג.
כדאי גם לשמור לאיזו גרסת מסמך התוצאה שייכת. תקציר טוב של קובץ ישן עלול להטעות כשהקובץ כבר הוחלף. תאריך עיבוד ומזהה גרסה יכולים לעזור להציג לעורך מצב מדויק. אלה החלטות קטנות במבנה הנתונים שחוסכות חוסר בהירות בממשק.
המערכת נעשית שימושית כשהיא מאפשרת לראות מה התקבל ולתקן אותו. אין צורך להציג בכל כרטיס את פרטי המסגרת או את שם ספריית העיבוד. פרטי הפיתוח נשארים בכלי העבודה של הצוות והארכיון מציג לקורא את המידע הרלוונטי לו.
שאלות על FastAPI באתר עם עיבוד מסמכים
מתי Django תהיה בחירה מתאימה יותר?
אם צריך מודלים מסודרים של נתונים וחשבונות משתמשים לצד ממשק ניהול פנימי, כדאי לבחון גם Django. היא כוללת ORM ומערכת אימות משתמשים ו־admin לעריכת נתוני המודלים. זה אינו CMS מוכן או ממשק מוצר מלא. FastAPI מתאימה במיוחד לשירות API מוגדר שמתחבר לממשק קיים. גם Django יכולה להגיש API. ההבדל הוא בתשתית שמגיעה עם המסגרת.
מה קורה אם ה־PDF מכיל תמונות של עמודים ולא טקסט?
ייתכן שיידרש שלב זיהוי טקסט לפני הסיווג. קליטת הקובץ אינה מעידה שהטקסט חולץ בהצלחה. כדאי להבחין במצב כזה בין בעיה בחילוץ לבין כישלון של מודל הסיווג. כך אפשר לטפל בשלב הנכון במקום לשלוח שוב ושוב תוכן ריק לאותו תהליך.
האם תגובת JSON שעברה אימות היא גם סיווג נכון?
לא. Pydantic יכולה לוודא שקיים שדה לנושא ושהוא מכיל ערך מותר. היא אינה קובעת אם המסמך באמת עוסק בנושא הזה. בדיקת מבנה ובדיקת משמעות הן שתי עבודות שונות. אפשר להציג את התוצאה כהצעה ולהשאיר לעורך דרך ברורה לאשר או לתקן אותה.



