Чат-бот для сайта на нейросети: архитектура, код со стримингом и цена
Собираем чат-бот для сайта: ключ только на сервере, бэкенд на FastAPI со стримингом, дешёвая модель, расчёт стоимости и лимиты против злоупотреблений.
6 мин · · разработка · API-ключи
Чат-бот для сайта на нейросети собирается за вечер, но одна архитектурная ошибка — ключ API в коде страницы — может обнулить баланс за ночь. Ниже — правильная схема, рабочий бэкенд на FastAPI со стримингом и простой виджет, выбор недорогой модели, расчёт стоимости 10 000 диалогов и настройки, которые ограничат расход, если ботом начнут злоупотреблять.
Архитектура: фронт → бэкенд → API
Браузер (виджет) → ваш бэкенд /api/chat → https://api.zukko.pro/v1
без ключа ключ fetch_..., лимиты, модель
системный промптКлюч fetch_... — только на сервере. Всё, что попало в JavaScript страницы, может прочитать любой посетитель через инструменты разработчика. С вашим ключом он сможет отправлять запросы к любым моделям за ваш счёт. Поэтому браузер общается только с вашим бэкендом, а тот — с API.
Что делает бэкенд:
- хранит ключ в переменной окружения;
- добавляет системный промпт — пользователь его не видит и не может заменить;
- обрезает историю диалога и длину сообщений;
- ограничивает частоту запросов с одного IP;
- скрывает от посетителя детали ошибок API.
Выбор модели
Для бота на сайте обычно хватает недорогой модели: вопросы короткие, ответы — по базе знаний из системного промпта. Цены на 7 октября 2026, $ за 1M токенов:
| Модель | id | Вход / выход | Индекс силы | Контекст |
|---|---|---|---|---|
| DeepSeek V4.1 Flash | deepseek-v4.1-flash | 0.013 / 0.038 | 39 | 1M |
| Qwen 3.8 Flash | qwen3.8-flash | 0.038 / 0.075 | 40 | 1M |
| GLM 5.3 Flash | glm-5.3-flash | 0.04 / 0.04 | 42 | 128K |
| GPT-6 Luna | gpt-6-luna | 0.04 / 0.21 | 38 | 1M |
| Gemini 3.8 Flash | gemini-3.8-flash | 0.063 / 0.288 | 41 | 1M |
| GPT-6.1 Sol | gpt-6.1-sol | 0.27 / 1.32 | 52 | 1M |
Индекс силы — Intelligence Index от Artificial Analysis из каталога Zukko. Актуальный список и цены — GET https://api.zukko.pro/v1/models или страница «Модели» в кабинете.
Как выбрать: соберите 30–50 реальных вопросов посетителей, прогоните их через 2–3 дешёвые модели с вашим системным промптом и оцените ответы. Если ни одна не справляется, попробуйте GPT-6.1 Sol. В коде модель — одна строка, её легко поменять. Подробнее о выборе — в статье как выбрать модель для чат-бота.
Чат-бот для сайта на нейросети: код бэкенда
Python 3.10+, FastAPI и официальный OpenAI SDK. Установка: pip install fastapi uvicorn openai. Файл main.py:
import os
import time
from collections import defaultdict, deque
from typing import Literal
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import FileResponse, StreamingResponse
from openai import APIStatusError, AsyncOpenAI
from pydantic import BaseModel, Field
client = AsyncOpenAI(
base_url="https://api.zukko.pro/v1",
api_key=os.environ["ZUKKO_API_KEY"], # ключ fetch_... только на сервере
)Ключевые моменты:
- Роль
systemклиент прислать не может — модельMessageдопускает толькоuserиassistant. - Проверка
if chunk.choicesобязательна: последний чанк стрима приходит сusageи пустымchoices. max_tokens=400ограничивает длину и стоимость одного ответа.- Счётчик запросов хранится в памяти — для одного процесса этого достаточно. При нескольких процессах или серверах вынесите его в Redis. Если перед приложением стоит прокси, берите IP клиента из заголовка, который выставляет ваш прокси, а не
request.client.host.
Запуск: ZUKKO_API_KEY=fetch_ваш_ключ uvicorn main:app. Справка по стримингу — в статье о stream=true.
Виджет на странице
Минимальный index.html: история хранится в браузере и отправляется целиком, бэкенд берёт последние 10 сообщений.
<pre id="log"></pre>
<form id="form">
<input id="text" maxlength="1000" autocomplete="off" placeholder="Ваш вопрос">
<button>Отправить</button>
</form>
<script>
const history = [];
const log = document.getElementById("log");
const form = document.getElementById("form");
const input = document.getElementById("text");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const text = input.value.trim();Если между бэкендом и браузером стоит обратный прокси, отключите для маршрута /api/chat буферизацию ответа — иначе текст придёт целиком в конце, а не по частям.
Сколько стоят 10 000 диалогов
Допущения: системный промпт с базой знаний — 1 500 токенов; в диалоге 4 вопроса по 50 токенов и 4 ответа по 150. Модель получает всю историю заново, поэтому вход n-го запроса = 1 500 + 200 × (n − 1) + 50.
- Вход за диалог: 1 550 + 1 750 + 1 950 + 2 150 = 7 400 токенов.
- Выход за диалог: 4 × 150 = 600 токенов.
- 10 000 диалогов: 74M входа и 6M выхода.
Формула: 74 × цена входа + 6 × цена выхода (цены за 1M токенов).
| Модель | Расчёт | 10 000 диалогов |
|---|---|---|
deepseek-v4.1-flash | 74 × 0.013 + 6 × 0.038 | $1.19 |
glm-5.3-flash | 74 × 0.04 + 6 × 0.04 | $3.20 |
qwen3.8-flash | 74 × 0.038 + 6 × 0.075 | $3.26 |
gpt-6-luna | 74 × 0.04 + 6 × 0.21 | $4.22 |
gemini-3.8-flash | 74 × 0.063 + 6 × 0.288 | $6.39 |
gpt-6.1-sol | 74 × 0.27 + 6 × 1.32 | $27.90 |
Цены на 7 октября 2026, расчёт без учёта кэша. Системный промпт повторяется в каждом запросе, поэтому у моделей, где поставщик сообщает о чтении кэша, часть входа может обойтись дешевле — например, у Gemini 3.8 Flash чтение кэша стоит 0.013 против 0.063 за вход. Запись кэша у этих моделей не списывается. Итог — пример расчёта: подставьте свои размеры промпта и диалогов.
Защита от злоупотреблений
Открытый чат на сайте — это бесплатный доступ к модели для всех, включая ботов. Ограничения ставьте на двух уровнях.
На уровне ключа Zukko (в кабинете):
- отдельный ключ только для бота;
- дневной и месячный лимит в долларах — при исчерпании API вернёт 429
key_daily_limit_reachedилиkey_monthly_limit_reached, остальные ключи аккаунта продолжат работать; - список разрешённых моделей — только модель бота, запрос к другой получит 403
model_not_allowed_for_key.
Лимиты мягкие: последний пропущенный запрос может немного превысить потолок. Подробнее — в документации по лимитам ключа.
На уровне бэкенда:
- лимит сообщений на IP или на сессию;
- ограничение длины сообщения и числа сообщений истории;
max_tokensдля ответа;- проверка от ботов на форме, если начался поток автоматических запросов;
- журнал расходов: в обычных (не потоковых) ответах шлюз присылает заголовок
X-Zukko-Cost-Micros, у потоковых стоимость смотрите вGET /v1/usageили в кабинете.
Если ключ всё же утёк, сразу отзовите его в кабинете и только потом выпускайте новый. Больше о хранении ключей — в статье о безопасности API-ключей.
Чтобы собрать бота по этой схеме, создайте в кабинете отдельный ключ с небольшим дневным лимитом и подставьте его в ZUKKO_API_KEY на сервере.
Частые вопросы
Можно ли вызывать API прямо из JavaScript на странице?
Нет. Ключ из кода страницы может прочитать любой посетитель. Запросы к API должны идти только с вашего сервера.
Сколько стоит чат-бот для сайта в месяц?
Зависит от числа диалогов и модели. По нашему расчёту 10 000 диалогов по 4 вопроса стоят от $1.19 на DeepSeek V4.1 Flash до $27.90 на GPT-6.1 Sol по ценам на 7 октября 2026.
Что будет, если закончится лимит ключа?
API вернёт 429, бэкенд из примера покажет посетителю «Чат временно недоступен». Дневной лимит обнуляется в 00:00 UTC, месячный — в начале месяца по UTC.
Можно ли сделать то же на Node.js?
Да. Схема та же: бэкенд на Express или другом фреймворке, официальный OpenAI SDK для Node с baseURL: "https://api.zukko.pro/v1", ключ в переменной окружения и стриминг ответа клиенту.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Свой прокси к нейросети на Node.js: не показывать API-ключ во фронтендеНебольшой сервер на Express между вашим фронтендом и API нейросети: ключ остаётся на сервере, а модели, длина запроса и частота ограничены.
- DeepSeek API на Python: запросы, стриминг, JSON и обработка ошибокГотовый код для DeepSeek V4.1 Flash и V4 Pro на OpenAI SDK: запрос, стриминг, разбор JSON и аккуратная обработка ошибок.
- Gemini API на Python: запросы через OpenAI SDK и OpenAI-форматРабочий пример Gemini API на Python без отдельной библиотеки: меняем base_url в OpenAI SDK, добавляем стриминг и JSON и сравниваем с google-genai.
- Anthropic SDK для Python: base_url, ключ и первый запрос через шлюзОфициальный пакет anthropic для Python нужно только направить на другой адрес. Разбираем base_url, ключ, стриминг, подсчёт токенов, кэш и ошибки.