تتيح لك واجهة تحكم الذكاء الاصطناعي (AICI) إنشاء وحدات تحكم تقيد وتوجيه الإخراج لنموذج اللغة الكبير (LLM) في الوقت الفعلي. تعد وحدات التحكم برامج مرنة قادرة على تنفيذ فك التشفير المقيد ، والتحرير الديناميكي للمطالبات والنص الذي تم إنشاؤه ، وتنسيق التنفيذ عبر أجيال متعددة متوازية. تتضمن وحدات التحكم المنطق المخصص أثناء فك تشفير الرمز المميز وصيانة الحالة أثناء طلب LLM. يتيح ذلك استراتيجيات وحدة تحكم متنوعة ، بدءًا من فك التشفير البرمجي أو القائم على الاستعلام إلى محادثات متعددة الوكلاء للتنفيذ بكفاءة في التكامل الضيق مع LLM نفسه.
الغرض من AICI هو تسهيل بناء وتجربة كل من استراتيجيات وحدة التحكم الحالية والجديدة تمامًا لتحسين أجيال LLM. من خلال استخلاص تفاصيل التنفيذ الخاصة بمحرك LLM ومحرك التقديم ، تهدف AICI إلى تبسيط تطوير وحدات التحكم ، وتسهيل كتابة وحدات التحكم السريعة ، وتخفيف التوافق عبر محركات LLM ومحركات التقديم.
تم تصميم AICI للتنفيذ المحلي والسحابي ، بما في ذلك (في نهاية المطاف) عمليات نشر LLM Multi-Multi-Menant. يتم تنفيذ وحدات التحكم كوحدات WebAssembly الخفيفة الوزن (WASM) التي تعمل على نفس الجهاز مثل محرك الاستدلال LLM ، باستخدام وحدة المعالجة المركزية بينما وحدة معالجة الرسومات مشغولة بالتوليد الرمزي. AICI هي طبقة واحدة في مكدس الاستدلال ، وهي مصممة للسماح لمكتبات التحكم مثل التوجيه ، LMQL ، وغيرها للتشغيل فوقها واكتساب كل من تحسينات الكفاءة والأداء ، وكذلك قابلية النقل عبر استدلال LLM ومحركات التقديم.
تتكامل AICI حاليًا مع llama.cpp و uggingface Transformers و RLLM (محرك الاستدلال LLM المستند إلى TCH مخصص) ، مع VLLM في الأعمال.
AICI هو:
AICI هو نموذج أولي ، مصمم وبنيت في Microsoft Research.
في هذه البداية السريعة ، سنرشدك خلال الخطوات التالية:
لتجميع مكونات AICI ، تحتاج إلى إعداد بيئة التطوير الخاصة بك من أجل الصدأ. لهذا المنشور السريع ، تحتاج أيضًا إلى Python 3.11 أو لاحقًا لإنشاء وحدة تحكم.
ملحوظة
مستخدمي Windows : يرجى استخدام WSL2 أو DevContainer المضمّن. يتم تتبع إضافة دعم Windows الأصلي هنا.
مستخدمو MacOS : يرجى التأكد من تثبيت أدوات سطر أوامر Xcode عن طريق تشغيل xcode-select -p ، وإذا لم يتم تثبيته ، قم بتشغيل xcode-select --install .
CUDA : يعتمد بناء CUDA على تثبيت LIBTORCH محدد. يوصى بشدة باستخدام DevContainer المضمّن.
إذا كنت تستخدم DevContainer ، فيمكنك الانتقال إلى القسم التالي.
باستخدام مدير حزمة النظام ، قم بتثبيت الأدوات اللازمة لبناء رمز في المستودع ، بما في ذلك git و cmake و ccache .
على سبيل المثال في WSL / Ubuntu باستخدام apt :
sudo apt-get install --assume-yes --no-install-recommends
build-essential cmake ccache pkg-config libssl-dev libclang-dev clang llvm-dev git-lfs
أو استخدام Homebrew على MacOS:
brew install git cmake ccache
ثم قم بتثبيت الصدأ والصدأ والبضائع ، وبعد الإرشادات المقدمة هنا وهنا:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
بعد التثبيت ، تحقق من أن أمر rustup --version يمكن الوصول إليه عن طريق تشغيله من المحطة. إذا لم يتم التعرف على الأمر ، فحاول فتح جلسة طرفية جديدة.
التثبيت التالي WASM32-Wasi Rust مكون:
rustup target add wasm32-wasi
إذا كنت قد قمت بالفعل بتثبيت الصدأ ، أو تحصل على شكاوى من البضائع حول الإصدارات التي عفا عليها الزمن ، قم بتشغيل:
rustup update
أخيرًا ، للعمل مع وحدات تحكم Python والبرامج النصية (مثل هذا البرنامج التعليمي) ، قم بتشغيل هذا الأمر لتثبيت الحزم المطلوبة:
pip install pytest pytest-forked ujson posix_ipc numpy requests
يحتوي خادم RLLM على خلفيين ، واحد يعتمد على libtorch و cuda ( rllm-cuda ) ، والآخر يعتمد على llama.cpp ( rllm-llamacpp ).
تعمل الواجهة الخلفية rllm-cuda فقط مع NVIDIA GPU مع قدرة الحساب 8.0 أو الأحدث (A100 وما بعدها ؛ RTX 30x0 ولاحقًا) وتتطلب إعدادًا كاذبًا من libtorch-يوصى بشدة باستخدام DevContainer المضمّن. بينما يركز هذا الدليل على الواجهة الخلفية rllm-llamacpp ، فإن خطوات الإنشاء هي نفسها بالنسبة لـ rllm-cuda ، Modulo اسم المجلد.
بعد إعداد Dev Env أعلاه ، استنساخ مستودع AICI والمضي قدمًا في الخطوات التالية الموضحة أدناه.
استخدم الأمر التالي لإنشاء وتشغيل aicirt و rllm-llamacpp :
cd rllm/rllm-llamacpp
./server.sh phi2
يمكنك تمرير أسماء النماذج الأخرى كوسيطة (Run ./server.sh بدون وسيط لمشاهدة النماذج المتاحة). يمكنك أيضًا استخدام عنوان URL LuggingFace إلى ملف .gguf أو مسار محلي إلى ملف .gguf . (بالنسبة إلى rllm-cuda استخدم معرف نموذج Huggingface أو مسار إلى المجلد).
./server.sh orca
يمكنك العثور على مزيد من التفاصيل حول rllm-llamacpp هنا.
يوفر خادم RLLM واجهة HTTP ، مستخدمًا لمهام التكوين وطلبات المعالجة. يمكنك أيضًا استخدام هذه الواجهة للتحقق من حالتها على الفور. على سبيل المثال ، إذا فتحت http://127.0.0.1:4242/v1/models ، يجب أن ترى:
{
"object" : " list " ,
"data" : [
{
"object" : " model " ,
"id" : " TheBloke/phi-2-GGUF " ,
"created" : 946810800 ,
"owned_by" : " owner "
}
]
}تأكيد أن النموذج المحدد يتم تحميله.
يتيح AICI استضافة منطق مخصص ، يسمى وحدات التحكم ، التي تبدأ وإنهاء وتفاعل مع توليد الرمز المميز LLMS. تأخذ وحدات التحكم وسيطات الإدخال ، ومعالجةها ، وإرجاع نتيجة مع سجلات LLM ، والمتغيرات.
يتضمن المستودع بعض الأمثلة ، على وجه الخصوص:
في هذا المثال ، سنستخدم Pyctrl لإدارة توليد الرمز المميز باستخدام برنامج نصي Python بسيط. إذا كنت تريد ، يمكنك إنشاء وتحميل Pyctrl ، ولكن بشكل افتراضي ، سيقوم الخادم تلقائيًا بتنزيل أحدث إصدار من Pyctrl من Github.
بشكل عام ، تتطلب وحدات التحكم بناء ونشر ، بينما يتم إرسال البرامج النصية (Python أو JavaScript) مع كل طلب.
يوضح ما يلي العلاقة بين خادم RLLM ووقت تشغيل AICI ووحدة التحكم:
erdiagram
مضيف ||-| {CPU: ""
مضيف ||-| {GPU: ""
وحدة المعالجة المركزية ||-|| "RLLM Server": تنفيذ
وحدة المعالجة المركزية ||-| {"AICI Runtime": تنفيذ
"AICI Runtime" ||-|| "وحدة التحكم": Instantiate
GPU ||-| {"LLM Token Generation": Execute
لنفترض أننا نهدف إلى إنشاء نموذج ، والتمسك بتنسيق محدد ويحتوي على خمسة عناصر فقط.
عادةً ما ينطوي تحقيق ذلك على الهندسة السريعة ، وصياغة المطالبة على وجه التحديد بتعليمات واضحة ، مثل:
What are the five most popular types of vehicles?
Return the result as a numbered list.
Do not add explanations, only the list.
ستختلف المطالبة أيضًا اعتمادًا على النموذج المستخدم ، بالنظر إلى أن كل نموذج يميل إلى إضافة تفسيرات ويفهم التعليمات بطرق مختلفة.
مع AICI ، ننقل التحكم مرة أخرى إلى التعليمات البرمجية ، ويمكننا تبسيط موجه إلى:
What are the most popular types of vehicles?
باستخدام رمز إلى:
دعنا ننشئ ملف Python list-of-five.py بيثون مع المحتوى التالي:
import pyaici . server as aici
# Force the model to generate a well formatted list of 5 items, e.g.
# 1. name 1
# 2. name 2
# 3. name 3
# 4. name 4
# 5. name 5
async def main ():
# This is the prompt we want to run.
# Note how the prompt doesn't mention a number of vehicles or how to format the result.
prompt = "What are the most popular types of vehicles? n "
# Tell the model to generate the prompt string, ie. let's start with the prompt "to complete"
await aici . FixedTokens ( prompt )
# Store the current position in the token generation process
marker = aici . Label ()
for i in range ( 1 , 6 ):
# Tell the model to generate the list number
await aici . FixedTokens ( f" { i } ." )
# Wait for the model to generate a vehicle name and end with a new line
await aici . gen_text ( stop_at = " n " )
await aici . FixedTokens ( " n " )
# Store the tokens generated in a result variable
aici . set_var ( "result" , marker . text_since ())
aici . start ( main ())تشغيل البرنامج النصي لا يختلف كثيرًا عن إرسال مطالبة. في هذه الحالة ، نرسل منطق التحكم والتعليمات معًا.
لرؤية النتيجة النهائية ، قم بتنفيذ الأمر التالي:
./aici.sh run list-of-five.py
نتيجة:
Running with tagged AICI Controller: gh:microsoft/aici/pyctrl
[0]: FIXED 'What are the most popular types of vehicles?n'
[0]: FIXED '1.'
[0]: GEN ' Carsn'
[0]: FIXED '2.'
[0]: GEN ' Motorcyclesn'
[0]: FIXED '3.'
[0]: GEN ' Bicyclesn'
[0]: FIXED '4.'
[0]: GEN ' Trucksn'
[0]: FIXED '5.'
[0]: GEN ' Boatsn'
[0]: FIXED 'n'
[DONE]
[Response] What are the most popular types of vehicles?
1. Cars
2. Motorcycles
3. Bicycles
4. Trucks
5. Boats
response saved to tmp/response.json
Usage: {'sampled_tokens': 16, 'ff_tokens': 37, 'cost': 69}
Timing: {'http_response': 0.05193686485290527, 'data0': 0.05199289321899414, 'first_token': 0.0658726692199707, 'last_token': 0.1784682273864746}
Tokens/sec: {'prompt': 861.0913072488067, 'sampling': 89.65181217019571}
Storage: {'result': '1. Carsn2. Motorcyclesn3. Bicyclesn4. Trucksn5. Boatsnn'}
يحتوي هذا المستودع على عدد من المكونات ، والتي تعتمد تلك التي تحتاجها على حالة الاستخدام الخاصة بك.
يمكنك استخدام وحدة تحكم موجودة . نحن نقدم PYCTRL و JSCTRL التي تتيح لك تحكم البرنامج النصي باستخدام Python و JavaScript من جانب الخادم ، على التوالي. تحتوي حزمة Pyaici على أداة سطر أوامر aici التي تتيح لك تحميل وتشغيل البرامج النصية مع أي وحدة تحكم (نقدم أيضًا تعريف API REST للفضولي).
عينات رمز python للبرمجة النصية Pyctrl و JavaScript Hello World لـ JSCTRL
نتوقع أن يتم بناء المكتبات على رأس وحدات التحكم. نحن نقدم مثالاً في PriderLib - مكتبة Python من جانب العميل التي تنشئ تتفاعل مع DECTTRL عبر حزمة Pyaici.
؟ مثال على دفتر الملاحظات الذي يستخدم QuortLib للتفاعل مع CREMCTRL.
يمكن تشغيل وحدات التحكم في سحابة أو محرك استنتاج LLM المحلي AICI. يمكنك تشغيل المحرك المرجعي المقدم (RLLM) محليًا باستخدام LIBTORCH+CUDA أو LLAMA.CPP الخلفية.
لتطوير وحدة تحكم جديدة ، استخدم مشروع Starter Rust يعرض استخدام مكتبة AICI_ABI ، مما يبسط تنفيذ واجهة AICI منخفضة المستوى.
رمز Sample للحصول على الحد الأدنى من وحدة تحكم جديدة لتبدأ
لإضافة دعم AICI إلى محرك الاستدلال الجديد LLM ، ستحتاج إلى تنفيذ LLM من البروتوكول الذي يتحدث إلى وقت تشغيل AICI.
أخيرًا ، قد ترغب في تعديل أي من المكونات المقدمة - PRS نرحب جدًا!
AICI ملخصات محرك الاستدلال LLM من وحدة التحكم والعكس بالعكس ، كما في الصورة أدناه. العقد الدائرية طموحة. يمكن بناء طبقات إضافية في الأعلى - نحن نقدم ادعاء ، لكننا نعتقد اعتقادا راسخا أن التوجيه ، LMQL ، SGLANG ، الخطوط العريضة ، jsonformer ، LMFE ، وما إلى ذلك يمكن أيضا أن تعمل فوق AICI (إما مع وحدات تحكم مخصصة أو استخدام PYCTRL أو JSCTRL).
الرسم البياني TD
Pyctrl-AICI-> aicirt [AICI-Runtime]
JSCTRL -AICI -> aicirt
إرشادات ([Guidancectrl]) -AICI -> aicirt
LMQL ([LMQL CTRL]) -AICI -> aicirt
aicirt -posix shm -> rllm
Aicirt -Posix shm -> llama [llama.cpp]
aicirt -posix shm -> pyaici
Pyaici -Python -> Vllm (Vllm)
Pyaici -Python -> HF [HF Transformers]
تجعل حزمة Pyaici من السهل دمج AICI مع محركات الاستدلال LLM المستندة إلى Python. ألقِ نظرة على التكامل مع محولات Huggingface ، على الرغم من أنه لا يدعم Forking (توليد تسلسلات متعددة بالتوازي). خادم REST VLLM حاليًا قديم. يرجى استخدام RLLM-CUDA أو RLLM-LAMA.CPP في الوقت الحالي.
aicirt في عملية منفصلة ، ويمكن أن يعمل تحت مستخدم مختلف عن محرك LLMaici_host_* ، التي تم تنفيذها في HOSTIMPL.RSaicirt يعرض أيضا واجهة واضحة جزئية. ومع ذلك ، فإن جميع الوظائف تقريبًا لا هي ، باستثناء fd_write التي تلمع واصفات الملفات 1 و 2 (stdout و stderr) لطباعة رسائل التصحيحعلى وجه الخصوص ، لا يمكن وحدات WASM الوصول إلى نظام الملفات أو الشبكة أو أي موارد أخرى. لا يمكنهم أيضًا تدوير المواضيع أو الوصول إلى أي أجهزة توقيت (وهذا مناسب لهجمات Specter/Meltdown).
تحدث معظم الحسابات في وحدات تحكم AICI على وحدة المعالجة المركزية ، بالتوازي مع توليد السجل على وحدة معالجة الرسومات. يحدث الجيل في خطوات ، حيث يتم إنشاء سجلات بالتوازي مع رمز جديد لكل تسلسل في دفعة (عادة ما بين 1 و 50). يتضمن ذلك قراءة النموذج بالكامل واختداءات KV للتسلسلات في الدفعة من ذاكرة GPU. للحصول على إنتاجية الدُفعات المثلى ، يجب على النموذج واختداءات ذاكرة التخزين المؤقت KV استخدام جزء كبير من ذاكرة GPU ، وقراءة الذاكرة بأكملها تستغرق حوالي 40 مللي ثانية على GPU A100 (80 جيجابايت).
وبالتالي ، فإن كل خطوة من خطوة التوليد تأخذ بترتيب 20-50 مللي ثانية. مع الهندسة الدقيقة ، هذا أكثر من كافية لحساب مجموعة من الرموز المسموح بها في الصدأ المترجمة إلى WASM. يمكن دمجها إما أصليًا في الصدأ ، أو عبر المترجمين الفوريين في الثعبان أو JavaScript.
على سبيل المثال ، يستغرق الرمز المميز المسموح به في المفردات التي تبلغ 32000 شخص من طراز Llama:
الأرقام المذكورة أعلاه مخصصة لتسلسل واحد ، ومع ذلك تتم معالجة كل تسلسل في عملية منفصلة ، وبالتالي إذا كان هناك المزيد من النوى من التسلسل (وهو أمر نموذجي) ، فإنها لا تتغير. وهي تشمل أيضًا النفقات العامة للاتصال بترجم بيثون المنفذ في WASM ، ثم العودة إلى رمز WASM الذي تم إنشاؤه الصدأ للقيد نفسه. إنها جميعها في حدود 20-50 مللي ثانية ، لذلك لا تؤثر على وقت التوليد على الإطلاق.
هناك أيضا بعض النفقات العامة في المسار الحرج لأخذ العينات. يأتي إلى حوالي 0.3 مللي ثانية لكل خطوة جيل عند تنفيذ 10 تسلسل بالتوازي (هذا بغض النظر عن القيد المستخدم). يرتفع النفقات العامة إلى حوالي 0.7 مللي ثانية لـ 40 متسلسلًا (على الرغم من أنه لم يتم تحسينه بالكامل بعد).
تم تصميم Webassembly للحصول على الحد الأدنى من النفقات العامة ، مقارنة بالرمز الأصلي. في تجربتنا ، يكون رمز الصدأ المحسن للغاية أقل من 2x أبطأ عند تشغيله في WasmTime من الأم. هذا هو 10-100x أفضل من JavaScript أو Python.
جميع القياسات التي أجريت على AMD EPYC 7V13 مع GPU NVIDIA A100 مع 80 جيجابايت من VRAM.
الواجهة ذات المستوى المنخفض الذي يوفره وقت تشغيل AICI يسمح بما يلي:
يمكن استخدامه من أي لغة تجمع إلى WASM.
يوفر هذا المستودع مكتبة صدأ تجعل من السهل تنفيذ وحدات التحكم في الصدأ ، ويوفر تطبيقات فعالة لقيود محددة (تعبيرات منتظمة ، قواعد YACC ، فرعية). كما نقدم المترجمين المترجمين في Python و JavaScript الذين يسمحون بإلصاق هذه القيود معًا. كل هذه يمكن تمديدها بسهولة.
إذا وجدت واجهة وحدة تحكم الذكاء الاصطناعى وأفكارها لتحديد طبقة جديدة في مكدس الاستدلال LLM مفيدة ، فيرجى الاستشهاد بالحزمة باستخدام المرجع التالي:
bibtex:
@misc { Moskal2024 ,
author = { Moskal, Michal and Musuvathi, Madan and {Ki ci man}, Emre } ,
title = { {AI Controller Interface} } ,
year = { 2024 } ,
publisher = { {GitHub} } ,
journal = { {GitHub} repository } ,
howpublished = { url{https://github.com/microsoft/aici/} }
}يرحب هذا المشروع بالمساهمات والاقتراحات. تطلب منك معظم المساهمات الموافقة على اتفاقية ترخيص المساهم (CLA) مع إعلان أن لديك الحق في ذلك في الواقع ، ويفعلنا في الواقع حقوق استخدام مساهمتك. لمزيد من التفاصيل ، تفضل بزيارة https://cla.opensource.microsoft.com.
عند إرسال طلب سحب ، سيحدد CLA Bot تلقائيًا ما إذا كنت بحاجة إلى توفير CLA وتزيين العلاقات العامة بشكل مناسب (على سبيل المثال ، فحص الحالة ، التعليق). ببساطة اتبع الإرشادات التي يقدمها الروبوت. ستحتاج فقط إلى القيام بذلك مرة واحدة عبر جميع عمليات إعادة الشراء باستخدام CLA لدينا.
اعتمد هذا المشروع رمز سلوك المصدر المفتوح Microsoft. لمزيد من المعلومات ، راجع مدونة الشهادة الأسئلة الشائعة أو الاتصال بـ [email protected] مع أي أسئلة أو تعليقات إضافية.
قد يحتوي هذا المشروع على علامات تجارية أو شعارات للمشاريع أو المنتجات أو الخدمات. يخضع الاستخدام المعتمد للعلامات التجارية أو الشعارات Microsoft ويجب أن يتبعوا إرشادات العلامات التجارية والعلامة التجارية Microsoft. يجب ألا يسبب استخدام العلامات التجارية Microsoft أو الشعارات في إصدارات معدلة من هذا المشروع الارتباك أو يعني رعاية Microsoft. يخضع أي استخدام للعلامات التجارية أو الشعارات من طرف ثالث لسياسات تلك الطرف الثالث.