Дата публикации
ai_products

Как за 10 минут поднять локальный ИИ-сервис на Azure: гид по Foundry Local Model Catalog

Что нового

Microsoft показала на GitHub рабочий пример, который помогает развернуть первую языковую модель на Foundry Local поверх Azure Local за считанные минуты. Скрипт catalog_sample.py автоматизирует полный цикл:

  1. Читает каталог доступных моделей из Kubernetes ConfigMap.
  2. Создаёт кастомный ресурс ModelDeployment по выбранной записи каталога.
  3. Ждёт, пока развёртывание перейдёт в состояние Running + Ready (таймаут по умолчанию — 600 секунд).
  4. Запускает инференс через OpenAI‑совместимый эндпоинт /v1/chat/completions.
  5. При необходимости автоматически удаляет развёртывание.

Ключевые детали:

  • Поддержка CPU и GPU‑конфигураций.
  • Два рантайма инференса: ONNX-GenAI (onnx) и vLLM (vllm).
  • Возможность поднять модель Phi‑4‑generic‑cpu «по умолчанию» одной командой.
  • Полная совместимость с протоколом OpenAI API, включая работу через официальный Python SDK.
  • Сценарий для запуска как внутри кластера, так и с ноутбука с доступом по kubectl port-forward.

Это не просто демо, а готовый шаблон жизненного цикла модели в Kubernetes: от выбора в каталоге до реального запроса и последующей очистки.

Как это работает

Под капотом Foundry Local на Azure Local использует Kubernetes и собственный Inference Operator.

Архитектура

Есть две ключевые зоны:

  1. Ваша рабочая станция

    • Скрипт catalog_sample.py.
    • Kubernetes‑клиент, который ходит в API‑сервер:
      • читает ConfigMap с каталогом моделей;
      • создаёт и отслеживает ModelDeployment (CRD);
      • читает Secret с API‑ключом.
    • HTTP‑клиент (requests или OpenAI SDK), который шлёт запросы на эндпоинт инференса:
      • POST /v1/chat/completions;
      • авторизация через Authorization: Bearer <API_KEY>.
  2. Кластер Kubernetes (Azure Local)

    • Неймспейс foundry-local-operator.
    • Inference Operator, который следит за кастомными ресурсами.
    • ConfigMap foundry-local-catalog с catalog.json, синхронизированным из Azure AI Foundry.
    • CR ModelDeployment, из которого оператор создаёт Deployment + Service + Ingress.
    • Secret <name>-api-keys с первичным и вторичным API‑ключами.
    • Pod модели: контейнер инференса + sidecar с TLS.

Поток работы скрипта

Сценарий реализует следующий pipeline:

  1. Запрос каталога
    Скрипт читает ConfigMap кластера с описанием всех доступных моделей (имя, версии, поддерживаемые рантаймы, типы вычислений).

  2. Создание ModelDeployment
    На основе выбранной записи каталога скрипт формирует CR ModelDeployment в namespace foundry-local-operator. Оператор:

    • при первом обращении выполняет «ленивую регистрацию» — создаёт объект Model из каталога;
    • разворачивает Deployment, Service и Ingress для выбранной модели и рантайма.
  3. Ожидание готовности
    Скрипт опрашивает статус ModelDeployment, пока тот не станет Running + Ready или не истечёт таймаут (по умолчанию 600 секунд). Если образ модели ещё не скачан, развёртывание может подзависнуть в состоянии Creating — в этом случае нужно смотреть события Pod.

  4. Инференс через OpenAI‑совместимый API
    После готовности скрипт отправляет запрос на /v1/chat/completions. Эндпоинт полностью совместим с OpenAI API: тот же формат messages, model, max_tokens и т.д.

  5. Очистка
    По умолчанию скрипт удаляет ModelDeployment после инференса. Можно отключить это флагом --skip-cleanup и держать сервис в онлайне.

Используемые компоненты

Чтобы всё это работало, нужны:

  • Kubernetes‑кластер с установленным Foundry Local.
  • Azure Local с AKS или любой Arc‑подключённый Kubernetes‑кластер.
  • Inference Operator Foundry Local, установленный через Helm.
  • cert-manager и trust-manager для TLS.
  • Настроенный kubectl с правами:
    • читать ConfigMaps, Secrets, CRDs;
    • создавать/получать/удалять modeldeployments.foundrylocal.azure.com в foundry-local-operator.
  • Python 3.9+ с pip.

Что это значит для вас

Этот пример полезен, если вы:

  • Разворачиваете ИИ‑сервисы на своём Kubernetes и хотите минимизировать ручную работу.
  • Тестируете Foundry Local и Azure Local и хотите быстро получить живой OpenAI‑совместимый эндпоинт.
  • Пишете свои операторы/автоматизацию и ищете образец полного жизненного цикла модели.

Для каких задач подходит

  • Быстрый POC: за один запуск вы проходите путь от каталога до реального ответа модели.
  • Интеграция в существующие приложения: эндпоинт совместим с OpenAI API, поэтому можно переиспользовать уже написанный клиентский код.
  • Эксперименты с CPU/GPU и рантаймами: легко сравнить ONNX-GenAI и vLLM на одних и тех же моделях и запросах.
  • Обучение команды: хороший учебный пример для разработчиков и DevOps, которые только заходят в тему K8s + LLM.

Где не стоит применять

  • Продакшн‑нагрузка без доработок: пример не закрывает вопросы масштабирования, мониторинга, логирования, ротации ключей и продакшн‑TLS.
  • Высоконагруженные сценарии без тюнинга: вам придётся отдельно настраивать ресурсы Pod, авто‑скейлинг и лимиты.
  • Облачные среды без доступа к Kubernetes: пример рассчитан на тех, у кого уже есть кластер и доступ по kubectl.

Доступность из России

Проект живёт на GitHub и использует Azure Local и Azure AI Foundry. Для доступа к репозиторию и облачной части Azure в России часто нужен VPN. Если ваша инфраструктура уже развёрнута и настроена в корпоративной сети, доступ может обеспечивать внутренний периметр — это зависит от политики вашей организации.

Место на рынке

Сценарий Foundry Local на Azure Local конкурирует не с одной моделью, а с целым классом решений: это альтернатива ручной сборке стека «Kubernetes + оператор + модель + сервис».

По ключевым параметрам:

  • Интерфейс API.
    Эндпоинт полностью совместим с OpenAI API. Это упрощает миграцию с GPT‑линеек: можно перенастроить base_url и ключ, не меняя формат запросов.

  • Рантаймы.
    ONNX-GenAI и vLLM уже зарекомендовали себя в сообществе как быстрые и эффективные движки для LLM. В примере нет числовых бенчмарков, но оба решения активно используют в продакшн‑сценариях, особенно vLLM на GPU.

  • Интеграция с Azure AI Foundry.
    Каталог моделей синхронизируется из Azure AI Foundry в ConfigMap кластера. Это даёт централизованное управление модельным зоопарком, чего не хватает многим самодельным решениям.

  • Управление жизненным циклом через CRD.
    Подход с ModelDeployment хорошо стыкуется с DevOps‑практиками: можно описывать развёртывания в Git, использовать GitOps, политики и т.д.

Если вы уже используете OpenAI API напрямую, этот путь интересен, когда нужно перенести инференс на собственный кластер и сохранить привычный протокол.

Установка

Ниже — полный набор шагов из примера, без сокращений.

1. Клонируем репозиторий

git clone https://github.com/Azure-Samples/foundry-local-model-catalog.git
cd foundry-local-model-catalog

2. Устанавливаем зависимости

python3 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -r requirements.txt

3. Проверяем доступ к кластеру

# Confirm you can reach the cluster
kubectl get pods -n foundry-local-operator

# Verify the Inference Operator CRDs are installed
kubectl get crd | grep foundry

Если эти команды не проходят, сначала нужно настроить кластер и Inference Operator.

Как запустить

Базовый сценарий: развернуть Phi‑4 на CPU, сделать запрос и очистить

# Default: deploy Phi-4 on CPU, run inference, clean up
python catalog_sample.py

Скрипт:

  • выберет модель Phi-4-generic-cpu из каталога;
  • создаст ModelDeployment с рантаймом по умолчанию (ONNX-GenAI);
  • дождётся состояния Running + Ready;
  • отправит запрос с дефолтным промптом;
  • удалит развёртывание.

Примеры использования

# List all available models in the catalog (no deployment)
python catalog_sample.py --catalog-only

# Deploy Phi-4 on GPU
python catalog_sample.py --model Phi-4-generic-gpu --compute gpu

# Deploy Phi-4-mini with the vLLM runtime on GPU
python catalog_sample.py --model Phi-4-mini-instruct --compute gpu --runtime vllm

# Deploy and keep the model running after inference
python catalog_sample.py --skip-cleanup

# Two-step flow (running from your laptop):
python catalog_sample.py --deploy-only  # Deploy and wait for ready

# In another terminal:
kubectl port-forward svc/phi-4-generic-cpu 5000:5000 -n foundry-local-operator

python catalog_sample.py --infer-only --endpoint https://localhost:5000 --insecure

# Use a custom prompt
python catalog_sample.py --prompt " Explain quantum computing in two sentences. "

Выбор рантайма

Разработчики предлагают простое правило:

  • ONNX-GenAI (onnx) — используйте на узлах только с CPU, для компактных моделей или когда у вас один основной сценарий использования.
  • vLLM (vllm) — используйте на GPU‑узлах для высокопроизводительного обслуживания больших моделей и множественных пользователей.

Оба рантайма отдают один и тот же OpenAI‑совместимый REST‑эндпоинт, поэтому клиентский код не меняется.

Запуск с ноутбука вне кластера

Если вы запускаете скрипт не изнутри кластера, а со своей машины, используйте двухшаговый сценарий:

# Step 1: Deploy the model and wait for it to become ready
python catalog_sample.py --deploy-only

# Step 2: In a separate terminal, set up port-forwarding
kubectl port-forward svc/phi-4-generic-cpu 5000:5000 -n foundry-local-operator

# Step 3: Run inference using the local endpoint
python catalog_sample.py --infer-only --endpoint https://localhost:5000 --insecure

Foundry Local использует самоподписанные TLS‑сертификаты внутри кластера. Флаг --insecure отключает проверку сертификата — аналогично -k в curl. В боевой среде лучше настроить полноценные TLS‑сертификаты.

Очистка

По умолчанию пример сам удаляет развёртывание после инференса. Чтобы оставить сервис работать:

python catalog_sample.py --skip-cleanup

Позже можно удалить развёртывание вручную:

kubectl delete modeldeployment <deployment-name> -n foundry-local-operator

Параметры командной строки

Скрипт catalog_sample.py принимает набор флагов, которые управляют моделью, рантаймом и режимом работы.

Flag              Default                                        Description
--model           Phi-4-generic-cpu                             Catalog model name
--version         (auto-detect)                                 Catalog model version
--compute         cpu                                            Compute type ( cpu or gpu )
--runtime         onnx                                           Inference runtime ( onnx or vllm ). vllm requires --compute gpu .
--deployment-name (derived from model)                           Custom deployment name
--namespace       foundry-local-operator                         Kubernetes namespace
--endpoint        (in-cluster DNS)                               Inference endpoint URL (required when running outside the cluster)
--prompt          "What is the capital of France? Reply in one sentence."  Prompt to send
--timeout         600                                            Deployment readiness timeout (seconds)
--catalog-only    false                                          List catalog and exit
--deploy-only     false                                          Deploy the model and exit (skip inference)
--infer-only      false                                          Skip deployment, run inference against existing deployment
--skip-cleanup    false                                          Keep deployment running after inference
--insecure        false                                          Skip TLS certificate verification (for self-signed certs)

Использование OpenAI Python SDK

Если вы уже пишете под OpenAI API, можно не трогать HTTP‑запросы вручную и подключиться через официальный Python SDK. Для этого установите дополнительные зависимости:

pip install openai httpx

Затем подключитесь к локальному эндпоинту после развёртывания модели и настройки port‑forward:

import httpx
from openai import OpenAI

# After deploying the model and setting up port-forward:
# kubectl port-forward svc/phi-4-generic-cpu 5000:5000 -n foundry-local-operator

client = OpenAI(
    base_url="https://localhost:5000/v1",
    api_key="<YOUR_API_KEY>",  # From: kubectl get secret phi-4-generic-cpu-api-keys ...
    http_client=httpx.Client(verify=False),  # Self-signed certs
)

response = client.chat.completions.create(
    model="Phi-4-generic-cpu:1",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What is the capital of France?"},
    ],
    max_tokens=256,
)

print(response.choices[0].message.content)

Ключ (api_key) нужно взять из секрета Kubernetes:

kubectl get secret phi-4-generic-cpu-api-keys -n foundry-local-operator -o jsonpath='{.data.primary-key}' | base64 -d

Ключевые концепции

Разработчики опираются на несколько базовых сущностей:

  • Inference Operator — Kubernetes‑оператор, который управляет жизненным циклом ИИ‑моделей: реагирует на CRD, создаёт Deployment, Service, Ingress и Secrets.
  • Model Catalog — ConfigMap, который кэширует метаданные моделей из Azure AI Foundry. Скрипт читает его, чтобы узнать, какие модели доступны и как их разворачивать.
  • ModelDeployment — CRD, который описывает желаемое состояние развёрнутой модели и служит источником правды для оператора.
  • Lazy Registration — оператор автоматически создаёт объект Model при первом развёртывании записи из каталога.
  • API Key Auth — при создании развёртывания оператор генерирует пару ключей и кладёт их в Secret <name>-api-keys.

Траблшутинг

Если что-то пошло не так, разработчики предлагают такие шаги:

  • CRD не найден
    Установите Inference Operator через Helm.

  • ConfigMap с каталогом не найден
    Запустите синхронизацию каталога:

    kubectl create job --from=cronjob/foundry-local-catalog-sync manual-sync -n foundry-local-operator
    
  • Развёртывание зависло в состоянии Creating
    Скорее всего, идёт загрузка образа модели. Посмотрите события:

    kubectl describe mdep <name> -n foundry-local-operator
    
  • Развёртывание в состоянии Error
    Проверьте сообщение об ошибке через ту же команду kubectl describe mdep <name> -n foundry-local-operator.

  • Connection refused при инференсе
    Убедитесь, что настроили port‑forward на нужный сервис:

    kubectl port-forward svc/<name> 5000:5000 -n foundry-local-operator
    
  • 401 Unauthorized
    Проверьте, что используете корректный API‑ключ из секрета:

    kubectl get secret <name>-api-keys -n foundry-local-operator -o jsonpath='{.data.primary-key}' | base64 -d
    

Лицензия и вклад

Проект открыт на GitHub под лицензией MIT. Можно свободно использовать пример в своих продуктах и адаптировать под инфраструктуру.

Если хотите доработать скрипт или оператор, Microsoft просит оформить Contributor License Agreement (CLA). Подробности лежат в CONTRIBUTING.md в репозитории, сама лицензия — в LICENSE.md.


Читайте также