Bloga dön

API ve SDKKılavuz

Bir API ile tek prompttan HTML aracı üretin (Python)

Tek bir promptu çalışan bir tool.html dosyasına dönüştüren, kesilmiş bir yanıtı finish_reason ile yakalayan ve tokenları ve maliyeti yazdıran bir Python betiği.

Yazan: CheapTokens TeamYayınlanma tarihi: 6 dk okuma

finish_reason değerini kontrol eden ve tool.html dosyasını 'Tek prompt, tek HTML aracı' başlığının yanına kaydeden bir kod parçacığı
Bu sayfada
  1. "Bana bir araç yap" promptunun ihtiyaç duyduğu şeyler
  2. Betik: istek, kontrol, kaydet
  3. max_tokens sayfanın çalışıp çalışmayacağını neden belirler
  4. Açın ve sayfaya bakın
  5. Tek bir üretimin maliyeti
  6. Çalışmazsa

Tek bir API çağrısıyla çalışan tek dosyalık bir araç elde edebilirsiniz: iyi yapılandırılmış bir prompt gönderin, max_tokens değerinin tam bir sayfa için yeterince büyük olduğundan emin olun, finish_reason değerinin stop olduğunu kontrol edin ve yanıtı tool.html olarak kaydedin. Aşağıda tam olarak bunu yapan betik ve kendi aracınız için yeniden şekillendirebileceğiniz bir prompt şablonu var.

Fikir basit ve DeepSeek bunu az önce gösterdi. DeepSeek Harness'taki Creator Mode için yedi demo prompttan oluşan bir koleksiyon yayımladı (sayfa, 3 Kasım 2026'da kontrol edildi): bir 3D simge yapı galerisi, bir poster tezgâhı, bir video düzenleme tezgâhı, bir makale okuyucu, bir konuşma istatistikleri panosu ve birkaç tane daha. Creator Mode, Harness uygulamasının içinde yaşıyor. Aynı "prompt gir, araç çık" akışını kendi betiğinizde ve kendi anahtarınızla istiyorsanız, tek dosyalık durum için sıradan bir chat completion yeterlidir. Harness'ın kendisini kullanacaksanız, onu CheapTokens'e bağlamak ayrı ve kısa bir rehberdir.

"Bana bir araç yap" promptunun ihtiyaç duyduğu şeyler#

O demo promptlardan birkaçını okuyun, bir kalıp ortaya çıkıyor. Her biri aracın ne olduğunu, ekranda ne bulunduğunu, kontrollerin ne yaptığını, başlangıç durumunun ne olduğunu ve ne yapmaması gerektiğini söylüyor. Bunlardan birini atlarsanız model boşluğu kendi tahminiyle doldurur, ki bu genellikle sizinki değildir.

İşte şablon, beş bölüm:

text
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>

Ve doldurulmuş bir sürüm. Diyelim ki sürekli yemek ölçülerini dönüştürüyorsunuz ve bir dönüştürücü aramaktan yoruldunuz:

text
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.

Bunu betiğin yanına prompt.txt olarak kaydedin. "Constraints" satırı yükün çoğunu taşır: "no external requests" olmadan model bir CDN kütüphanesi çekmeyi sever ve sayfa çevrimdışı bozulur.

Öncesi ve sonrası: tek satırlık bir prompt ile aynı promptun beş bölümlü hali
Aynı istek tek satır ve beş bölüm olarak: ne olduğu, düzen, kontroller, varsayılanlar, kısıtlar

Betik: istek, kontrol, kaydet#

CheapTokens API'si https://api.cheaptokens.dev/v1 adresinde OpenAI Chat Completions ile uyumludur, yani openai paketi iki değişiklikle çalışır: temel URL ve anahtar. Tam bir sayfa için deepseek-ai/DeepSeek-V4-Flash-0731 kullanıyoruz: yanıt başına 32.768 çıktı tokenına kadar izin verir ve 380K bağlam penceresine sahiptir. Tam API ayrıntıları CheapTokens belgelerinde.

Paketi kurun, anahtarınızı bir ortam değişkenine koyun ve iki fiyatı fiyat tablosundan ayarlayın (betik bunları maliyeti yazdırmak için kullanır):

bash
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>"

Sonra make_tool.py:

python
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}')

Adımların sırası önemlidir ve yanlış yapmak kolaydır:

Sıraya koy

Betiğin adımlarını çalıştırdığı sıraya koyun

  1. Promptu cömert bir max_tokens ile gönderin
  2. Metne dokunmadan önce finish_reason değerini kontrol edin
  3. Varsa HTML'i kod bloğundan çıkarın
  4. Kapanış </html> etiketinin orada olduğunu doğrulayın
  5. tool.html dosyasını kaydedin ve kullanımı yazdırın
İşlem hattı: prompt, API çağrısı, finish_reason kontrolü, tool.html
Betiğin yaptıkları, prompttan kaydedilen dosyaya kadar

max_tokens sayfanın çalışıp çalışmayacağını neden belirler#

Tam etkileşimli bir sayfa uzun bir yanıttır. HTML, CSS ve JavaScript hızla birikir ve model bunları bu sırayla yazar: yanıt kesilirse önce betiğin sonunu kaybedersiniz, ki düğmeleri çalıştıran tam da o kısımdır. Tarayıcı sayfayı yine de açabilir. Sadece hiçbir şey yapmaz.

Bu yüzden betik metne bakmadan önce finish_reason değerini kontrol eder. stop modelin kendi kendine bitirdiği anlamına gelir. length ise dosyanın ortasında max_tokens sınırına takıldığı anlamına gelir. Bu sorunun genel hali AI yanıtı kesildi mi? finish_reason length sorununu düzeltin yazısında ele alınıyor; buradaki kural kısa: finish_reason değeri length olan bir sayfayı asla kaydetmeyin.

Yine de görürseniz:

  • max_tokens değerini artırın (DeepSeek-V4-Flash yanıt başına 32.768'e kadar izin verir);
  • ya da daha azını isteyin: daha az kontrol, tek ekran, animasyon yok;
  • GLM-5.3-Flash'te (zai-org/GLM-5.3-Flash) sınır 8.192 çıktı tokenıdır, yani o model yukarıdaki dönüştürücü gibi küçük araçlara uyar.

İkinci kontrol, metindeki </html>, modelin dosyayı bitirmeden yanıtı kibarca sonlandırdığı daha sessiz hatayı yakalar. max_tokens ayarlamak da modelin daha fazla yazmasını sağlamaz: bu yalnızca bir üst sınırdır ve yalnızca gerçekte üretilen tokenlar için ödersiniz (bunun hakkında daha fazlası Çıktı tokenlarını azaltın yazısında).

Hızlı kontrol

Betik finish_reason = length yazdırdı. Ne yaparsınız?

Cevabı göster

Cevap: Kaydetmeyin; max_tokens değerini artırın veya isteği küçültün

length, yanıtın sınırda kesildiği anlamına gelir, yani betiğin sonu eksiktir. Daha düşük bir sınır kesintinin daha erken gelmesine neden olur.

Açın ve sayfaya bakın#

tool.html dosyasını çift tıklayarak veya terminalden açın: macOS'te open tool.html, Linux'ta xdg-open tool.html, Windows'ta start tool.html.

Bu, bir modelin sizin için yazdığı koddur, o yüzden ona güvenmeden önce bir dakika ayırın. Tarayıcının geliştirici araçlarını açın (F12), Network sekmesine bakın ve yeniden yükleyin: "no external requests" kısıtıyla boş kalmalıdır. Sonra promptunuzun "Controls" bölümündeki her kontrolü bir kez tıklayın.

Bir şey ters giderse sıfırdan yeniden üretmeyin. Prompta belirli şeyle ilgili bir cümle ekleyin ("the swap button must also swap the two values") ve tekrar çalıştırın. DeepSeek'in kendi sayfası, demolarından bazılarının birkaç konuşma turu boyunca iyileştirildiğini belirtiyor, yani ikinci bir geçiş normaldir.

Kendin deneDeneyin: dönüştürücü için Network sekmesinde ne görmeyi beklersiniz?Cevabı göster

Hiçbir şey: sayfa satır içi CSS ve JavaScript içeren tek bir dosyadır, yani ilk yüklemeden sonra başka istek olmaz. Bir CDN'e istek görürseniz model kısıtı yok saymıştır; prompta büyük harflerle ekleyin ve tekrar çalıştırın.

Tek bir üretimin maliyeti#

Diyelim ki prompt yaklaşık 600 giriş tokenı ve bitmiş sayfa yaklaşık 6.000 çıktı tokenı (orta boyutlu bir araç için bir varsayım; kendi usage satırınız gerçek sayıları gösterecektir). DeepSeek-V4-Flash'te bir çalıştırma $0.00061, GLM-5.3-Flash'te ise $0.00025. İkisi de güncel fiyat listesinden canlı sayılardır ve toplamda, giriş ve çıktı birlikte sayıldığında, ikisi de OpenRouter'dan daha ucuzdur.

Model Maliyet OpenRouter
GLM-5.3-Flash $0.00025 $0.00052
DeepSeek-V4-Flash $0.00061 $0.00088
MiniMax-M2.7 $0.00093 $0.0112

Toplamda 600 giriş ve 6.000 çıkış token'ı. 1M token başına fiyatlar günceldir ve tarifelerimizle birlikte değişir; OpenRouter sütunu aynı iş yükü için referans fiyatları gösterir.

Pratikte aracı ilk denemede doğru yapamazsınız, o yüzden yinelemelerle düşünün: promptun on ince ayarı o satırın on katıdır, yine de elle yazacağınız bir araç için küçük bir meblağdır. Neredeyse tamamı çıktı tarafıdır, yani sayfanın kendisidir, bu yüzden isteği küçültmek (daha az kontrol) yanıtı ve faturayı kısaltır.

Çalışmazsa#

Gördüğünüz şey Muhtemel neden Ne yapmalı
API'den 401 veya 404 yanlış anahtar, temel URL veya model kimliği üçünü kontrol edin, bkz. API 401 veya 404 hatası
Cut off at max_tokens sayfa sınırdan uzun max_tokens değerini artırın veya daha azını isteyin
The reply has no closing </html> model erken durdu veya metin ekledi tekrar çalıştırın; prompta "end with </html>" ekleyin
Sayfa açılıyor ama düğmeler çalışmıyor JavaScript hatası konsolu açın (F12), kırmızı hatayı bir takip promptuna yapıştırın

Modelin yanıtının bir sayfa yerine veri olarak ayrıştırılmasını istiyorsanız, çıkarma hilesi bir LLM yanıtında json.JSONDecodeError yazısındakiyle aynıdır. API'de yeni misiniz? İlk API isteğiniz ile başlayın.