يوفر FastAPI طريقة سريعة لبناء خدمة خلفية باستخدام بايثون. باستخدام بعض المزخرفات، يمكنك تحويل دالة بايثون إلى تطبيق واجهة برمجة تطبيقات.
يُستخدم على نطاق واسع من قِبل العديد من الشركات، بما في ذلك مايكروسوفت وأوبر ونتفليكس. ووفقًا لاستطلاع مطوري بايثون، ارتفعت نسبة استخدام FastAPI من 21% في عام 2021 إلى 29% في عام 2023. وبالنسبة لعلماء البيانات، يُعدّ FastAPI ثاني أكثر إطارات العمل شيوعًا، حيث يستخدمه 31% منهم.
في هذا الدرس سنتناول أساسيات FastAPI لعلماء البيانات الذين قد يرغبون في إنشاء نموذج أولي سريع لمشروعهم.
ما هو FastAPI؟
FastAPI هو إطار عمل ويب شائع لبناء واجهات برمجة التطبيقات (API) باستخدام بايثون، ويعتمد على تلميحات نوع بايثون القياسية. يتميز بسهولة الاستخدام وبديهية الاستخدام، ويُمكّنه من إنشاء تطبيق جاهز للإنتاج في وقت قصير. وهو متوافق تمامًا مع OpenAPI ومخطط JSON.
لماذا نستخدم FastAPI لتعلم الآلة؟
تتكون معظم الفرق العاملة على مشاريع تعلم الآلة من علماء بيانات متخصصين في الإحصاء. قد لا يمتلكون خبرة في تطوير البرامج أو التطبيقات اللازمة لمشاريع تعلم الآلة الخاصة بهم. يُمكّن FastAPI علماء البيانات من إنشاء واجهات برمجة تطبيقات بسهولة للمشاريع التالية:
نشر نماذج التنبؤ
ربما قام فريق علوم البيانات بتدريب نموذج للتنبؤ بطلب المبيعات في أحد المستودعات. ولجعله مفيدًا، عليهم توفير واجهة برمجة تطبيقات (API) لتمكين الأجزاء الأخرى من نظام إدارة المخزون من استخدام وظيفة التنبؤ الجديدة هذه.
محركات الاقتراح
من الاستخدامات الشائعة لتعلم الآلة كنظام يقدم اقتراحات بناءً على اختيارات المستخدمين. على سبيل المثال، إذا أضاف أحدهم منتجات معينة إلى سلة التسوق، يمكن اقتراح المزيد من المنتجات عليه. يتطلب نظام التجارة الإلكترونية هذا استدعاء واجهة برمجة تطبيقات (API) لمحرك الاقتراحات الذي يأخذ معلمات الإدخال.
لوحات معلومات ديناميكية وأنظمة إعداد التقارير
أحيانًا، قد تحتاج تقارير مشاريع علوم البيانات إلى عرضها كلوحات معلومات ليتمكن المستخدمون من الاطلاع على النتائج بأنفسهم. أحد الحلول الممكنة هو توفير واجهة برمجة تطبيقات (API) لنموذج البيانات. يمكن لمطوري واجهات المستخدم الأمامية استخدام هذه الواجهة لإنشاء تطبيقات تتيح للمستخدمين التفاعل مع البيانات.
مزايا استخدام FastAPI
مقارنةً بأطر عمل بايثون الأخرى للويب، يتميز FastAPI بالبساطة وفعاليته الكاملة. يعتمد بشكل أساسي على المزخرفات وتلميحات الأنواع، مما يسمح لك ببناء تطبيق ويب دون تعقيد بناء نموذج ORM (تعيين الكائنات والعلاقات) بالكامل، مع مرونة استخدام أي قاعدة بيانات، بما في ذلك قواعد بيانات SQL وNoSQL. كما يوفر FastAPI إنشاءً تلقائيًا للوثائق، ودعمًا للمعلومات الإضافية والتحقق من صحة معلمات الاستعلام، ودعمًا جيدًا للمزامنة غير المتزامنة.
التطور السريع
إنشاء استدعاءات واجهة برمجة التطبيقات (API) في FastAPI سهلٌ كإضافة مزخرفات في شيفرة بايثون. لا يتطلب أي شخص يرغب في تحويل دالة بايثون إلى تطبيق يستجيب لاستدعاءات واجهة برمجة التطبيقات (API) سوى خبرة ضئيلة أو معدومة في البرمجة الخلفية.
توثيق سريع
يوفر FastAPI توثيقًا تفاعليًا تلقائيًا لواجهة برمجة التطبيقات (API) باستخدام واجهة مستخدم Swagger، وهو معيار صناعي. لا يتطلب الأمر جهدًا إضافيًا لبناء توثيق واضح مع أمثلة لاستدعاءات واجهة برمجة التطبيقات. هذا يُتيح ميزة لفرق علوم البيانات المشغولة التي قد لا تمتلك الطاقة والخبرة الكافيتين لكتابة المواصفات الفنية والوثائق.
اختبار سهل
كتابة الاختبارات من أهم خطوات تطوير البرمجيات، ولكنها قد تكون أيضًا من أكثرها إرهاقًا، خاصةً عندما يكون وقت فريق علوم البيانات ثمينًا. بفضل Starlette وHTTPX، أصبح اختبار FastAPI سهلًا. في معظم الأحيان، لا حاجة إلى تعديلات بسيطة، وتكون كتابة الاختبارات وفهمها سهلة.
نشر سريع
يأتي FastAPI مزودًا بأداة سطر أوامر تربط التطوير والنشر بسلاسة. تتيح لك هذه الأداة التبديل بسهولة بين وضع التطوير ووضع الإنتاج. بعد اكتمال التطوير، يُمكن نشر الكود بسهولة باستخدام حاوية Docker مع صور مُعدّة مسبقًا بلغة بايثون.
كيفية استخدام FastAPI لمشروع لتعلم الآلة
في هذا المثال، سنحوّل نموذج تنبؤ بالتصنيف، يستخدم خوارزمية “أقرب الجيران” للتنبؤ بأنواع طيور البطريق المختلفة بناءً على طول منقارها وزعانفها، إلى تطبيق خلفي. سنوفر واجهة برمجة تطبيقات تأخذ معلمات من معلمات استعلام عنوان URL وتُعيد التنبؤ. يوضح هذا كيف يُمكن لأي عالم بيانات، دون خبرة في تطوير التطبيقات الخلفية، إنشاء نموذج أولي بسرعة.
سنستخدم مُصنِّف “KNeighborsClassifier” البسيط على مجموعة بيانات البطريق كمثال. لن نتطرق إلى تفاصيل كيفية بناء النموذج، ولكن لا تتردد في الاطلاع على دفتر الملاحظات ذي الصلة هنا. في الدرس التالي، سنركز على استخدام FastAPI وشرح بعض المفاهيم الأساسية. سنبني نموذجًا أوليًا للقيام بذلك.
ابدأ مشروع FastAPI باستخدام PyCharm
في هذه التدوينة، سنستخدم PyCharm Professional 2024.1. أفضل طريقة لبدء استخدام FastAPI هي إنشاء مشروع FastAPI باستخدام PyCharm. عند النقر على “مشروع جديد” في PyCharm، ستظهر لك مجموعة واسعة من المشاريع للاختيار من بينها. اختر علامة التبويب FastAPI.

من هنا، يمكنك إدخال اسم مشروعك والاستفادة من خيارات أخرى مثل تهيئة Git والبيئة الافتراضية التي تريد استخدامها.
بعد القيام بذلك، سوف ترى الهيكل الأساسي لمشروع FastAPI تم إعداده لك.

هناك أيضًا ملف test_main.http
تم إعداده لك لاختبار جميع نقاط النهاية بسرعة.

إعداد تبعيات البيئة
بعد ذلك، قم بإعداد تبعية بيئتنا باستخدام requirements.txt
عن طريق تحديد Sync Python Requirements ضمن قائمة أدوات PyCarm.

يمكنك بعد ذلك تحديد الملف requirements.txt
الذي تريد استخدامه.

يمكنك نسخ ملف requirements.txt
واستخدامه. سنستخدم pandas وscikit-learn لجزء تعلم الآلة من المشروع. أضف أيضًا ملف penguins.csv
إلى مجلد مشروعك.
قم بإعداد نموذج تعلم الآلة الخاص بك
رتّب شيفرة تعلّم الآلة في ملف main.py. سنبدأ بنص برمجي لتدريب نموذجنا:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
data = pd.read_csv('penguins.csv')
data = data.dropna()
le = preprocessing.LabelEncoder()
X = data[["bill_length_mm", "flipper_length_mm"]]
le.fit(data["species"])
y = le.transform(data["species"])
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
clf = Pipeline(
steps=[("scaler", StandardScaler()), ("knn", KNeighborsClassifier(n_neighbors=11))]
)
clf.set_params().fit(X_train, y_train)
يمكننا وضع الكود أعلاه بعد app = FastAPI()
. سيتم تنفيذه بالكامل عند بدء التطبيق.

مع ذلك، توجد طريقة أفضل لتشغيل شيفرة بدء التشغيل التي استخدمناها لإعداد نموذجنا. سنتناولها لاحقًا في هذه التدوينة.
اطلب الرد
سنتناول الآن كيفية إضافة نموذجنا إلى وظيفة FastAPI. كخطوة أولى، سنضيف استجابةً إلى جذر عنوان URL، وسنُعيد ببساطة رسالةً حول نموذجنا بصيغة JSON. غيّر الكود في async def root():
من “Hello world” إلى رسالتنا كما يلي:
@app.get("/")
async def root():
return {
"Name": "Penguins Prediction",
"description": "This is a penguins prediction model based on the bill length and flipper length of the bird.",
}
الآن، اختبر تطبيقنا. أولًا، سنبدأ تشغيله، وهو سهل الاستخدام في PyCharm. ما عليك سوى الضغط على زر السهم بجوار اسم مشروعك في الأعلى.

إذا كنت تستخدم الإعدادات الافتراضية، فسيعمل تطبيقك على http://127.0.0.1:8000. يمكنك التحقق من ذلك من خلال نافذة التشغيل.

بعد بدء العملية، انتقل إلى test_main.http
واضغط على زر السهم الأول بجوار GET
. من نافذة الخدمات، ستظهر لك رسالة الاستجابة التي أدخلناها.

يتم أيضًا حفظ ملف الاستجابة JSON للفحص في المستقبل.
طلب مع معلمات الاستعلام
بعد ذلك، نود أن نسمح للمستخدمين بالتنبؤات من خلال توفير معلمات الاستعلام في عنوان URL. لنضف الكود التالي بعد دالة root.
@app.get("/predict/")
async def predict(bill_length_mm: float = 0.0, flipper_length_mm: float = 0.0):
param = {
"bill_length_mm": bill_length_mm,
"flipper_length_mm": flipper_length_mm
}
if bill_length_mm <=0.0 or flipper_length_mm <=0.0:
return {
"parameters": param,
"error message": "Invalid input values",
}
else:
result = clf.predict([[bill_length_mm, flipper_length_mm]])
return {
"parameters": param,
"result": le.inverse_transform(result)[0],
}
هنا، نُعيّن القيمة الافتراضية لـ bill_length_mm
وflipper_length_mm
إلى 0 إذا لم يُدخل المستخدم قيمة. كما نضيف فحصًا للتحقق مما إذا كانت أيٌّ من القيمتين تساوي 0، ونُعيد رسالة خطأ بدلاً من محاولة التنبؤ بالبطريق الذي يُشير إليه المُدخل.
إذا لم تكن المدخلات تساوي 0، فسنستخدم النموذج للتنبؤ واستخدام المبرمج لإجراء تحويل عكسي للحصول على تسمية الهدف المتوقع، أي اسم نوع البطريق.
ليست هذه هي الطريقة الوحيدة للتحقق من المدخلات. يمكنك أيضًا استخدام Pydantic للتحقق من المدخلات.
إذا كنت تستخدم نفس إصدار FastAPI المذكور في ملف requirements.txt
، فسيُحدّث FastAPI الخدمة تلقائيًا ويُطبّق التغييرات عند الحفظ. الآن، أدخل رابطًا جديدًا في test_main.http
للاختبار (مفصولًا عن الرابط السابق بعلامة ###):
###
GET http://127.0.0.1:8000/predict/?bill_length_mm=40.3&flipper_length_mm=195
Accept: application/json
اضغط على زر السهم الموجود بجوار عنوان URL الجديد الخاص بنا وشاهد النتيجة.

بعد ذلك، يمكنك تجربة عنوان URL مع إزالة أحد المعلمتين أو كليهما لرؤية رسالة الخطأ:
###
GET http://127.0.0.1:8000/predict/?bill_length_mm=40.3
Accept: application/json

قم بإعداد نموذج تعلم الآلة مع أحداث العمر الافتراضي
أخيرًا، لنلقِ نظرة على كيفية إعداد نموذجنا باستخدام أحداث عمر FastAPI. ميزة ذلك هي ضمان عدم قبول أي طلب أثناء إعداد النموذج، ومسح الذاكرة المستخدمة لاحقًا. للقيام بذلك، سنستخدم asynccontextmanager
. قبل app = FastAPI()
، سنضيف:
from contextlib import asynccontextmanager
ml_models = {}
@asynccontextmanager
async def lifespan(app: FastAPI):
# Set up the ML model here
yield
# Clean up the models and release resources
ml_models.clear()
الآن سننقل استيراد pandas وscikit-learn إلى جانب عمليات الاستيراد الأخرى. سننقل أيضًا شيفرة الإعداد داخل دالة lifespan، مع ضبط نموذج تعلم الآلة وLabelEncoder داخل ml_models كما يلي:
from fastapi import FastAPI
from contextlib import asynccontextmanager
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
ml_models = {}
@asynccontextmanager
async def lifespan(app: FastAPI):
# Set up the ML model here
data = pd.read_csv('penguins.csv')
data = data.dropna()
le = preprocessing.LabelEncoder()
X = data[["bill_length_mm", "flipper_length_mm"]]
le.fit(data["species"])
y = le.transform(data["species"])
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
clf = Pipeline(
steps=[("scaler", StandardScaler()), ("knn", KNeighborsClassifier(n_neighbors=11))]
)
clf.set_params().fit(X_train, y_train)
ml_models["clf"] = clf
ml_models["le"] = le
yield
# Clean up the models and release resources
ml_models.clear()
بعد ذلك سوف نضيف المعلمة lifespan=lifespan
في app = FastAPI()
:
app = FastAPI(lifespan=lifespan)
الآن احفظ وجرّب مرة أخرى. كل شيء يعمل، وسنرى نفس النتيجة السابقة.
فكرة لاحقة: متى يتم تدريب النموذج؟
من مثالنا، قد تتساءل متى يتم تدريب النموذج. بما أن clf
يُدرَّب في البداية، أي عند تشغيل الخدمة، فقد تتساءل لماذا لا ندرِّب النموذج في كل مرة يُقدِّم فيها شخص ما تنبؤًا.
لا نريد تدريب النموذج في كل مرة يُجري فيها شخص ما مكالمة، لأن إعادة تدريب كل شيء تتطلب موارد أكثر بكثير. بالإضافة إلى ذلك، قد يُسبب ذلك حالات تعارض نظرًا لأن تطبيق FastAPI يعمل بالتزامن. هذا ينطبق بشكل خاص إذا كنا نستخدم بيانات مباشرة تتغير باستمرار.
من الناحية الفنية، يمكننا إعداد واجهة برمجة تطبيقات لجمع البيانات وإعادة تدريب النموذج (سنوضح ذلك في المثال التالي). ومن الخيارات الأخرى جدولة إعادة التدريب في وقت محدد عند جمع كمية معينة من البيانات الجديدة، أو السماح لمستخدم رئيسي بتحميل بيانات جديدة وتفعيل إعادة التدريب.
حتى الآن، نهدف إلى بناء نموذج أولي يعمل محليًا. للمزيد من المعلومات، يُرجى الاطلاع على هذه المقالة حول نشر مشروع FastAPI على خدمة سحابية.
ما هو التزامن؟
ببساطة، يشبه التزامن الطهي في المطبخ، وبينما تنتظر غليان الماء، تقوم بتقطيع الخضراوات. في عالم خدمات الويب، يتواصل الخادم مع العديد من الأجهزة الطرفية، ويكون الاتصال بين الخادم والأجهزة الطرفية أبطأ من معظم التطبيقات الداخلية، لذا لن يتواصل الخادم مع الأجهزة الطرفية ويخدمها واحدة تلو الأخرى. بل سيتواصل مع العديد منها ويخدمها في الوقت نفسه أثناء تلبية طلباتها. قد ترغب في الاطلاع على هذا الشرح في وثائق FastAPI.
في بايثون، يتحقق ذلك باستخدام شيفرة غير متزامنة. في شيفرة FastAPI الخاصة بنا، يُعد استخدام async def
بدلاً من def
دليلاً واضحاً على أن FastAPI يعمل بشكل متزامن. هناك كلمات مفتاحية أخرى مستخدمة في شيفرة بايثون غير المتزامنة، مثل await
وasyncio.get_event_loop
، لكننا لن نتمكن من تغطيتها في هذه التدوينة.
كيفية استخدام FastAPI لمشروع تصنيف الصور
لاكتشاف المزيد من وظائف FastAPI، سنضيف نموذج تصنيف صور قائم على مثال MNIST في Keras إلى تطبيقنا أيضًا (نستخدم واجهة TensorFlow الخلفية). إذا ثبّت ملف requirements.txt
المُرفق، فيجب أن يكون Keras وPillow مُثبّتين لديك لمعالجة الصور وبناء شبكة عصبية ملتوية (CNN).
إعادة الهيكلة
قبل أن نبدأ، لنُعِد هيكلة الكود. لجعل الكود أكثر تنظيمًا، سنضع إعداد النموذج لتوقعات البطاريق في دالة:
def penguins_pipeline():
data = pd.read_csv('penguins.csv')
data = data.dropna()
le = preprocessing.LabelEncoder()
X = data[["bill_length_mm", "flipper_length_mm"]]
le.fit(data["species"])
y = le.transform(data["species"])
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
clf = Pipeline(
steps=[("scaler", StandardScaler()), ("knn", KNeighborsClassifier(n_neighbors=11))]
)
clf.set_params().fit(X_train, y_train)
return clf, le
ثم نعيد كتابة دالة العمر الافتراضي. مع إكمال سطر الكود بالكامل في PyCharm، يصبح الأمر سهلاً للغاية:

إعداد نموذج CNN للتنبؤ بـ MNIST
بنفس الطريقة التي استخدمناها في نموذج التنبؤ بالبطريق، قمنا بإنشاء دالة للتنبؤ بـ MNIST (وسنقوم بتخزين المعلمات الوصفية عالميًا):
# MNIST model meta parameters
num_classes = 10
input_shape = (28, 28, 1)
batch_size = 128
epochs = 15
def mnist_pipeline():
# Load the data and split it between train and test sets
(x_train, y_train), _ = keras.datasets.mnist.load_data()
# Scale images to the [0, 1] range
x_train = x_train.astype("float32") / 255
# Make sure images have shape (28, 28, 1)
x_train = np.expand_dims(x_train, -1)
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
model = keras.Sequential(
[
keras.Input(shape=input_shape),
layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Flatten(),
layers.Dropout(0.5),
layers.Dense(num_classes, activation="softmax"),
]
)
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1)
return model
ثم أضف إعداد النموذج في وظيفة عمر الخدمة:
ml_models["cnn"] = mnist_pipeline()
لاحظ أنه منذ إضافة هذه الميزة، في كل مرة تُجري فيها تغييرات على ملف main.py وتحفظه، سيتم تدريب النموذج مرة أخرى. قد يستغرق الأمر بعض الوقت. لذلك، في مرحلة التطوير، قد ترغب في استخدام نموذج وهمي لا يتطلب أي تدريب على الإطلاق، أو نموذج مُدرّب مسبقًا. بعد التدريب، سيكون نموذج CNN جاهزًا للاستخدام.
قم بإعداد نقطة نهاية POST لتحميل ملف صورة للتنبؤ
لإعداد نقطة نهاية تستقبل ملف التحميل، يتعين علينا استخدام UploadFile في FastAPI:
@app.post("/predict-image/")
async def predicct_upload_file(file: UploadFile):
img = await file.read()
# process image for prediction
img = Image.open(BytesIO(img)).convert('L')
img = np.array(img).astype("float32") / 255
img = np.expand_dims(img, (0, -1))
# predict the result
result = ml_models["cnn"].predict(img).argmax(axis=-1)[0]
return {"filename": file.filename,
"result": str(result)}
يرجى ملاحظة أن هذه نقطة نهاية POST (حتى الآن قمنا بإعداد نقاط نهاية GET فقط).
لا تنسى استيراد UploadFile
من fastapi
:
from fastapi import FastAPI, UploadFile
و”Image” من Pillow. نستخدم أيضًا “BytesIO” من وحدة “io”:
from PIL import Image
from io import BytesIO
لاختبار ذلك باستخدام عميل HTTP الخاص بـ PyCharm مع ملف صورة اختبار، سنستخدم ترميز multipart/form-data
. يمكنك الاطلاع على صيغة طلب HTTP هنا. هذا ما ستضعه في ملف test_in.http
:
###
POST http://127.0.0.1:8000/predict-image/ HTTP/1.1
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="test_img0.png"
< ./test_img0.png
--boundary–
أضف واجهة برمجة التطبيقات (API) لجمع البيانات وتحفيز إعادة التدريب
الآن، تأتي مرحلة إعادة التدريب. نُعِدّ نقطة نهاية POST كما هو موضح أعلاه لقبول ملف مضغوط يحتوي على صور وملصقات تدريب. بعد ذلك، تتم معالجة ملف zip وتجهيز بيانات التدريب. بعد ذلك، سنُلائم نموذج CNN مرة أخرى:
@app.post("/upload-images/")
async def retrain_upload_file(file: UploadFile):
img_files = []
labels_file = None
train_img = None
with ZipFile(BytesIO(await file.read()), 'r') as zfile:
for fname in zfile.namelist():
if fname[-4:] == '.txt' and fname[:2] != '__':
labels_file = fname
elif fname[-4:] == '.png':
img_files.append(fname)
if len(img_files) == 0:
return {"error": "No training images (png files) found."}
else:
for fname in sorted(img_files):
with zfile.open(fname) as img_file:
img = img_file.read()
# process image
img = Image.open(BytesIO(img)).convert('L')
img = np.array(img).astype("float32") / 255
img = np.expand_dims(img, (0, -1))
if train_img is None:
train_img = img
else:
train_img = np.vstack((train_img, img))
if labels_file is None:
return {"error": "No training labels file (txt file) found."}
else:
with zfile.open(labels_file) as labels:
labels_data = labels.read()
labels_data = labels_data.decode("utf-8").split()
labels_data = np.array(labels_data).astype("int")
labels_data = keras.utils.to_categorical(labels_data, num_classes)
# retrain model
ml_models["cnn"].fit(train_img, labels_data, batch_size=batch_size, epochs=epochs, validation_split=0.1)
return {"message": "Model trained successfully."}
تذكر استيراد ZipFile
:
from zipfile import ZipFile
إذا حاولنا الآن نقطة النهاية باستخدام ملف zip الذي يحتوي على 1000 صورة وعلامات إعادة تدريب، فستجد أن الاستجابة تستغرق بعض الوقت، حيث يستغرق التدريب بعض الوقت:
POST http://127.0.0.1:8000/upload-images/ HTTP/1.1
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="training_data.zip"
< ./retrain_img.zip
--boundary--
تخيل أن ملفات zip تحتوي على بيانات تدريب أكثر، أو أنك تُعيد تدريب نموذج أكثر تعقيدًا. سيضطر المستخدم حينها للانتظار طويلًا، ويبدو أن الأمور لا تسير على ما يرام بالنسبة له.
إعادة تدريب النموذج باستخدام BackgroundTasks
هناك طريقة أفضل لإدارة إعادة التدريب، وهي معالجتها بعد استلام بيانات التدريب والتحقق من صحتها، ثم إرسال رد يفيد بإعادة تشغيل عملية إعادة التدريب وتدريب النموذج في “BackgroundTasks”. إليك كيفية القيام بذلك: أولًا، سنضيف “BackgroundTasks” إلى نقطة نهاية “upload-images”:
@app.post("/upload-image/")
async def retrain_upload_file(file: UploadFile, background_tasks: BackgroundTasks):
...
تذكر أن تقوم باستيراده من fastapi
:
from fastapi import FastAPI, UploadFile, BackgroundTasks
بعد ذلك، سنضع ملاءمة النموذج في background_tasks
:
# retrain model
background_tasks.add_task(
ml_models["cnn"].fit,
train_img,
labels_data,
batch_size=batch_size,
epochs=epochs,
validation_split=0.1
)
وسوف نقوم أيضًا بتحديث الرسالة في الرد:
return {"message": "Data received successfully, model training has started."}
الآن، اختبر نقطة النهاية مرة أخرى. ستلاحظ وصول الاستجابة أسرع بكثير، وإذا نظرت إلى نافذة التشغيل، فسترى أن التدريب يعمل بعد وصول الاستجابة.
في هذه المرحلة، يمكن إضافة المزيد من الوظائف، على سبيل المثال، خيار لإعلام المستخدم لاحقًا (على سبيل المثال عبر البريد الإلكتروني) عند انتهاء التدريب أو تتبع تقدم التدريب في لوحة معلومات عند إنشاء تطبيق كامل.
في هذه التدوينة، عرضنا عملية توفير واجهة برمجة تطبيقات بسيطة لنموذج تنبؤ مُدرّب مسبقًا. لمعرفة المزيد عن FastAPI، أنصحك بالاطلاع على وثائق FastAPI الرسمية. إذا كنت تختار بين أطر عمل مختلفة، فاستكشف أوجه اختلاف FastAPI عن Django.
اكتشاف المزيد من بايثون العربي
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.