A interface do Controlador de Inteligência Artificial (AICI) permite criar controladores que restrinjam e diretamente a saída de um modelo de linguagem grande (LLM) em tempo real. Os controladores são programas flexíveis capazes de implementar decodificação restrita, edição dinâmica de prompts e texto gerado e execução de coordenação em várias gerações paralelas. Os controladores incorporam a lógica personalizada durante a decodificação de token-by-togen e mantenha o estado durante uma solicitação LLM. Isso permite diversas estratégias de controlador, desde decodificação programática ou baseada em consulta a conversas multi-agentes, execute com eficiência na integração rígida com o próprio LLM.
O objetivo da AICI é facilitar a construção e a experiência das estratégias de controlador existentes e totalmente novas para melhorar as gerações do LLM. Ao abstrair os detalhes da implementação do mecanismo de inferência e servir LLM subjacentes, a AICI visa simplificar o desenvolvimento de controladores, facilitar a redação de controladores rápidos e facilitam a compatibilidade entre os motores de inferência e serviço do LLM.
A AICI foi projetada para execução local e em nuvem, incluindo (eventualmente) implantações de LLM com vários inquilinos. Os controladores são implementados como módulos leves WebAssembly (WASM) que são executados na mesma máquina que o mecanismo de inferência LLM, utilizando a CPU enquanto a GPU está ocupada com a geração de token. A AICI é uma camada na pilha de inferência e foi projetada para permitir que bibliotecas de controle, como orientação, LMQL e outros, para executar e obter melhorias de eficiência e desempenho, além de portabilidade entre os motores de inferência e serviço do LLM.
Atualmente, a AICI se integra ao llama.cpp, nos transformadores do Huggingface e no RLLM (mecanismo de inferência de LLM baseado em TCH personalizado), com VLLM nos trabalhos.
AICI é:
A AICI é um protótipo, projetado e construído na Microsoft Research.
Neste Início Quick, vamos guiá -lo pelas seguintes etapas:
Para compilar os componentes da AICI, você precisa configurar seu ambiente de desenvolvimento para ferrugem. Para esse início rápido, você também precisa do Python 3.11 ou posterior para criar um controlador.
Observação
Usuários do Windows : use o WSL2 ou o devContainer incluído. Adicionar suporte ao Windows nativo é rastreado aqui.
Usuários do MacOS : verifique se você possui ferramentas de linha de comando xcode instaladas executando xcode-select -p e, se não estiver instalado, execute xcode-select --install .
CUDA : A compilação CUDA depende de instalação específica de Libtorch. É altamente recomendável que você use o devContainer incluído.
Se você estiver usando o DevContainer, poderá pular para a próxima seção.
Usando o gerenciador de pacotes do sistema, instale as ferramentas necessárias para criar código no repositório, incluindo git , cmake e ccache .
Por exemplo, no WSL / Ubuntu usando 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
ou usando homebrew no macOS:
brew install git cmake ccache
Em seguida, instale a ferrugem, a ferrugem e a carga , seguindo as instruções fornecidas aqui e aqui:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Após a instalação, verifique se o comando rustup --version está acessível executando -o no terminal. Se o comando não for reconhecido, tente abrir uma nova sessão de terminal.
Próximo Instalação WASM32-WASI RUST Component:
rustup target add wasm32-wasi
Se você já teve a ferrugem instalada ou está recebendo queixas da Cargo sobre versões desatualizadas, execute:
rustup update
Por fim, para trabalhar com controladores e scripts Python (como este tutorial), execute este comando para instalar os pacotes necessários:
pip install pytest pytest-forked ujson posix_ipc numpy requests
O servidor RLLM possui dois back-end, um baseado em libtorch e cuda ( rllm-cuda ) e o outro com base no llama.cpp ( rllm-llamacpp ).
O back-end rllm-cuda funciona apenas com NVIDIA GPUs com capacidade de computação 8.0 ou posterior (A100 e posterior; RTX 30x0 e posterior) e requer uma configuração complicada de Libtorch-é fortemente recomendável usar o devContainer incluído. Embora este guia se concentre no back-end rllm-llamacpp , as etapas de construção são as mesmas para rllm-cuda , Modulo o nome da pasta.
Após a configuração do Dev Env acima, clone o repositório AICI e prossiga com as próximas etapas descritas abaixo.
Use o seguinte comando para construir e executar aicirt e rllm-llamacpp :
cd rllm/rllm-llamacpp
./server.sh phi2
Você pode passar outros nomes de modelos como argumento (execute ./server.sh sem argumentos para ver os modelos disponíveis). Você também pode usar um URL do Huggingface para .gguf ou um caminho local para um arquivo .gguf . (Para rllm-cuda use o ID do modelo HuggingFace ou o caminho para a pasta).
./server.sh orca
Você pode encontrar mais detalhes sobre rllm-llamacpp aqui.
O servidor RLLM fornece uma interface HTTP, utilizada para tarefas de configuração e solicitações de processamento. Você também pode usar essa interface para verificar imediatamente seu status. Por exemplo, se você abrir http://127.0.0.1:4242/v1/models, você deve ver:
{
"object" : " list " ,
"data" : [
{
"object" : " model " ,
"id" : " TheBloke/phi-2-GGUF " ,
"created" : 946810800 ,
"owned_by" : " owner "
}
]
}confirmando que o modelo selecionado está carregado.
A AICI permite hospedar lógica personalizada, chamada controladores , que iniciam, encerram e interajam com a geração de token LLMS. Os controladores assumem argumentos de entrada, processam -os e retornam um resultado com logs, tokens LLM e variáveis.
O repositório inclui alguns exemplos, em particular:
Neste exemplo, utilizaremos o Pyctrl para gerenciar a geração de token usando um script python simples. Se desejar, você pode criar e fazer upload de pyctrl, no entanto, por padrão, o servidor baixará automaticamente a versão mais recente do Pyctrl no GitHub.
Em geral, os controladores exigem construção e implantação, enquanto os scripts (Python ou JavaScript) são enviados a cada solicitação.
A seguir, ilustra o relacionamento entre o servidor RLLM, o tempo de execução da AICI e o controlador:
erdiagram
Host ||-| {cpu: ""
Host ||-| {gpu: ""
CPU ||-|| "Rllm Server": execute
CPU ||-| {"AICI Runtime": Execute
"Aici Runtime" ||-|| "Controlador": instanciado
GPU ||-| {"LLM Token Generation": Execute
Suponha que busquemos um modelo para gerar uma lista, aderindo a um formato específico e contendo apenas cinco itens.
Normalmente, conseguir isso envolve engenharia imediata, elaborando o prompt precisamente com instruções claras, como:
What are the five most popular types of vehicles?
Return the result as a numbered list.
Do not add explanations, only the list.
O prompt também variaria dependendo do modelo em uso, já que cada modelo tende a adicionar explicações e entender as instruções de maneiras diferentes.
Com a AICI, mudamos o controle de volta ao código e podemos simplificar o prompt para:
What are the most popular types of vehicles?
Usando o código para:
Vamos criar um arquivo python list-of-five.py com o seguinte conteúdo:
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 ())A execução do script não é muito diferente de enviar um prompt. Nesse caso, estamos enviando lógica de controle e instruções todas juntas.
Para ver o resultado final, execute o seguinte comando:
./aici.sh run list-of-five.py
Resultado:
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'}
Este repositório contém vários componentes e quais você precisa depende do seu caso de uso.
Você pode usar um módulo de controlador existente . Fornecemos Pyctrl e JSCTRL que permitem controladores de script usando o Python e JavaScript do lado do servidor, respectivamente. O pacote pyaici contém ferramenta de linha de comando aici que permite fazer upload e executar scripts com qualquer controlador (também fornecemos definição de API REST para o curioso).
? Python amostras para script pyctrl e um javascript hello world for jsctrl
Prevemos que as bibliotecas serão construídas sobre os controladores. Fornecemos um exemplo no PromptLib - uma biblioteca Python do lado do cliente que gera interage com o Declctrl através do pacote pyaici.
? Notebook Exemplo que usa o promptLib para interagir com o DCLCTRL.
Os controladores podem ser executados em uma nuvem ou mecanismo local de inferência LLM habilitado para a AIC. Você pode executar o mecanismo de referência fornecido (RLLM) localmente com o back -end Libtorch+Cuda ou LLAMA.CPP.
Para desenvolver um novo controlador , use um projeto inicial do Rust que mostre o uso da biblioteca AICI_ABI, que simplifica a implementação da interface AICI de baixo nível.
"Sample Code para um novo controlador mínimo para você começar
Para adicionar suporte da AICI a um novo mecanismo de inferência LLM , você precisará implementar o lado do LLM do protocolo que fala com o AICI Runtime.
Por fim, você pode modificar qualquer um dos componentes fornecidos - os PRs são bem -vindos!
Aici Abstracts LLM Inferência do Motor do controlador e vice-versa, como na figura abaixo. Os nós arredondados são aspiracionais. Camadas adicionais podem ser construídas na parte superior - fornecemos PromptLib, mas acreditamos firmemente que a orientação, LMQL, SGLANG, EXPLORES, JSONFERMER, LMFE, ETC. também pode ser executada em cima da AICI (com controladores personalizados ou utilizando pyctrl ou jsctrl).
Gráfico TD
Pyctrl-Aici-> Aicirt [Aici-Runtime]
JSCTRL -AICI -> Aicirt
Orientação ([GuidanciCectrl]) -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]
O pacote Pyaici facilita a integração da AICI aos mecanismos de inferência LLM baseados em Python. Dê uma olhada na integração com os Transformers do Huggingface, embora observe que ele não suporta o forking (geração de múltiplas sequências em paralelo). O servidor VLLM REST está atualmente desatualizado. Por favor, use o rllm-cuda ou rllm-llama.cpp por enquanto.
aicirt é executado em um processo separado e pode ser executado sob um usuário diferente do mecanismo LLMaici_host_* , implementadas no HOSTIMPL.RSaicirt também expõe uma interface parcial de WASI; No entanto, quase todas as funções não são de OP, exceto fd_write , que descritores de arquivos de calços 1 e 2 (stdout e stderr) para imprimir mensagens de depuraçãoEm particular, os módulos WASM não podem acessar o sistema de arquivos, a rede ou qualquer outro recurso. Eles também não podem girar encadeamentos ou acessar nenhum temporizador (isso é relevante para ataques de espectro/colapso).
A maior parte da computação nos controladores AICI ocorre na CPU, paralelamente à geração de logit na GPU. A geração ocorre nas etapas, onde os logits são gerados em paralelo para um novo token para cada sequência em um lote (normalmente entre 1 e 50). Isso envolve a leitura de todo o modelo e os caches KV para seqüências no lote da memória da GPU. Para a taxa de transferência de lote ideal, o modelo e os caches KV devem utilizar uma fração importante da memória da GPU e a leitura de toda a memória leva cerca de 40ms na GPU A100 (80 GB).
Assim, cada etapa da geração assume a ordem de 20 a 50ms. Com uma engenharia cuidadosa, isso é mais do que suficiente para calcular o conjunto de tokens permitidos em ferrugem compilada ao WASM. Estes podem ser combinados nativamente em ferrugem ou por intérpretes python ou javascript que fornecemos.
Por exemplo, a computação permitiu o token definido no vocabulário de 32000 pessoas que o modelo de llama leva:
Os números acima são para uma única sequência, no entanto, cada sequência é processada em processo separado e, portanto, se houver mais núcleos que sequências (o que é típico), elas não mudam. Eles também incluem a sobrecarga de chamar o intérprete Python implementado no WASM e depois voltar ao código WASM gerado por ferrugem para a própria restrição. Eles estão todos bem dentro do orçamento de 20 a 50ms, por isso não afetam o tempo de geração.
Há também algumas despesas gerais no caminho crítico da amostragem. Tudo se resume a cerca de 0,3ms por etapa da geração ao executar 10 sequências em paralelo (isso é independente da restrição usada). A sobrecarga sobe para cerca de 0,7ms para 40 sequências (embora ainda não tenha sido totalmente otimizado).
O WebAssembly foi projetado para ter uma sobrecarga mínima, em comparação com o código nativo. Em nossa experiência, o código de ferrugem altamente otimizado é inferior a 2x mais lento quando executado em Wasmtime que nativo. Isso é 10-100X melhor que JavaScript ou Python.
Todas as medidas realizadas na AMD EPYC 7V13 com GPU NVIDIA A100 com 80 GB de VRAM.
A interface de baixo nível que o AICI Runtime fornece permite:
Pode ser utilizado a partir de qualquer idioma que compila com o WASM.
Esse repositório fornece uma biblioteca de ferrugem que facilita a implementação de controladores em ferrugem e fornece implementações eficientes de restrições específicas (expressões regulares, gramáticas YACC, substringas). Também fornecemos intérpretes de Python e JavaScript que permitem colar essas restrições. Tudo isso pode ser facilmente estendido.
Se você encontrar a interface do controlador AI e suas idéias para definir uma nova camada na pilha de inferência LLM útil, cite o pacote usando a seguinte referência:
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/} }
}Este projeto recebe contribuições e sugestões. A maioria das contribuições exige que você concorde com um Contrato de Licença de Colaborador (CLA) declarando que você tem o direito e, na verdade, concede -nos os direitos de usar sua contribuição. Para detalhes, visite https://cla.opensource.microsoft.com.
Quando você envia uma solicitação de tração, um BOT do CLA determina automaticamente se você precisa fornecer um CLA e decorar o PR adequadamente (por exemplo, verificação de status, comentar). Simplesmente siga as instruções fornecidas pelo bot. Você só precisará fazer isso uma vez em todos os repositórios usando nosso CLA.
Este projeto adotou o Código de Conduta Open Microsoft. Para obter mais informações, consulte o Código de Conduta Perguntas frequentes ou entre em contato com [email protected] com quaisquer perguntas ou comentários adicionais.
Este projeto pode conter marcas comerciais ou logotipos para projetos, produtos ou serviços. O uso autorizado de marcas comerciais ou logotipos da Microsoft está sujeito e deve seguir as diretrizes de marca registrada e marca da Microsoft. O uso de marcas comerciais da Microsoft ou logotipos em versões modificadas deste projeto não deve causar confusão ou implicar o patrocínio da Microsoft. Qualquer uso de marcas comerciais ou logotipos de terceiros estão sujeitas às políticas de terceiros.