Два способа получить бесплатную LLM в скрипт Python
Когда люди ищут бесплатные llms для python, они обычно имеют в виду одно из двух. Первое — это модель с открытыми весами, которую вы скачиваете и запускаете самостоятельно, используя что-то вроде Ollama, llama.cpp или библиотеку transformers Hugging Face. Второе — это хостинговый эндпоинт, который стоит так мало или имеет достаточно пробного кредита, что кажется бесплатным для прототипа. Оба варианта законны и подходят для разных задач.
Запуск локально означает отсутствие счета за токен и отсутствие передачи данных с вашего компьютера. Это также означает, что вам нужно достаточно оперативной памяти или памяти GPU для выбранной модели, вы ждете загрузки, а маленькие модели, помещающиеся на ноутбуке, работают хуже больших. Хостинговое API устраняет вопрос с оборудованием, но вы платите за токен, когда пробный период закончится. Эта страница честно охватывает оба варианта, а затем показывает код Python для хостингового варианта на этом сайте, который совместим с OpenAI и работает со стандартным пакетом openai.
Локальные модели и хостинговое API рядом
| Вопрос | Запустить самостоятельно | Хостинговое предоплаченное API |
|---|---|---|
| Стоимость за токен | Нет, но вы платите за оборудование и электроэнергию | $0,15 за 1 млн входных, $0,50 за 1 млн выходных |
| Время настройки | Установите среду выполнения, скачайте веса, настройте параметры | Установите один пакет, вставьте ключ |
| Длина контекста | Ограничено вашей памятью | 100 000 токенов, промпт плюс завершение |
| Параллельные запросы | Все, что может обработать ваша машина | 8 запросов одновременно для полного ключа, 2 для пробного ключа |
| Отказы | Зависит от выбранных весов | Настроена на ответы без отказов по контенту для законного использования взрослыми |
| Офлайн-использование | Да | Нет |
Если у вас есть мощный GPU и ваша работа приватна или автономна, локальный вариант — отличный выбор, и вы можете прекратить чтение здесь. Если вы хотите большую модель без владения машиной или хотите, чтобы ваш скрипт вел себя одинаково на ноутбуке, сервере и в CI-раннере, хостинговый вариант проще. Многие проекты используют оба: маленькую локальную модель во время разработки, хостинговую в продакшене, переключаясь путем изменения одного базового URL.
Настройте хостинговый эндпоинт за пять минут
Сначала вам нужен ключ. Зарегистрируйтесь через Google или с помощью электронной почты и пароля, затем получите пробный кредит на $0,50 одним кликом на странице API key. Пробный период действителен в течение 7 дней, один на человека, и не требует оплаты. Затем установите SDK и держите ключ вне исходного кода.
pip install openai
export NOTRACK_API_KEY="sk-your-key-here"
Клиенту нужно изменить два параметра по сравнению со стандартной настройкой OpenAI: базовый URL и ключ. Идентификатор модели — uncensored, и предлагается только одна модель.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nsfwvideogenerator.cc/v1",
api_key=os.environ["NOTRACK_API_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a concise writing assistant."},
{"role": "user", "content": "Give me three title ideas for a noir short story."},
],
temperature=0.8,
)
print(resp.choices[0].message.content)
print(resp.usage)
Аутентификация — это стандартный заголовок Authorization: Bearer, который SDK добавляет за вас. Существуют два метода: POST /v1/chat/completions и GET /v1/models. Вы можете подтвердить соединение с помощью client.models.list(), который возвращает доступный идентификатор модели. Полный список параметров находится на странице документации.
Потоковые ответы
Для всего, что наблюдает человек, используйте потоковую передачу. Установите stream=True и перебирайте фрагменты по мере поступления событий, отправляемых сервером. Использование сообщается в конце потока, поэтому вы все еще можете регистрировать количество токенов.
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Write a four-line poem about rain on a tin roof."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
usage = getattr(chunk, "usage", None)
if usage:
print("\n", usage)
Один нюанс застает людей врасплох: потоковый запрос удерживает слот одновременности до завершения потока. На пробном ключе с 2 слотами два открытых потока означают, что третий вызов получит ошибку 429 с кодом concurrency. Всегда потребляйте или закрывайте поток.
Вызов инструментов и JSON-режим
Эндпоинт поддерживает tools, tool_choice, потоковую передачу tool_calls и результаты, отправляемые обратно как role: "tool". Вот полный цикл с одной функцией.
import json
tools = [{
"type": "function",
"function": {
"name": "word_count",
"description": "Count the words in a piece of text.",
"parameters": {
"type": "object",
"properties": {"text": {"type": "string"}},
"required": ["text"],
},
},
}]
messages = [{"role": "user", "content": "How many words are in: the quick brown fox jumps"}]
first = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = first.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = len(args["text"].split())
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": str(result),
})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)
Всегда парсите аргументы arguments с защитой от ошибок: модель возвращает их в виде строки JSON, и любая модель может время от времени выдавать некорректную строку. Для структурированного вывода без инструментов используйте JSON-режим.
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "Reply with a JSON object with keys title and tags (list of strings)."},
{"role": "user", "content": "Describe a lighthouse keeper's diary."},
],
response_format={"type": "json_object"},
temperature=0.2,
)
data = json.loads(resp.choices[0].message.content)
print(data["title"], data["tags"])
Скажите слово JSON и назовите ключи в вашем промпте, и держите температуру низкой. Оберните json.loads в блок try для производственного кода.
Лимиты запросов, ошибки и повторные попытки
Полный ключ позволяет выполнять 8 параллельных запросов и 300 запросов в минуту. Пробный ключ позволяет выполнять 2 и 60 соответственно. Если превысить лимит, вы получите HTTP 429 с кодом rate_limited (слишком много запросов в минуту) или concurrency (слишком много одновременно). При временной перегрузке API также возвращает 429 с заголовком Retry-After: 5. SDK самостоятельно повторяет запросы при некоторых ошибках; для скрипта, разбивающего задачи на параллельные запросы, небольшая явная обертка будет понятнее.
import time
from concurrent.futures import ThreadPoolExecutor
from openai import RateLimitError
def ask(prompt, tries=4):
for attempt in range(tries):
try:
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
max_tokens=300,
)
return r.choices[0].message.content
except RateLimitError:
time.sleep(5 * (attempt + 1))
raise RuntimeError("still rate limited")
prompts = [f"Summarize idea number {i} in one sentence." for i in range(20)]
with ThreadPoolExecutor(max_workers=2) as pool: # 8 on a full key
results = list(pool.map(ask, prompts))
Сопоставление max_workers с лимитом параллелизма вашего ключа предотвращает большинство ошибок 429 до их возникновения. Каждый ответ также содержит X-Request-Id, X-Balance-USD и два заголовка лимита запросов, которые вы можете прочитать через client.chat.completions.with_raw_response.create(...), когда они вам нужны для отладки или поддержки.
Как выбрать между локальным и хостинговым
Пропустите идеологию и ответьте на четыре вопроса о вашем проекте.
- Должны ли данные оставаться на вашем компьютере? Если контракт или привычка говорят «да», запускайте локально. Промпты, отправляемые на хостинг, не используются для обучения здесь, но они передаются по сети.
- Сколько у вас памяти? Размер модели определяет качество. Ноутбук без выделенного GPU ограничивает вас маленькими моделями, и ответы это покажут. Хостинговая модель дает вам большую с контекстным окном на 100 000 токенов, что трудно достичь дома.
- Сколько запросов вы отправите? Несколько сотен в неделю — это тривиально с любой стороны. Сотни тысяч в месяц превращают счет за хостинг в реальную цифру, и локальная машина начинает выглядеть привлекательно, если она простаивает. Посчитайте: 100,000 запросов по 1,000 входных и 500 выходных токенов стоят 100,000 x $0.0004 = $40.
- Нужны ли вам определенные способы обработки отказов? Многие модели с открытыми весами поставляются со встроенным поведением отказа, а другие настроены на его отключение. Хостинговая модель здесь настроена на ответы без отказов по контенту для законного использования взрослыми, поэтому вам не нужно искать правильные веса.
Если ваши ответы указывают в обоих направлениях, начните с хостинга на первую неделю. Пробный период ничего не стоит, и вы узнаете, что нужно вашим промптам, прежде чем покупать оборудование или скачивать еще один многогигабайтный файл.
Распространенные ошибки в скриптах Python
Большинство проблем, с которыми сталкиваются люди, невелики и исправимы.
- Неверный базовый URL. Он должен заканчиваться на
/v1. Отсутствие суффикса дает ошибку 404, а не полезное сообщение. Распечатайтеclient.base_url, если сомневаетесь. - Ключ в коде. Прочитайте его из переменной окружения, как выше, и добавьте файл
.envв.gitignore. - Неверное имя модели. Единственный идентификатор модели —
uncensored. Имена от других поставщиков не будут работать, поэтому измените их при переносе кода. - Неограниченные циклы. Цикл вызова инструментов, который никогда не заканчивается, — это дорогостоящая ошибка. Ограничьте его, например, пятью раундами.
- Игнорирование бюджета контекста. Промпт и завершение делят 100,000 токенов. Если вы будете добавлять каждый ход бесконечно, вы в конечном итоге достигнете лимита. Обрежьте или суммируйте старые сообщения.
- Предположение, что JSON всегда действителен. Даже в JSON-режиме проверяйте ключи, которые вам нужны, перед их использованием.
Если на стороне сервера что-то выглядит неправильно, укажите значение X-Request-Id из ответа при обращении в support. Это позволит операторам найти ваш конкретный запрос.
Сколько стоит хостинговый вариант для работы с Python
Типичный вызов скрипта с 1 000 входными и 500 выходными токенами стоит $0,00015 плюс $0,00025, то есть $0,0004. Пробный баланс в $0,50 покрывает около 1 250 таких вызовов. Пополнение на $20 (минимальная сумма) покрывает 50 000 вызовов. Баланс не сгорает, неудачные или отклонённые запросы не оплачиваются, а промпты не используются для обучения. Пополнения идут до $500 с бонусом от $50, оплата криптовалютой: USDT в сети TRC20 или USDC в сети Base. Подробности см. на странице с ценами.
Это только текст: нет изображений, аудио, видео, эмбеддингов или дообучения. И единственное строгое правило — запрет на сексуальный контент с участием несовершеннолетних. Для проекта на Python, которому нужна генерация текста с меньшим количеством отказов, это весь охват.
