Chainlit — Python-фреймворк для быстрого чат-интерфейса: несколько функций-обработчиков, и у вас готовый веб-чат с историей и стримингом. Модель вызывается через официальный SDK openai, поэтому для Heli достаточно указать base_url https://getheli.ru/v1 и ключ sk-heli- из вкладки «Ключи».
app.py
Установка и запуск: pip install chainlit openai, затем chainlit run app.py -w. Флаг -w перезапускает приложение при изменении файла.
import os
import chainlit as cl
from openai import AsyncOpenAI
client = AsyncOpenAI(base_url="https://getheli.ru/v1", api_key=os.environ["HELI_API_KEY"])
MODEL = "openai/gpt-5.4-mini"
@cl.on_chat_start
async def start():
cl.user_session.set("history", [
{"role": "system", "content": "Ты полезный ассистент. Отвечай по-русски."}
])
@cl.on_message
async def on_message(message: cl.Message):
history = cl.user_session.get("history")
history.append({"role": "user", "content": message.content})
msg = cl.Message(content="")
stream = await client.chat.completions.create(
model=MODEL, messages=history, stream=True, max_tokens=1500
)
async for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
await msg.stream_token(chunk.choices[0].delta.content)
history.append({"role": "assistant", "content": msg.content})
await msg.update()На что обратить внимание
- Используйте AsyncOpenAI: обработчики Chainlit асинхронные, а синхронный клиент блокирует приложение для всех пользователей на время ответа.
- Проверяйте chunk.choices: последний чанк потока Heli содержит только usage и пустой список choices.
- История хранится в cl.user_session отдельно для каждой сессии. Обрезайте её до последних реплик — весь контекст оплачивается в каждом запросе.
- Ключ держите в переменной окружения или файле .env, который не попадает в git.
Выбор модели в интерфейсе
Chainlit позволяет дать пользователю переключатель модели через настройки чата (cl.ChatSettings с элементом Select). Значения — обычные слаги каталога Heli, например openai/gpt-5.4-mini или anthropic/claude-sonnet-5. Ограничьте список несколькими моделями: так проще прогнозировать расход.
Частые ошибки
- 401 — неверный ключ или лишний пробел в переменной окружения.
- Ошибка о неизвестной модели — слаг указан без префикса vendor/.
- Ответ приходит целиком, а не по токенам, — включён stream=False или ответ буферизует прокси перед приложением.
Деплой и доступ
По умолчанию Chainlit слушает порт 8000 и общается с браузером через WebSocket. Если перед приложением стоит nginx, проксируйте заголовки Upgrade и Connection, иначе чат не подключится. Не публикуйте приложение без авторизации: любой, кто знает адрес, будет тратить ваш баланс.
В Chainlit есть встроенная авторизация, например по паролю через декоратор @cl.password_auth_callback. Для неё нужен секрет CHAINLIT_AUTH_SECRET — его генерирует команда chainlit create-secret. После входа в сессии доступен пользователь, и расход можно учитывать по нему.
Попробуйте Heli
Ключ sk-heli- появляется после подтверждения почты. Через Google и Яндекс — сразу в кабинете.