diff --git a/docs/inkling-akash.md b/docs/inkling-akash.md new file mode 100644 index 0000000..25aec62 --- /dev/null +++ b/docs/inkling-akash.md @@ -0,0 +1,74 @@ +# Inkling on Akash + +## Configuration optimale + +Inkling compte 975 milliards de paramètres et nécessite un cluster de GPU spécialisés pour l'auto-hébergement. Une RTX 3090 de 24 GiB ne peut pas charger le modèle. + +La solution la moins chère est donc, dans cet ordre : + +1. appeler directement une API Inkling compatible OpenAI ; +2. si un endpoint privé et une clé client distincte sont nécessaires, déployer une petite passerelle LiteLLM CPU sur Akash ; +3. ne louer une RTX 3090 que pour un autre modèle local compatible, car elle ne sert à rien pour une passerelle API Inkling. + +Le profil par défaut du script est désormais CPU-only : + +- 0,5 vCPU ; +- 1 GiB de RAM ; +- 1 GiB de stockage éphémère ; +- aucune carte graphique ; +- plafond d'enchère de 25 uACT par bloc, soit environ 10,80 ACT par mois au maximum configuré. Le prix réel dépend de l'offre gagnante. + +## Prérequis + +- Un compte Akash financé. +- Le CLI `provider-services` configuré avec une clé Akash. +- Un endpoint Inkling compatible avec l'API OpenAI. +- Une clé API du fournisseur. + +## Générer le SDL + +```bash +export INKLING_API_BASE='https://provider.example/v1' +export INKLING_API_KEY='replace-me' +export LITELLM_MASTER_KEY="$(openssl rand -hex 32)" + +bash scripts/bash/deploy_inkling_akash.sh --dry-run +bash scripts/bash/deploy_inkling_akash.sh --output deploy-inkling-akash.yaml +``` + +Le fichier SDL contient les secrets. Ne le commitez pas et supprimez-le après le déploiement. + +## Déployer + +```bash +export AKASH_KEY_NAME='your-akash-key' +bash scripts/bash/deploy_inkling_akash.sh --deploy +``` + +Après la création du déploiement, sélectionnez une offre fournisseur et envoyez le manifeste avec votre workflow Akash habituel. La passerelle expose une API compatible OpenAI sur le port 80. + +## Tester + +```bash +curl 'http://YOUR_AKASH_HOST/v1/chat/completions' \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "inkling", + "messages": [{"role": "user", "content": "Bonjour"}] + }' +``` + +## Profil RTX 3090 + +Le profil historique reste disponible uniquement pour comparaison : + +```bash +bash scripts/bash/deploy_inkling_akash.sh --profile rtx3090 --dry-run +``` + +Il affiche un avertissement, car le GPU reste inutilisé par la passerelle et peut ajouter plusieurs centaines de dollars par mois. Il ne permet pas d'auto-héberger Inkling. + +## Réduction supplémentaire du coût + +Pour un usage personnel ou un seul client, utilisez directement `INKLING_API_BASE` depuis l'application et ne déployez aucune passerelle. La passerelle Akash devient utile pour centraliser les clés, présenter un endpoint stable, appliquer des quotas ou connecter plusieurs applications. \ No newline at end of file diff --git a/scripts/bash/deploy_inkling_akash.sh b/scripts/bash/deploy_inkling_akash.sh new file mode 100644 index 0000000..bd87ed7 --- /dev/null +++ b/scripts/bash/deploy_inkling_akash.sh @@ -0,0 +1,190 @@ +#!/usr/bin/env bash +set -euo pipefail + +OUTPUT_FILE="deploy-inkling-akash.yaml" +PROFILE="cpu" +MAX_PRICE_UACT="25" +CPU_UNITS="0.5" +MEMORY_SIZE="1Gi" +STORAGE_SIZE="1Gi" +LITELLM_IMAGE="ghcr.io/berriai/litellm:v1.92.0" +DEPLOY=false +DRY_RUN=false + +usage() { + cat <<'EOF' +Generate and optionally submit a cost-optimized Akash SDL for Inkling. + +Inkling cannot run locally on one RTX 3090. The optimal low-cost setup is a +small CPU-only LiteLLM gateway forwarding to an OpenAI-compatible Inkling API. +For the absolute lowest cost, call the upstream API directly and skip Akash. + +Usage: + deploy_inkling_akash.sh [options] + +Options: + --profile cpu|rtx3090 Resource profile (default: cpu) + --cpu UNITS CPU cores for cpu profile (default: 0.5) + --memory SIZE RAM (default: 1Gi) + --storage SIZE Ephemeral storage (default: 1Gi) + --max-price-uact N Maximum ACT micro-units per block (default: 25) + --output FILE Generated SDL path + --deploy Submit SDL with provider-services + --dry-run Print SDL and estimated maximum monthly cost + -h, --help Show help + +Required environment variables: + INKLING_API_BASE OpenAI-compatible upstream base URL + INKLING_API_KEY Upstream API token + LITELLM_MASTER_KEY Client-facing gateway key + +Optional environment variables: + INKLING_MODEL_NAME Upstream model identifier (default: inkling) + +Example: + export INKLING_API_BASE='https://provider.example/v1' + export INKLING_API_KEY='...' + export LITELLM_MASTER_KEY="$(openssl rand -hex 32)" + bash scripts/bash/deploy_inkling_akash.sh --dry-run + bash scripts/bash/deploy_inkling_akash.sh --deploy +EOF +} + +fail() { printf 'ERROR: %s\n' "$*" >&2; exit 1; } + +require_positive_integer() { + [[ "$2" =~ ^[1-9][0-9]*$ ]] || fail "$1 must be a positive integer" +} + +require_cpu_value() { + [[ "$1" =~ ^([0-9]+([.][0-9]+)?|[0-9]+m)$ ]] || fail "--cpu must be numeric or millicores (for example 0.5 or 500m)" +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --profile) [[ $# -ge 2 ]] || fail "--profile requires a value"; PROFILE="$2"; shift 2 ;; + --cpu) [[ $# -ge 2 ]] || fail "--cpu requires a value"; CPU_UNITS="$2"; shift 2 ;; + --memory) [[ $# -ge 2 ]] || fail "--memory requires a value"; MEMORY_SIZE="$2"; shift 2 ;; + --storage) [[ $# -ge 2 ]] || fail "--storage requires a value"; STORAGE_SIZE="$2"; shift 2 ;; + --max-price-uact) [[ $# -ge 2 ]] || fail "--max-price-uact requires a value"; MAX_PRICE_UACT="$2"; shift 2 ;; + --output) [[ $# -ge 2 ]] || fail "--output requires a value"; OUTPUT_FILE="$2"; shift 2 ;; + --deploy) DEPLOY=true; shift ;; + --dry-run) DRY_RUN=true; shift ;; + -h|--help) usage; exit 0 ;; + *) fail "unknown option: $1" ;; + esac +done + +case "$PROFILE" in + cpu) ;; + rtx3090) + printf 'WARNING: RTX 3090 is unused in API gateway mode and can cost hundreds of dollars per month.\n' >&2 + ;; + *) fail "--profile must be cpu or rtx3090" ;; +esac + +require_cpu_value "$CPU_UNITS" +require_positive_integer "--max-price-uact" "$MAX_PRICE_UACT" +[[ "$MEMORY_SIZE" =~ ^[1-9][0-9]*(Mi|Gi)$ ]] || fail "--memory must use Mi or Gi" +[[ "$STORAGE_SIZE" =~ ^[1-9][0-9]*(Mi|Gi)$ ]] || fail "--storage must use Mi or Gi" + +: "${INKLING_API_BASE:?Set INKLING_API_BASE}" +: "${INKLING_API_KEY:?Set INKLING_API_KEY}" +: "${LITELLM_MASTER_KEY:?Set LITELLM_MASTER_KEY to a long random secret}" + +MODEL_NAME="${INKLING_MODEL_NAME:-inkling}" + +GPU_BLOCK="" +if [[ "$PROFILE" == "rtx3090" ]]; then + GPU_BLOCK=$(cat <<'EOF' + gpu: + units: 1 + attributes: + vendor: + nvidia: + - model: rtx3090 + ram: 24Gi + interface: pcie +EOF +) +fi + +read -r -d '' SDL </tmp/litellm.yaml <<'YAML' + model_list: + - model_name: inkling + litellm_params: + model: openai/\${INKLING_MODEL_NAME} + api_base: \${INKLING_API_BASE} + api_key: \${INKLING_API_KEY} + general_settings: + master_key: \${LITELLM_MASTER_KEY} + YAML + exec litellm --config /tmp/litellm.yaml --host 0.0.0.0 --port 4000 + expose: + - port: 4000 + as: 80 + to: + - global: true + +profiles: + compute: + inkling-gateway: + resources: + cpu: + units: ${CPU_UNITS} + memory: + size: ${MEMORY_SIZE} + storage: + size: ${STORAGE_SIZE} +${GPU_BLOCK} + placement: + akash: + pricing: + inkling-gateway: + denom: uact + amount: ${MAX_PRICE_UACT} + +deployment: + inkling-gateway: + akash: + profile: inkling-gateway + count: 1 +EOF + +# Approximately 432,000 six-second blocks in 30 days; 1,000,000 uACT = 1 ACT. +MONTHLY_MAX_ACT=$(awk -v amount="$MAX_PRICE_UACT" 'BEGIN { printf "%.2f", amount * 432000 / 1000000 }') +printf 'Profile: %s | maximum configured bid: about %s ACT/month (actual winning bid may be lower).\n' "$PROFILE" "$MONTHLY_MAX_ACT" >&2 + +if [[ "$DRY_RUN" == true ]]; then + printf '%s\n' "$SDL" + printf '\nDry run only; nothing was written or deployed.\n' >&2 + exit 0 +fi + +umask 077 +printf '%s\n' "$SDL" >"$OUTPUT_FILE" +printf 'Generated %s\n' "$OUTPUT_FILE" +printf 'Security: this SDL contains secrets. Do not commit it; remove it after deployment.\n' >&2 + +if [[ "$DEPLOY" == true ]]; then + command -v provider-services >/dev/null 2>&1 || fail "provider-services CLI is required for --deploy" + provider-services tx deployment create "$OUTPUT_FILE" --from "${AKASH_KEY_NAME:?Set AKASH_KEY_NAME}" --yes +else + printf 'Review the SDL, then deploy it with provider-services.\n' +fi