API та SDKПосібник
Згенеруйте HTML-інструмент з одного запиту через API (Python)
Скрипт Python, який перетворює один запит на робочий tool.html, виявляє обрізану відповідь за finish_reason і виводить токени та вартість.

На цій сторінці
Ви можете отримати робочий односторінковий інструмент за один виклик API: надішліть добре структурований запит, переконайтеся, що max_tokens достатньо великий для цілої сторінки, перевірте, що finish_reason дорівнює stop, і збережіть відповідь як tool.html. Нижче наведено скрипт, який робить саме це, і шаблон запиту, який ви можете адаптувати для власного інструменту.
Ідея проста, і DeepSeek щойно її продемонстрував. Він опублікував колекцію з семи демонстраційних запитів для Creator Mode у DeepSeek Harness (сторінка, перевірена 3 листопада 2026 року): галерея 3D-пам'яток, робоча станція для постерів, робоча станція для редагування відео, читач статей, панель статистики розмов та кілька інших. Creator Mode працює всередині додатка Harness. Якщо ви хочете отримати такий самий потік «запит на вході — інструмент на виході» у власному скрипті з власним ключем, для односторінкового випадку достатньо звичайного чат-завершення. Якщо ви все ж використовуєте сам Harness, підключення його до CheapTokens — це окремий короткий посібник.
Що потрібно запиту «зроби мені інструмент»#
Прочитайте кілька з цих демонстраційних запитів, і з'явиться закономірність. Кожен із них говорить, що це за інструмент, що знаходиться на екрані, що роблять елементи керування, який початковий стан і чого він не повинен робити. Пропустіть щось із цього — і модель заповнить прогалину власним припущенням, яке зазвичай не збігається з вашим.
Ось шаблон із п'яти частин:
What it is: <one sentence: the tool and who uses it>
Layout: <what is on the screen, top to bottom>
Controls: <every input and button, and what each one does>
Defaults: <what the page shows before the user touches anything>
Constraints: <single HTML file, no external requests, no libraries, size of the page>А ось заповнена версія. Скажімо, ви постійно перераховуєте кулінарні міри і втомилися шукати конвертер:
What it is: a unit converter for cooking, for someone standing in a kitchen with a phone.
Layout: a title, one number field, two dropdowns (from, to), a large result line under them.
Controls: the dropdowns hold cup, tablespoon, teaspoon, ml, oz, g (flour) and g (sugar). Typing a number updates the result immediately. A swap button exchanges the two dropdowns.
Defaults: 1 cup to ml, result already shown.
Constraints: one HTML file with inline CSS and JavaScript, no external libraries, fonts or network requests, works on a narrow phone screen, dark text on a light background.Збережіть це як prompt.txt поруч зі скриптом. Рядок «Constraints» несе найбільше навантаження: без «no external requests» модель любить підтягувати бібліотеку з CDN, і сторінка тоді ламається офлайн.

Скрипт: запит, перевірка, збереження#
API CheapTokens сумісний з OpenAI Chat Completions за адресою https:/, тому пакет openai працює з двома змінами: базовий URL і ключ. Для цілої сторінки ми використовуємо deepseek-: він дозволяє до 32 768 вихідних токенів на відповідь і має контекстне вікно 380K. Повні деталі API — у документації CheapTokens.
Встановіть пакет, помістіть ключ у змінну середовища і задайте дві ціни з таблиці цін (скрипт використовує їх для виведення вартості):
pip install openai
export CHEAPTOKENS_API_KEY="your-key"
export PRICE_IN_PER_M="<input price per 1M from the table>"
export PRICE_OUT_PER_M="<output price per 1M from the table>"Потім make_tool.py:
import os
import re
import sys
from openai import OpenAI
MODEL = 'deepseek-ai/DeepSeek-V4-Flash-0731'
PRICE_IN = float(os.environ['PRICE_IN_PER_M']) # USD per 1M input tokens (from the table)
PRICE_OUT = float(os.environ['PRICE_OUT_PER_M']) # USD per 1M output tokens (from the table)
FENCE = '`' * 3
client = OpenAI(
base_url='https://api.cheaptokens.dev/v1',
api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
prompt = open('prompt.txt', encoding='utf-8').read()
resp = client.chat.completions.create(
model=MODEL,
max_tokens=16000,
messages=[
{'role': 'system', 'content': 'You write one self-contained HTML file. Reply with the file only, no commentary.'},
{'role': 'user', 'content': prompt},
],
)
choice = resp.choices[0]
if choice.finish_reason == 'length':
sys.exit('Cut off at max_tokens: the page is unfinished. Raise max_tokens or shrink the request.')
text = choice.message.content or ''
m = re.search(FENCE + r'(?:html)?\s*(.*?)' + FENCE, text, re.DOTALL)
html = (m.group(1) if m else text).strip()
if '</html>' not in html.lower():
sys.exit('The reply has no closing </html>; not saving it.')
with open('tool.html', 'w', encoding='utf-8') as f:
f.write(html)
u = resp.usage
cost = (u.prompt_tokens * PRICE_IN + u.completion_tokens * PRICE_OUT) / 1_000_000
print(f'saved tool.html, {u.prompt_tokens} in / {u.completion_tokens} out, about ${cost:.6f}')Порядок кроків має значення, і його легко переплутати:
Розставте по порядку
Розташуйте кроки скрипта в порядку їх виконання
Перетягніть елементи або скористайтеся стрілками
- Надішліть запит із щедрим max_tokens
- Перевірте finish_reason, перш ніж торкатися тексту
- Витягніть HTML із код-фенсу, якщо він є
- Переконайтеся, що закриваючий </html> на місці
- Збережіть tool.html і виведіть використання

Чому max_tokens визначає, чи працює сторінка#
Повна інтерактивна сторінка — це довга відповідь. HTML, CSS і JavaScript швидко накопичуються, і модель пише їх саме в такому порядку: якщо відповідь обрізано, ви втрачаєте кінець скрипта першим, а це саме та частина, яка змушує кнопки працювати. Браузер все ще може відкрити сторінку. Вона просто нічого не робить.
Ось чому скрипт перевіряє finish_reason, перш ніж дивитися на текст. stop означає, що модель завершила самостійно. length означає, що вона вперлася в стелю max_tokens посеред файлу. Загальна версія цієї проблеми розглянута в Відповідь AI обрізано? Виправте finish_reason length; тут правило коротке: ніколи не зберігайте сторінку, у якої finish_reason дорівнює length.
Якщо ви все ж це бачите:
- збільште
max_tokens(DeepSeek-V4-Flash дозволяє до 32 768 на відповідь); - або попросіть менше: менше елементів керування, один екран, без анімацій;
- на GLM-5.3-Flash (
zai-) стеля становить 8 192 вихідних токени, тож ця модель підходить для невеликих інструментів, як-от конвертер вище.org/ GLM- 5. 3- Flash
Друга перевірка, </html> у тексті, ловить тихіший збій, коли модель ввічливо завершує відповідь, не дописавши файл. Встановлення max_tokens також не змушує модель писати більше: це лише стеля, і ви платите за фактично згенеровані токени (докладніше в Скоротіть вихідні токени).
Швидка перевірка
Скрипт вивів finish_reason = length. Що ви робите?
Показати відповідь
Відповідь: Не зберігати його; збільшити max_tokens або зменшити запит
length означає, що відповідь було обрізано на стелі, тому кінець скрипта відсутній. Нижча стеля робить обрізання ще ранішим.
Відкрийте і подивіться на сторінку#
Відкрийте tool.html подвійним клацанням або з терміналу: open tool.html на macOS, xdg- на Linux, start tool.html на Windows.
Це код, який модель написала для вас, тож витратьте хвилину, перш ніж довіряти йому. Відкрийте інструменти розробника браузера (F12), подивіться на вкладку Network і перезавантажте: з обмеженням «no external requests» вона має залишатися порожньою. Потім натисніть кожен елемент керування з частини «Controls» вашого запиту по одному разу.
Якщо щось не так, не перегенеровуйте з нуля. Додайте одне речення до запиту про конкретну річ («кнопка обміну також повинна міняти місцями два значення») і запустіть знову. Власна сторінка DeepSeek зазначає, що деякі з її демо були вдосконалені протягом кількох раундів розмови, тож другий прохід — це нормально.
Спробуйте саміСпробуйте: що ви очікуєте побачити на вкладці Network для конвертера?Показати відповідь
Нічого: сторінка — це один файл із вбудованими CSS і JavaScript, тож після першого завантаження подальших запитів немає. Якщо ви бачите запит до CDN, модель проігнорувала обмеження; додайте його до запиту великими літерами і запустіть знову.
Скільки коштує одна генерація#
Скажімо, запит — це близько 600 вхідних токенів, а готова сторінка — близько 6 000 вихідних токенів (припущення для інструменту середнього розміру; ваш власний рядок usage покаже реальні цифри). Один запуск на DeepSeek-V4-Flash — це $0.00061, а на GLM-5.3-Flash — $0.00025. Обидва — актуальні цифри з поточного прайс-листа, і загалом, з урахуванням вхідних і вихідних разом, обидва дешевші за OpenRouter.
| Модель | Вхід $/1М | Вихід $/1М | Вартість | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.00025 | $0.00052 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00061 | $0.00088 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.00093 | $0.0112 |
600 вхідних і 6 000 вихідних токенів загалом. Ціни за 1 млн токенів актуальні та змінюються разом із нашими тарифами; стовпець OpenRouter показує довідкові ціни для того самого навантаження.
На практиці ви не отримаєте інструмент з першої спроби, тож думайте ітераціями: десять правок запиту — це десять разів той рядок, все ще невелика сума за інструмент, який інакше довелося б писати вручну. Майже все це вихідна сторона, сама сторінка, тому зменшення запиту (менше елементів керування) скорочує відповідь і рахунок.
Якщо не працює#
Прокрутіть таблицю праворуч →
| Що ви бачите | Ймовірна причина | Що робити |
|---|---|---|
401 або 404 від API |
неправильний ключ, базовий URL або ідентифікатор моделі | перевірте всі три, див. Помилка API 401 або 404 |
Cut off at max_ |
сторінка довша за стелю | збільште max_tokens або попросіть менше |
The reply has no closing </ |
модель зупинилася рано або додала текст | запустіть знову; додайте «end with </html>» до запиту |
| Сторінка відкривається, але кнопки нічого не роблять | помилка JavaScript | відкрийте консоль (F12), вставте червону помилку в наступний запит |
Якщо ви хочете, щоб відповідь моделі розбиралася як дані, а не як сторінка, трюк із вилученням той самий, що й у json.JSONDecodeError у відповіді LLM. Вперше з API? Почніть із вашого першого запиту до API.



