Como Usar#

Acesso via API#

O AMALIA está disponível via API no IAedu para professores e investigadores. Após realizar login e escolher o modelo AMALIA, os parâmetros da API podem ser obtidos clicando na roda no canto superior direito. Com estes, é possível interagir com o modelo usando o código:

import requests
import json
formData = {
    "channel_id": channel_id,
    "thread_id": thread_id,
    "user_info": "{}",
    "message": message
}
response = requests.post(
    url=endpoint,
    headers= {'x-api-key': api_key },
    data=formData
)

for line in response.text.split('\n\n'):
    jsonline = json.loads(line)
    if jsonline["type"] == "message":
        print(jsonline["content"]["content"])
        break

Neste exemplo, message representa a mensagem enviada ao modelo e thread_id é o identificador da conversa, para manutenção do contexto.

Acesso ao Modelo Público#

O AMALIA está publicamente disponível em código-aberto via HuggingFace.

Como servir uma API localmente#

Para servir localmente o AMALIA, o hardware mínimo recomendado é de 4x GPUs NVIDIA A100 40GB. O software recomendado é o vLLM instalado em ambiente conda com Python 3.12+:

conda create -n vllm_env python=3.12
uv pip install vllm --torch-backend=auto
# Login HuggingFace
hf auth login

O seguinte script serve_llm.sh exemplifica como servir o AMALIA com vLLM recorrendo ao gestor de recursos slurm:

#!/bin/bash
#SBATCH --job-name=vllm-serve
#SBATCH --partition=slurm_queue
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --gres=gpu:nvidia_a100-sxm4-40gb:4  # Pedir 4 GPUs
#SBATCH --cpus-per-task=64                  # Alocar CPUs do sistema
#SBATCH --mem=256G                          # Alocar memória RAM do sistema
#SBATCH --output=logs/%x-%j.out
#SBATCH -e logs/%x-%j.err

# Ativar o ambiente conda
eval "$(conda shell.bash hook)"
source activate vllm_env

# Correr vLLM
# $1: Nome do modelo, $2: Host $3: Porto, $4: Chave API $5: Chat template
python -m vllm.entrypoints.openai.api_server \
    --model "$1" \
    --host "$2" \
    --port "$3" \
    --tokenizer-mode hf \
    --config-format hf \
    --enable-auto-tool-choice \
    --tool-call-parser llama3_json \
    --tensor-parallel-size 4 \
    --gpu-memory-utilization 0.90 \
    --api-key "$4" \
    --chat-template "$5"

Como exemplo, para correr localmente no porto 8001, com uma certa chave de API api_key, o script pode ser lançado com o comando abaixo. O ficheiro chat_template.jinja padrão está disponível no repositório HuggingFace.

sbatch serve_llm.sh carminho/AMALIA-9B-50-DPO 0.0.0.0 8001 api_key ./chat_template.jinja

Utilização de API local#

Tendo o modelo disponível em servidor local, um exemplo simples de utilização com curl é:

curl -X POST http://127.0.0.1:8001/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer api_key" \
    --data '{"model": "carminho/AMALIA-9B-50-DPO", "messages": [{"role": "user", "content": "Olá"}]}'

Ou usando Python:

import requests

url = "http://127.0.0.1:8001/v1/chat/completions"

headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer api_key"
}

payload = {
    "model": "carminho/AMALIA-9B-50-DPO",
    "messages": [
        {
            "role": "user",
            "content": "Olá"
        }
    ]
}

response = requests.post(url, headers=headers, json=payload)

if response.status_code == 200:
    print(response.json()['choices'][0]['message']['content'])
else:
    print(f"Error {response.status_code}: {response.text}")

Uma API local servida com vLLM desta forma segue o formato de API da OpenAI.

Os exemplos anteriores mostram como enviar mensagens únicas ao modelo. Para fornecer contexto anterior de uma conversa, basta juntar turnos anteriores à lista de messages, como por exemplo:

"messages": [
    {
        "role": "user",
        "content": "Por favor trata-me por Miguel"
    },
    {
        "role": "assistant",
        "content": "Olá, Miguel. Como posso ajudar-te hoje?"
    },
    {
        "role": "user",
        "content": "Qual é o meu nome?"
    }
]

Com a versão multimodal do modelo é possível também carregar imagens no input do utilizador. Para tal, um link para a imagem poderá ser adicionada ao content da mensagem, da forma:

"messages": [
    {
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "O que está nesta imagem?"
            },
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://upload.wikimedia.org/wikipedia/commons/3/39/Bacalhau_a_Bras.jpg"
                }
            }
        ]
    }
]

Outros parâmetros opcionais que poderão ser úteis são:

  • max_completion_tokens: Permite limitar o número de tokens da resposta do modelo;

  • temperature: Permite ajustar a variância das respostas. Um valor de 0 produz respostas deterministas, valores mais próximos de 1 permitem mais variância;

  • stream: Se true, o modelo funcionará em formato de streaming, respondendo token a token à medida que estes são gerados em tempo real. O processamento da resposta deverá ser feita de forma diferente que anteriormente dado o seu formato diferente.

Um exemplo de utilização destes parâmetros é:

payload = {
    "model": "carminho/AMALIA-9B-50-DPO",
    "messages": [
        {
            "role": "user",
            "content": "Olá"
        }
    ],
    "max_completion_tokens": 300,
    "temperature": 0,
    "stream": True
}