Знакът на КАГАМИ КАГАМИ
kagami.bg/academy · lesson · machine-readable viewUPDATED 2026-10-03
IDENTITY
module
GX10-04-102 · Calling a local NIM through the OpenAI client
series
GX10 (local AI server class: NVIDIA GB10, e.g. ASUS Ascent GX10 / DGX Spark)
level
Intermediate
duration
1–2 h
prerequisites
Docker with the NVIDIA runtime, a free NGC account and API key, Python 3.9+ with pip, a NIM container image for an LLM that is published for the machine's architecture (check the model's page)
trust_label
UPDATED 2026-10-03 · NOT TESTED (no GB10 machine available; the NIM LLM documentation pages did not load during the check, so image names, tags and the health endpoint are not verified) · not VERIFIED
versions
No versions are pinned in this lesson: the image tag is taken from the model page on NGC; the openai Python package is the 1.x client
language
human view: en · bulgarian edition: /academy/gx10/ (same file name)
previous / next
GX10 series index / GX10 series index
PURPOSE

A NIM microservice packages a model with an inference engine behind an OpenAI-style HTTP API. Point the standard openai client at the local endpoint, discover the served model name, send a chat request, stream the answer, add retries with backoff, and optionally send an image to a vision-capable model. No data leaves the machine when the container runs locally.

KEY CONCEPTS
COMMANDS / PATHS
CHECKLIST
NEXT MODULE

GX10 series index: kagami.bg/academy/gx10/ · related: 04-10 vLLM inference (04-10_vLLM_Inference.html), 04-07 Open WebUI with Ollama (04-07_Open_WebUI_Ollama.html) · offer: Quick experiment (kagami.bg/stalbata/)

SOURCES
TAGS
gx10nvidia-gb10nimopenai-compatiblestreamingpythonllm-serving
ОБНОВЕНО · 03.10.2026

NIM API: OpenAI клиент към локален модел

Много програми и библиотеки вече говорят на „OpenAI език“. NIM е контейнер, който предлага модел през същия API — и затова можеш да насочиш познат клиент към собствената си машина, без да пренаписваш кода. Моделът остава при теб.

⏱ 1–2 ч Средно GX10 NIM · OpenAI-съвместим API Python · curl
NIM контейнер (моделът)🔒 локално Библиотеката openai (клиент)🔒 локално Облачният API на build.nvidia.com (по избор)🌐 глобален
🔄
ОБНОВЕНО · 03.10.2026 — какво
Урокът е написан наново. Махнахме: примерния адрес на машина с измислено име, фиксирания модел llama-3.1-70b (името на модела вече се чете от сървъра, не се гадае), примера с конкретен модел за зрение, твърдението за „медицински изображения“ и хардкоднатия ключ в кода. Добавихме: разделите „Преди да започнеш“ и „Проверка“ с тест, проверка на готовността, повторни опити, затворен порт и съвети за сигурност. Не сверихме: страниците на документацията за NIM за езикови модели не се заредиха при проверката ни, затова имената на образите, таговете и точния адрес за проверка на готовността са отбелязани с ⚠️ и са за сверяване.
⚠️
Какво не сме пускали сами
Нямахме машина от класа GB10. Нито една команда по-долу не е пускана от нас, затова няма етикет „ТЕСТВАНО“ — и няма „ПРОВЕРЕНО“. Особено за сверяване: кои модели имат NIM образ за ARM64/GB10 (виж страницата на модела в каталога на NVIDIA), точният таг и дали локалният NIM проверява api_key.

01Какво ще научиш

02Преди да започнеш

03Стъпки

  1. Какво прави NIM

    NIM („NVIDIA Inference Microservice“) е Docker образ с модел, подготвена за видеокартата среда за изпълнение и уеб сървър. Отвън изглежда като услугата на OpenAI: същите адреси (/v1/models, /v1/chat/completions) и същият вид заявки. Защо е важно: всяка програма, която може да се насочи към друг „base URL“, работи с твоя модел — и данните не излизат от машината.

  2. Стартирай контейнера

    Портът е публикуван само към 127.0.0.1 — недостъпен за останалите в мрежата. Първото стартиране тегли и подготвя модела и може да отнеме дълго.

    bash · на машината · не е пускано ⚠️
    export NGC_API_KEY=<вашият-ключ-от-NGC>
    export LOCAL_NIM_CACHE=$HOME/.cache/nim
    mkdir -p "$LOCAL_NIM_CACHE"
    
    docker run -it --rm --gpus all --shm-size=16GB \
      -e NGC_API_KEY \
      -v "$LOCAL_NIM_CACHE:/opt/nim/.cache" \
      -p 127.0.0.1:8000:8000 \
      nvcr.io/nim/<издател>/<модел>:<таг>
    ⚠️
    Сверете с документацията
    Флаговете и пътят на кеша са по образеца от документацията на NIM, както го познаваме, но страницата не се зареди при проверката и не сме го сверявали на 03.10.2026. Името на образа (<издател>/<модел>:<таг>) вземи от страницата на избрания модел в каталога на NVIDIA.
  3. Провери, че работи

    Първо питаме сървъра кой модел обслужва. Този отговор ще ползваме за името на модела.

    bash · не е пускано ⚠️
    curl -s http://localhost:8000/v1/models
    curl -s http://localhost:8000/v1/health/ready

    Очакваш списък с един модел. Втората команда (адрес за готовност) е по спомен от документацията — ⚠️ провери я.

  4. Първо извикване с openai

    Сменяме само base_url. Името на модела четем от сървъра — така не рискуваме да напишем име, което не съществува.

    python · не е пускано ⚠️
    import os
    from openai import OpenAI
    
    client = OpenAI(
        base_url="http://<адрес-на-машината>:8000/v1",   # от същата машина: http://localhost:8000/v1
        api_key=os.environ.get("NIM_API_KEY", "not-used"),  # локалният NIM може да не проверява ключа
    )
    
    # Името на модела не се гадае: питаме сървъра какво обслужва.
    MODEL = client.models.list().data[0].id
    print("Модел:", MODEL)
    
    resp = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "user", "content": "Обясни в три изречения какво е NIM."}],
        max_tokens=200,
        temperature=0.7,
    )
    print(resp.choices[0].message.content)
    💡
    Защо има ключ, щом е локално
    Клиентската библиотека изисква стойност за api_key. ⚠️ Дали локалният NIM я проверява, не сме потвърдили. Ако включиш защита на входа (прокси с удостоверяване), ключът става истински — и тогава е тайна.
  5. Отговор на части (streaming)

    С stream=True сървърът праща отговора на парчета, както се генерира. Потребителят вижда първите думи веднага, вместо да чака края — общото време е същото, но усещането е по-бързо.

    python · не е пускано ⚠️
    stream = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "user", "content": "Напиши хайку за видеокарти."}],
        stream=True,
    )
    for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
    print()

    Проверката if chunk.choices е нужна, защото някои парчета са празни.

  6. Повторни опити

    Сървърът може да е зает, да се рестартира или да не е достигнат. Вместо програмата да спре, изчакваме все по-дълго (1, 2, 4, 8 секунди) и пробваме пак. Така се държат повечето услуги в продукция.

    python · не е пускано ⚠️
    import time
    import openai
    
    def ask(messages, tries=4):
        for n in range(tries):
            try:
                return client.chat.completions.create(model=MODEL, messages=messages, max_tokens=200)
            except (openai.RateLimitError, openai.APIConnectionError, openai.APITimeoutError):
                time.sleep(2 ** n)   # 1, 2, 4, 8 секунди
        raise RuntimeError("Сървърът не отговори след няколко опита")
    
    print(ask([{"role": "user", "content": "Здравей!"}]).choices[0].message.content)
  7. Изображения (по избор)

    Само ако имаш NIM за модел, който приема изображения, снимката се праща като част от съобщението, кодирана в base64. Форматът е на OpenAI API; ⚠️ не сме го пускали с конкретен модел.

    python · не е пускано ⚠️
    import base64
    
    with open("chart.png", "rb") as f:
        img = base64.b64encode(f.read()).decode()
    
    resp = client.chat.completions.create(
        model=MODEL,   # трябва да е модел, който приема изображения
        messages=[{"role": "user", "content": [
            {"type": "text", "text": "Опиши тази диаграма."},
            {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img}"}},
        ]}],
    )
    print(resp.choices[0].message.content)
    ✅
    Не пращай чужди лични данни към неподходящ модел
    Снимки на документи и хора съдържат лични данни. Докато контейнерът е локален, те не напускат машината — но ако насочиш същия код към облачен адрес, напускат. Провери накъде сочи base_url.
  8. Достъп отдалеч и сигурност

    • От друг компютър стигаш до порта през SSH тунел: ssh -L 8000:localhost:8000 <потребител>@<адрес-на-машината>; тогава в клиента ползваш http://localhost:8000/v1.
    • Не публикувай порта на 0.0.0.0 без прокси с удостоверяване и HTTPS.
    • NGC_API_KEY стои в променлива на средата или във файл с права 600, който не е в Git.
    • Ако ключът се е появил някъде, където не трябва — отмени го в NGC и направи нов.

04Проверка

Тест

1. Какво сменяш в клиента на openai, за да говори с локален NIM?

2. Какво прави stream=True?

3. Къде е правилно да стои API ключът за NGC?

4. Коя заявка показва кой модел обслужва NIM?

05Какво следва

Всички уроци от серията са в индекса GX10.

06Източници

  1. NVIDIA NIM за езикови модели: документация 🔒 локално — ⚠️ страницата не се зареди при проверката на 03.10.2026; сверете флаговете и таговете там.
  2. NIM API: справочник 🌐 глобален — облачните крайни точки на NVIDIA.
  3. OpenAI API: chat completions — формат на заявките, streaming, съобщения с изображения.
  4. openai-python — клиентската библиотека.
  5. NVIDIA NGC: преглед и ключове — как се създава API ключ.