Mit der AICI (Artificial Intelligence Controller Interface) können Sie Controller erstellen, die in Echtzeit die Ausgabe eines großen Sprachmodells (LLM) einschränken und leiten. Controller sind flexible Programme, die eingeschränkte Dekodierung, dynamische Bearbeitung von Eingabeaufforderungen und generierten Text und die Koordination der Ausführung über mehrere parallele Generationen implementieren können. Controller enthalten eine benutzerdefinierte Logik während des Dekodierens von Token-by-Token und pflegen während einer LLM-Anfrage. Dies ermöglicht verschiedene Controller-Strategien, von programmatischen oder abfragebasierten Dekodierung bis hin zu Multi-Agent-Gesprächen, um effizient in enger Integration in die LLM selbst auszuführen.
Der Zweck von AICI ist es, es einfach zu machen, mit vorhandenen und völlig neuen Controller -Strategien zur Verbesserung der LLM -Generationen zu erstellen und zu experimentieren. Durch die Abstrahiere von Implementierungsdetails der zugrunde liegenden LLM -Inferenz und der Serviermotor soll AICI die Entwicklung von Controllern vereinfachen, schnelle Controller einfacher zu schreiben und die Kompatibilität über LLM -Inferenz- und Serviermotoren zu vereinfachen.
AICI ist sowohl für die lokale als auch für die Cloud-Ausführung ausgelegt, einschließlich (letztendlich) Multi-Tenant-LLM-Bereitstellungen. Controllers are implemented as light-weight WebAssembly (Wasm) modules which run on the same machine as the LLM inference engine, utilizing the CPU while the GPU is busy with token generation. AICI ist eine Schicht im Inferenzstapel und dient damit, Steuerbibliotheken wie Leitfaden, LMQL und andere zu ermöglichen, darüber hinaus zu laufen und sowohl Effizienz- als auch Leistungsverbesserungen sowie die Tragabilität über LLM -Inferenz- und Serviermotoren zu gewinnen.
AICI integriert sich derzeit in LLAMA.CPP, Huggingface-Transformatoren und Rllm (benutzerdefinierte TCH-basierte LLM Inference Engine) mit VLLM in Arbeit.
Aici ist:
AICI ist ein Prototyp, der in Microsoft Research entworfen und gebaut wurde.
In diesem QuickStart führen wir Sie durch die folgenden Schritte:
Um AICI -Komponenten zusammenzustellen, müssen Sie Ihre Entwicklungsumgebung für Rost einrichten. Für diesen QuickStart benötigen Sie auch Python 3.11 oder später, um einen Controller zu erstellen.
Notiz
Windows -Benutzer : Bitte verwenden Sie WSL2 oder den enthaltenen DevContainer. Das Hinzufügen von nativem Windows -Support wird hier verfolgt.
MacOS-Benutzer : Bitte stellen Sie sicher, dass Sie Xcode-Befehlszeilen-Tools installieren lassen, indem Sie xcode-select -p ausführen und, falls sie nicht installiert sind, xcode-select --install ausführen.
CUDA : Der CUDA -Build basiert auf einer spezifischen Libtorch -Installation. Es wird dringend empfohlen, den mitgelieferten DevContainer zu verwenden.
Wenn Sie DevContainer verwenden, können Sie zum nächsten Abschnitt gehen.
Installieren Sie mit dem Systempaketmanager die erforderlichen Tools für das Erstellen von Code im Repository, einschließlich git , cmake und ccache .
Zum Beispiel in WSL / Ubuntu mit 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
oder mit Homebrew auf macOS:
brew install git cmake ccache
Installieren Sie dann Rost, Rustup und Fracht und folgen Sie den Anweisungen hier und hier:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Überprüfen Sie nach der Installation, dass der Befehl rustup --version zugänglich ist, indem er vom Terminal aus ausgeführt wird. Wenn der Befehl nicht erkannt wird, öffnen Sie eine neue Terminalsitzung.
Als nächstes installieren Sie die WASM32-WASI-Rust-Komponente:
rustup target add wasm32-wasi
Wenn Sie bereits Rost installiert haben oder Beschwerden von Fracht über veraltete Versionen erhalten, rennen Sie:
rustup update
Um mit Python Controllern und Skripten (wie dieses Tutorial) mit Python -Controllern und -Skripten zu arbeiten, führen Sie diesen Befehl aus, um die erforderlichen Pakete zu installieren:
pip install pytest pytest-forked ujson posix_ipc numpy requests
Der RLLM-Server verfügt über zwei Backends, eine basierend auf libtorch und CUDA ( rllm-cuda ) und die andere auf llama.cpp ( rllm-llamacpp ).
Das rllm-cuda Backend funktioniert nur mit Nvidia GPUs mit Rechnungsfunktion 8.0 oder später (A100 und später; RTX 30x0 und später) und erfordert eine fummelige Einrichtung von Libtorch-es wird dringend empfohlen, den eingeschlossenen DevContainer zu verwenden. Während sich diese Anleitung auf das rllm-llamacpp Backend konzentriert, sind die Build-Schritte für rllm-cuda gleich, modulo den Ordnernamen.
Klonen Sie nach dem oben genannten Dev Env -Setup das AICI -Repository und fahren Sie mit den folgenden nächsten Schritten fort.
Verwenden Sie den folgenden Befehl, um aicirt und rllm-llamacpp zu erstellen und auszuführen:
cd rllm/rllm-llamacpp
./server.sh phi2
Sie können andere Modellnamen als Argument übergeben (ausführen ./server.sh ohne Argumente, um verfügbare Modelle anzuzeigen). Sie können auch eine URL von Suggingface verwenden, um .gguf -Datei oder einen lokalen Pfad zu einer .gguf -Datei. (Verwenden Sie für rllm-cuda die Huggingface-Modell-ID oder Pfad zum Ordner).
./server.sh orca
Weitere Informationen zu rllm-llamacpp finden Sie hier.
Der RLLM -Server bietet eine HTTP -Schnittstelle, die für Konfigurationsaufgaben und Verarbeitungsanforderungen verwendet wird. Sie können diese Schnittstelle auch verwenden, um ihren Status umgehend zu überprüfen. Wenn Sie beispielsweise http://127.0.0.1:4242/v1/models öffnen, sollten Sie sehen:
{
"object" : " list " ,
"data" : [
{
"object" : " model " ,
"id" : " TheBloke/phi-2-GGUF " ,
"created" : 946810800 ,
"owned_by" : " owner "
}
]
}bestätigt, dass das ausgewählte Modell geladen ist.
AICI ermöglicht das Hosting benutzerdefinierter Logik, genannte Controller , die mit der LLMS -Token -Generation initiieren, enden und interagieren. Controller nehmen Eingabeargumente ein, verarbeiten sie und geben ein Ergebnis mit Logs, LLM -Token und Variablen zurück.
Das Repository enthält insbesondere einige Beispiele:
In diesem Beispiel verwenden wir PYCTRL , um die Token -Generation mithilfe eines einfachen Python -Skripts zu verwalten. If you want, you can build and upload pyctrl, however by default the server will automatically download the latest release of pyctrl from GitHub.
Im Allgemeinen erfordern Controller Erstellung und Bereitstellung, während Skripte (Python oder JavaScript) mit jeder Anfrage gesendet werden.
Das Folgende zeigt die Beziehung zwischen dem RLLM -Server, der AICI -Laufzeit und dem Controller:
Erdiagram
Host ||-| {CPU: ""
Host ||-| {GPU: ""
CPU ||-|| "Rllm Server": Ausführen
CPU ||-| {"AICI-Laufzeit": Ausführen
"AICI-Laufzeit" ||-|| "Controller": Instantiate
GPU ||-| {"LLM Token Generation": Ausführen
Angenommen, wir streben ein Modell an, um eine Liste zu generieren, sich an ein bestimmtes Format zu halten und nur fünf Elemente zu enthalten.
In der Regel beinhaltet das Erreichen eines sofortigen Engineering und das Erstellen der Eingabeaufforderung genau mit klaren Anweisungen wie:
What are the five most popular types of vehicles?
Return the result as a numbered list.
Do not add explanations, only the list.
Die Eingabeaufforderung würde auch abhängig vom verwendeten Modell variieren, da jedes Modell Erklärungen hinzufügt und Anweisungen auf unterschiedliche Weise versteht.
Mit AICI verschieben wir die Kontrolle wieder in den Code und können die Eingabeaufforderung zu vereinfachen:
What are the most popular types of vehicles?
Verwenden von Code zu:
Erstellen wir eine Python-Datei list-of-five.py Python mit dem folgenden Inhalt:
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 ())Das Ausführen des Skripts unterscheidet sich nicht allzu vom Senden einer Eingabeaufforderung. In diesem Fall senden wir die Kontrolllogik und Anweisungen zusammen.
Um das Endergebnis zu sehen, führen Sie den folgenden Befehl aus:
./aici.sh run list-of-five.py
Ergebnis:
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'}
Dieses Repository enthält eine Reihe von Komponenten, und welche Sie benötigen, hängt von Ihrem Anwendungsfall ab.
Sie können ein vorhandenes Controller -Modul verwenden . Wir stellen PYCTRL und JSCTRL bereit, mit denen Sie Skript-Controller mithilfe von serverseitigem Python bzw. JavaScript mit Skript-Controllern können. Das Pyaici -Paket enthält aici -Befehlszeilen -Tool, mit dem Sie Skripte hochladen und mit jedem Controller ausführen können (wir stellen auch die REST -API -Definition für die Neugierigen an).
?
Wir gehen davon aus, dass Bibliotheken auf Controllern aufgebaut werden. Wir geben ein Beispiel in Promptlib - eine clientseitige Python -Bibliothek, die interagiert mit DECDCTRL über das Pyaici -Paket.
Beispiel Notizbuch, mit dem forderlib mit Declctrl interagiert wird.
Die Controller können in einer Cloud- oder lokalen AICi-fähigen LLM-Inferenzmotor ausgeführt werden. Sie können die bereitgestellte Referenzmotor (RLLM) vor Ort mit libtorch+cuda oder lama.cpp -Backend ausführen .
To develop a new controller , use a Rust starter project that shows usage of aici_abi library, which simplifies implementing the low-level AICI interface.
?
Um einer neuen LLM-Inferenz-Engine AICI-Unterstützung hinzuzufügen , müssen Sie die LLM-Seite des Protokolls implementieren, das mit der AICI-Laufzeit spricht.
Schließlich möchten Sie möglicherweise eine der bereitgestellten Komponenten ändern - PRs sind sehr willkommen!
AICI Abstracts LLM Inferenzmotor vom Controller und umgekehrt, wie im Bild unten. Die abgerundeten Knoten sind Aspiration. Zusätzliche Ebenen können oben aufgebaut werden - wir bieten promptlib, aber wir glauben fest, dass Leitlinien, LMQL, Sglang, Umrisse, Jsonformer, LMFE usw. auch auf AICI ausgeführt werden können (entweder mit benutzerdefinierten Controllern oder Verwendung von Pyctrl oder JSCtrl).
Graph TD
Pyctrl-aici-> AICIRT [AICI-Runtime]
JSCTRL -AICI -> AICIRT
Anleitung ([Guidancectrl]) -AICI -> AICIRT
LMQL ([LMQL Strl]) -AICI -> AICIRT
AICIRT -POSIX SHM -> rllm
AICIRT -POSIX SHM -> LAMA [lama.cpp]
Aicirt -posix shm -> pyaici
Pyaici -Python -> vllm (Vllm)
Pyaici -Python -> HF [HF -Transformatoren]
Das Pyaici-Paket erleichtert die Integration von AICI in Python-basierte LLM-Inferenzmotoren. Schauen Sie sich die Integration mit Huggingface -Transformatoren an, beachten Sie jedoch, dass es nicht unterstützt wird (Generierung mehrerer Sequenzen parallel). Der VLLM REST Server ist derzeit veraltet. Bitte verwenden Sie vorerst die rllm-cuda oder rllm-llama.cpp.
aicirt läuft in einem separaten Prozess und kann unter einem anderen Benutzer als die LLM -Engine ausgeführt werdenaici_host_* -Funktionen, die in hostImpl.rs implementiert sindaicirt legt auch eine partielle WASI -Schnittstelle frei; Allerdings sind fast alle Funktionen no-op, mit Ausnahme von fd_write , die die Dateideskriptoren 1 und 2 (STDOut und Stderr) für die Drucken von Debug-Nachrichten druckenInsbesondere können WASM -Module nicht auf das Dateisystem, das Netzwerk oder andere Ressourcen zugreifen. Sie können auch keine Threads drehen oder auf Timer zugreifen (dies ist für Gespenst-/Melddown -Angriffe relevant).
Der größte Teil der Berechnung in AICI -Controllern erfolgt parallel zur Logit -Erzeugung der GPU auf der CPU. Die Erzeugung tritt in Schritten auf, bei denen Logits parallel für ein neues Token für jede Sequenz in einer Stapel (typischerweise zwischen 1 und 50) erzeugt werden. Dies beinhaltet das Lesen des gesamten Modells und KV -Caches für Sequenzen in der Stapel aus dem GPU -Speicher. Für einen optimalen Batch -Durchsatz sollten das Modell und die KV -Caches einen Hauptanteil des GPU -Speichers verwenden, und das Lesen des gesamten Speichers dauert ungefähr 40 ms auf A100 GPU (80 GB).
Somit nimmt jeder Schritt der Erzeugung die Reihenfolge von 20-50 ms an. Mit sorgfältigem Engineering ist dies mehr als ausreichend, um die von WASM zusammengestellten Rostmengen in Rost zu berechnen. Diese können entweder nativ in Rost oder über Python- oder JavaScript -Dolmetscher kombiniert werden, die wir bereitstellen.
Zum Beispiel dauert ein Computer-Zulassungs-Token, der im 32000-köpfigen Vokabular des Lama-Modells eingestellt ist:
Die obigen Zahlen sind für eine einzelne Sequenz, jedoch wird jede Sequenz im getrennten Prozess verarbeitet. Wenn es also mehr Kerne gibt als Sequenzen (was typisch ist), ändern sie sich nicht. Dazu gehören auch Overhead of Calling in Python Interpreter, das in WASM implementiert wurde, und dann wieder in den Rost-generierten WASM-Code für die Einschränkung selbst. Sie sind alle gut im Budget von 20-50 ms. Daher beeinflussen sie die Generationszeit überhaupt nicht.
Es gibt auch einen Aufwand im kritischen Weg der Probenahme. Es kommt auf etwa 0,3 ms pro Generierungsschritt bei, wenn 10 Sequenzen parallel ausführt (dies ist unabhängig von der verwendeten Einschränkung). Der Overhead liegt auf rund 0,7 ms für 40 Sequenzen (obwohl er noch nicht vollständig optimiert wurde).
Die WebAssembly ist im Vergleich zu nativem Code nur minimaler Overhead aufweist. Nach unserer Erfahrung ist der hoch optimierte Rust -Code weniger als 2x langsamer, wenn Sie in WASMTIME als nativ ausgeführt werden. Dies ist 10-100x besser als JavaScript oder Python.
Alle Messungen an AMD EPYC 7v13 mit NVIDIA A100 GPU mit 80 GB VRAM.
Die AICI-Laufzeit mit niedriger Ebene ermöglicht es::
Es kann von jeder Sprache verwendet werden, die zu WASM kompiliert.
Dieses Repository bietet eine Rust -Bibliothek, die es einfach macht, Controller in Rost zu implementieren, und effiziente Implementierungen spezifischer Einschränkungen (reguläre Ausdrücke, YACC -Grammatiken, Substrings). Wir stellen auch Python- und JavaScript -Dolmetscher zur Verfügung, die es ermöglichen, diese Einschränkungen zusammenkleben zu lassen. All dies kann leicht verlängert werden.
If you find the AI Controller Interface and its ideas for defining a new layer in the LLM inference stack useful, please cite the package using the following reference:
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/} }
}Dieses Projekt begrüßt Beiträge und Vorschläge. Bei den meisten Beiträgen müssen Sie einer Mitarbeiters Lizenzvereinbarung (CLA) zustimmen, in der Sie erklären, dass Sie das Recht haben und uns tatsächlich tun, um uns die Rechte zu gewähren, Ihren Beitrag zu verwenden. Weitere Informationen finden Sie unter https://cla.opensource.microsoft.com.
Wenn Sie eine Pull -Anfrage einreichen, bestimmt ein CLA -Bot automatisch, ob Sie einen CLA angeben und die PR angemessen dekorieren müssen (z. B. Statusprüfung, Kommentar). Befolgen Sie einfach die vom Bot bereitgestellten Anweisungen. Sie müssen dies nur einmal über alle Repos mit unserem CLA tun.
Dieses Projekt hat den Microsoft Open Source -Verhaltenscode übernommen. Weitere Informationen finden Sie im FAQ oder wenden Sie sich an [email protected] mit zusätzlichen Fragen oder Kommentaren.
Dieses Projekt kann Marken oder Logos für Projekte, Produkte oder Dienstleistungen enthalten. Die autorisierte Verwendung von Microsoft -Marken oder Logos unterliegt den Marken- und Markenrichtlinien von Microsoft und muss folgen. Die Verwendung von Microsoft -Marken oder Logos in geänderten Versionen dieses Projekts darf keine Verwirrung verursachen oder Microsoft -Sponsoring implizieren. Jede Verwendung von Marken oder Logos von Drittanbietern unterliegt den Richtlinien dieses Drittanbieters.