
![]()
جعل نموذج الخدمة فعالا في السحابة.

MOSEC هو إطار عمل عالي الأداء ومرن يخدم لبناء الواجهة الخلفية التي تدعم طراز ML والخدمات الدقيقة. إنه يسد الفجوة بين أي نماذج تعلم آلية قمت بتدريبها للتو وواجهة برمجة تطبيقات الخدمة عبر الإنترنت الفعالة.
MOSEC يتطلب بيثون 3.7 أو أعلى. قم بتثبيت أحدث حزمة PYPI لـ Linux X86_64 أو MacOS X86_64/ARM64 مع:
pip install -U mosec
# or install with conda
conda install conda-forge::mosecللبناء من الرمز المصدر ، قم بتثبيت الصدأ وتشغيل الأمر التالي:
make package ستحصل على ملف عجلة MOSEC في مجلد dist .
نوضح كيف يمكن أن تساعدك MOSEC بسهولة في استضافة نموذج نشر مستقر مسبقًا كخدمة. تحتاج إلى تثبيت الناشرون والمحولات كشروط مسبقة:
pip install --upgrade diffusers[torch] transformersأولاً ، نستورد المكتبات وننشئ مسجلًا أساسيًا لمراقبة ما يحدث بشكل أفضل.
from io import BytesIO
from typing import List
import torch # type: ignore
from diffusers import StableDiffusionPipeline # type: ignore
from mosec import Server , Worker , get_logger
from mosec . mixin import MsgpackMixin
logger = get_logger ()بعد ذلك ، نقوم بإنشاء واجهة برمجة تطبيقات للعملاء للاستعلام عن موجه نص والحصول على صورة بناءً على نموذج الانتشار المستقر-V1-5 في 3 خطوات فقط.
حدد خدمتك على أنها فئة ترث mosec.Worker . هنا نرث أيضًا MsgpackMixin لتوظيف تنسيق تسلسل MSGPack (A) .
داخل طريقة __init__ ، قم بتهيئة النموذج الخاص بك ووضعه على الجهاز المقابل. اختياريا يمكنك تعيين self.example مع بعض البيانات لتسخين (ب) النموذج. لاحظ أن البيانات يجب أن تكون متوافقة مع تنسيق إدخال معالجك ، وهو ما نقوم بالتفصيل بعد ذلك.
تجاوز الطريقة forward لكتابة معالج الخدمة الخاص بك (ج) ، مع توقيع forward(self, data: Any | List[Any]) -> Any | List[Any] . يعتمد استلام/إرجاع عنصر واحد أو tuple على ما إذا كان يتم تكوين تجميع ديناميكي (D) .
class StableDiffusion ( MsgpackMixin , Worker ):
def __init__ ( self ):
self . pipe = StableDiffusionPipeline . from_pretrained (
"sd-legacy/stable-diffusion-v1-5" , torch_dtype = torch . float16
)
self . pipe . enable_model_cpu_offload ()
self . example = [ "useless example prompt" ] * 4 # warmup (batch_size=4)
def forward ( self , data : List [ str ]) -> List [ memoryview ]:
logger . debug ( "generate images for %s" , data )
res = self . pipe ( data )
logger . debug ( "NSFW: %s" , res [ 1 ])
images = []
for img in res [ 0 ]:
dummy_file = BytesIO ()
img . save ( dummy_file , format = "JPEG" )
images . append ( dummy_file . getbuffer ())
return images[!ملحوظة]
(أ) في هذا المثال ، نعيد صورة بالتنسيق الثنائي ، والتي لا تدعمها JSON (ما لم يتم ترميزها بـ BASE64 التي تجعل الحمولة الحمولة أكبر). وبالتالي ، فإن MSGPACK يناسب احتياجاتنا بشكل أفضل. إذا لم نرث
MsgpackMixin، فسيتم استخدام JSON افتراضيًا. بمعنى آخر ، يمكن أن يكون بروتوكول طلب/استجابة الخدمة إما MSGPack أو JSON أو أي تنسيق آخر (تحقق من Mixins).(ب) عادة ما يساعد الاحماء على تخصيص ذاكرة GPU مقدمًا. إذا تم تحديد مثال الاحماء ، فلن تكون الخدمة جاهزة إلا بعد إعادة توجيه المثال من خلال المعالج. ومع ذلك ، إذا لم يتم تقديم مثال ، فمن المتوقع أن يكون زمن انتقال الطلب الأول أطول. يجب تعيين
exampleكعنصر واحد أو توبلي اعتمادًا على ما يتوقعهforward. علاوة على ذلك ، في الحالة التي تريد فيها الاحماء مع أمثلة مختلفة متعددة ، يمكنك تعيينmulti_examples(العرض التوضيحي هنا).(ج) يعرض هذا المثال خدمة مرحلة واحدة ، حيث يأخذ عامل
StableDiffusionمباشرة طلب العميل ويستجيب الصورة. وبالتالي يمكن اعتبارforwardمعالج خدمة كامل. ومع ذلك ، يمكننا أيضًا تصميم خدمة متعددة المراحل مع العمال يقومون بوظائف مختلفة (على سبيل المثال ، تنزيل الصور ، استنتاج النموذج ، ما بعد المعالجة) في خط أنابيب. في هذه الحالة ، يعتبر خط الأنابيب بأكمله معالج الخدمة ، حيث يأخذ العامل الأول في الطلب وآخر عامل يرسل الاستجابة. يتم تدفق البيانات بين العمال عن طريق التواصل بين العمليات.(د) نظرًا لتم تمكين الدفع الديناميكي في هذا المثال ، ستتلقى الطريقة
forwardبأتمنى قائمة من السلسلة ، على سبيل المثال ،['a cute cat playing with a red ball', 'a man sitting in front of a computer', ...]، تم تجميعه من عملاء مختلفين لاستدلال الدُفعات ، وتحسين إنتاجية النظام.
أخيرًا ، نقوم بإلحاق العامل بالخادم لإنشاء سير عمل لمرحلة واحدة (يمكن أن تكون مراحل متعددة أنابيب لزيادة زيادة الإنتاجية ، ويرى هذا المثال) ، وحدد عدد العمليات التي نريد تشغيلها بشكل متوازي ( num=1 ) ، وحجم الدفعة القصوى ( max_batch_size=4 ، سوف يقيد العدد الأقصى للطلبات التي تم تقديرها لقيامات الديناميكية التي تم تقديميها قبل وقت ما قبل الوقت ؛ max_wait_time=10 بالمللي ثانية ، وهذا يعني أن أطول وقت ينتظر Mosec حتى إرسال الدفعة إلى العامل).
if __name__ == "__main__" :
server = Server ()
# 1) `num` specifies the number of processes that will be spawned to run in parallel.
# 2) By configuring the `max_batch_size` with the value > 1, the input data in your
# `forward` function will be a list (batch); otherwise, it's a single item.
server . append_worker ( StableDiffusion , num = 1 , max_batch_size = 4 , max_wait_time = 10 )
server . run ()يتم دمج المقتطفات أعلاه في ملف مثالنا. يمكنك تشغيل مباشرة على مستوى جذر المشروع. نلقي نظرة أولاً على وسيطات سطر الأوامر (تفسيرات هنا):
python examples/stable_diffusion/server.py --helpثم لنبدأ الخادم مع سجلات التصحيح:
python examples/stable_diffusion/server.py --log-level debug --timeout 30000 افتح http://127.0.0.1:8000/openapi/swagger/ في متصفحك للحصول على مستند Openapi.
وفي محطة أخرى ، اختبره:
python examples/stable_diffusion/client.py --prompt " a cute cat playing with a red ball " --output cat.jpg --port 8000ستحصل على صورة تسمى "CAT.JPG" في الدليل الحالي.
يمكنك التحقق من المقاييس:
curl http://127.0.0.1:8000/metricsهذا كل شيء! لقد استضافت للتو نموذج الانتشار المستقر كخدمة!
يمكن العثور على المزيد من الأمثلة الجاهزة للاستخدام في قسم المثال. ويشمل:
max_batch_size و max_wait_time (millisecond) عند الاتصال append_worker .max_batch_size لن يتسبب في الخارج في GPU.max_wait_time أقل من وقت استنتاج الدُفعة.max_batch_size أو عند انقضاء max_wait_time . ستستفيد الخدمة من هذه الميزة عندما تكون حركة المرور مرتفعة.mosec ، فيمكنك التحقق من الصورة الرسمية mosecorg/mosec . لحالة الاستخدام المعقدة ، تحقق من ENVD.mosec_service_batch_size_bucket توزيع حجم الدُفعة.mosec_service_batch_duration_second_bucket يعرض مدة الدفع الديناميكي لكل اتصال في كل مرحلة (يبدأ من تلقي المهمة الأولى).mosec_service_process_duration_second_bucket يعرض مدة المعالجة لكل اتصال في كل مرحلة (بما في ذلك وقت IPC ولكن باستثناء mosec_service_batch_duration_second_bucket ).mosec_service_remaining_task عدد مهام المعالجة حاليًا.mosec_service_throughput يعرض إنتاجية الخدمة.SIGINT ( CTRL+C ) أو SIGTERM ( kill {PID} ) نظرًا لأنه يحتوي على منطق الإغلاق الرشيق. max_batch_size و max_wait_time لخدمة الاستدلال الخاصة بك. ستظهر المقاييس الرسوم البيانية لحجم الدُفعة الحقيقي ومدة الدُفعة. هذه هي المعلومات الرئيسية لضبط هاتين المعلمتين.serialize_ipc/deserialize_ipc ، لذلك قد تجعل البيانات الكبيرة للغاية خط الأنابيب بأكمله. يتم تمرير البيانات المسلسل إلى المرحلة التالية من خلال الصدأ افتراضيًا ، يمكنك تمكين الذاكرة المشتركة لتقليل الكمون (REF Redisshmipcmixin).serialize/deserialize المناسبة ، والتي يتم استخدامها لفك تشفير طلب المستخدم وترميز الاستجابة. بشكل افتراضي ، كلاهما يستخدم JSON. ومع ذلك ، فإن الصور والتضمينات ليست مدعومة جيدًا من قبل JSON. يمكنك اختيار MSGPack وهو أسرع وتوافق ثنائي (مرجع مستقر الانتشار).mosec تلقائيًا مع بروتوكول المستخدم (على سبيل المثال ، HTTP/2) منذ V0.8.8. فيما يلي بعض الشركات والمستخدمين الأفراد الذين يستخدمون MOSEC:
إذا وجدت هذا البرنامج مفيدًا لبحثك ، فيرجى التفكير في الإشارة إلى
@software{yang2021mosec,
title = {{MOSEC: Model Serving made Efficient in the Cloud}},
author = {Yang, Keming and Liu, Zichen and Cheng, Philip},
url = {https://github.com/mosecorg/mosec},
year = {2021}
}
نرحب بأي نوع من المساهمة. يرجى إعطائنا ملاحظات من خلال إثارة القضايا أو مناقشة الخلاف. يمكنك أيضًا المساهمة بشكل مباشر في الكود وسحب طلب!
للبدء في التطور ، يمكنك استخدام EnvD لإنشاء بيئة Python و Rust معزولة ونظيفة. تحقق من envd-docs أو build.envd لمزيد من المعلومات.