NIM API: OpenAI клиент към локален модел
Много програми и библиотеки вече говорят на „OpenAI език“. NIM е контейнер, който предлага модел през същия API — и затова можеш да насочиш познат клиент към собствената си машина, без да пренаписваш кода. Моделът остава при теб.
llama-3.1-70b (името на модела вече се чете от сървъра, не се гадае), примера с конкретен модел за зрение, твърдението за „медицински изображения“ и хардкоднатия ключ в кода. Добавихме: разделите „Преди да започнеш“ и „Проверка“ с тест, проверка на готовността, повторни опити, затворен порт и съвети за сигурност. Не сверихме: страниците на документацията за NIM за езикови модели не се заредиха при проверката ни, затова имената на образите, таговете и точния адрес за проверка на готовността са отбелязани с ⚠️ и са за сверяване.
api_key.01Какво ще научиш
- Какво е NIM и защо „OpenAI-съвместим“ ти спестява работа.
- Как да насочиш готовия клиент към локален адрес и да разбереш кой модел отговаря.
- Как да получаваш отговора на части (streaming).
- Как да правиш повторни опити, когато сървърът е зает или недостъпен.
- Как да изпратиш изображение — само ако моделът го поддържа.
- Как да държиш ключовете и порта затворени.
02Преди да започнеш
- Машина с NVIDIA видеокарта и Docker с NVIDIA runtime. На сървър от класа GB10 Docker и NVIDIA Container Toolkit са предварително настроени (виж урока „n8n на GX10“).
- Безплатен акаунт в NVIDIA NGC и API ключ — контейнерът го ползва, за да изтегли модела. Ключът е тайна: не го слагай в код, в чат и в публични файлове.
- Python 3.9 или по-нов и
pip install openai. - Избран NIM образ за езиков модел, публикуван за архитектурата на твоята машина. ⚠️ Провери го в каталога на NVIDIA преди да теглиш десетки гигабайта.
- Свободно място: моделите са от няколко до десетки гигабайта.
03Стъпки
-
Какво прави NIM
NIM („NVIDIA Inference Microservice“) е Docker образ с модел, подготвена за видеокартата среда за изпълнение и уеб сървър. Отвън изглежда като услугата на OpenAI: същите адреси (
/v1/models,/v1/chat/completions) и същият вид заявки. Защо е важно: всяка програма, която може да се насочи към друг „base URL“, работи с твоя модел — и данните не излизат от машината. -
Стартирай контейнера
Портът е публикуван само към
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. -
Провери, че работи
Първо питаме сървъра кой модел обслужва. Този отговор ще ползваме за името на модела.
bash · не е пускано ⚠️curl -s http://localhost:8000/v1/models curl -s http://localhost:8000/v1/health/readyОчакваш списък с един модел. Втората команда (адрес за готовност) е по спомен от документацията — ⚠️ провери я.
-
Първо извикване с 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 я проверява, не сме потвърдили. Ако включиш защита на входа (прокси с удостоверяване), ключът става истински — и тогава е тайна. -
Отговор на части (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е нужна, защото някои парчета са празни. -
Повторни опити
Сървърът може да е зает, да се рестартира или да не е достигнат. Вместо програмата да спре, изчакваме все по-дълго (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) -
Изображения (по избор)
Само ако имаш 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. -
Достъп отдалеч и сигурност
- От друг компютър стигаш до порта през SSH тунел:
ssh -L 8000:localhost:8000 <потребител>@<адрес-на-машината>; тогава в клиента ползвашhttp://localhost:8000/v1. - Не публикувай порта на
0.0.0.0без прокси с удостоверяване и HTTPS. NGC_API_KEYстои в променлива на средата или във файл с права 600, който не е в Git.- Ако ключът се е появил някъде, където не трябва — отмени го в NGC и направи нов.
- От друг компютър стигаш до порта през SSH тунел:
04Проверка
/v1/modelsвръща името на модела.- Първото извикване връща текст.
- Streaming печата отговора на части.
- Спри контейнера и пусни повторните опити: програмата изчаква и не се срива с грозна грешка.
- Портът е публикуван само към
127.0.0.1; ключът не е в кода.
Тест
1. Какво сменяш в клиента на openai, за да говори с локален NIM?
2. Какво прави stream=True?
3. Къде е правилно да стои API ключът за NGC?
4. Коя заявка показва кой модел обслужва NIM?
05Какво следва
Всички уроци от серията са в индекса GX10.
06Източници
- NVIDIA NIM за езикови модели: документация 🔒 локално — ⚠️ страницата не се зареди при проверката на 03.10.2026; сверете флаговете и таговете там.
- NIM API: справочник 🌐 глобален — облачните крайни точки на NVIDIA.
- OpenAI API: chat completions — формат на заявките, streaming, съобщения с изображения.
- openai-python — клиентската библиотека.
- NVIDIA NGC: преглед и ключове — как се създава API ключ.