Kurulum ve ilk istek
Sanal ortam oluşturun ve SDK'yı yükleyin. openai paketinin sürüm 1 veya sonrası varsayılır.
python -m venv .venv
source .venv/bin/activate
pip install --upgrade openaiAPI anahtarı sayfasından bir anahtar alın; yeni kullanıcılar tek tıkla 7 gün geçerli ve kart gerektirmeyen $0.50 deneme kredisi alabilir. Anahtarı bir ortam değişkeninde tutun, ardından ilk çağrıyı yapın:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.glmapi.cc/v1",
api_key=os.environ["GLM_API_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a concise writing assistant."},
{"role": "user", "content": "Suggest five titles for a space-western novel."},
],
temperature=0.8,
)
print(resp.choices[0].message.content)
print(resp.usage)Bu tüm entegrasyondur. Hizmet, tek bir açık ağırlıklı model için bağımsız, OpenAI uyumlu bir uç noktadır, bu nedenle GLM'nin arkasındaki tedarikçinin veya başkasının resmi API'si değildir. Sadece POST /v1/chat/completions ve GET /v1/models mevcuttur. hızlı başlangıç desteklenen istek alanlarını listeler.
İki küçük alışkanlık başlangıçta yardımcı olur. İlk olarak, bir smoke testinde client.models.list()'i bir kez çağırın: bu GET /v1/models'e erişir, böylece bir tamamlama için tek bir token harcamadan önce anahtarın, temel URL'nin ve ağ yolunun çalıştığını kanıtlar. İkinci olarak, geliştirme sırasında resp.usage'i yazdırın. İstem ve tamamlama token sayıları, bir sistem isteminizin düşündüğünüzden daha büyük olup olmadığını erken gösterir ve 1M başına $0.15 giriş ve 1M başına $0.50 çıkış fiyatıyla bir çağrıyı zihninizde fiyatlandırabilirsiniz.
Çoklu sohbet ve örnekleme ayarları
API durum bilgisi taşımaz, bu nedenle konuşma listesini kendiniz tutar ve her seferinde gönderirsiniz. Küçük bir sınıf yeterlidir:
class Chat:
def __init__(self, client, system, max_turns=12):
self.client = client
self.system = system
self.max_turns = max_turns
self.history = []
def say(self, text):
self.history.append({"role": "user", "content": text})
window = self.history[-self.max_turns * 2:]
resp = self.client.chat.completions.create(
model="uncensored",
messages=[{"role": "system", "content": self.system}] + window,
temperature=0.9,
top_p=0.95,
frequency_penalty=0.3,
)
reply = resp.choices[0].message.content
self.history.append({"role": "assistant", "content": reply})
return replyself.history[-self.max_turns * 2:] dilimi son on iki kullanıcı ve asistan çiftini korur. Gerçek bir uygulama ayrıca birkaç erken mesajı sabitleyebilir, örneğin bir karakter sayfası veya temel gerçekler gibi ve ortayı özetleyebilir. Son 12 adıma kırpma, konuşma büyüdükçe giriş maliyetini sabit tutar. Bağlam penceresi istem ve tamamlama için birlikte 100.000 token içerir, bu nedenle bu bir zorunluluktan çok bir maliyet seçimidir. temperature, top_p, stop, seed parametreleri ve cezalar aktarılır. Bir istemi test ederken tekrarlanabilir çalıştırmalar istediğinizde seed'i ayarlayın ve uzunluğu sınırlamak istemediğiniz sürece max_tokens'i dışarıda bırakın.
Akış yanıtları
Akış, sunucu tarafından gönderilen olayları kullanır ve tokenları oluşturulurken size verir, bu da herhangi bir etkileşimli araç için önemlidir. stream=True parametresini iletin ve döngü kurun:
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Describe a harbour at dawn in 120 words."}],
stream=True,
)
parts = []
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta.content
if delta:
parts.append(delta)
print(delta, end="", flush=True)
text = "".join(parts)chunk.choices üzerindeki kontrol önemlidir çünkü son parça kullanım bilgisi taşır ve boş bir choices listesi içerebilir. Operasyonel bir nokta: akışlı bir istek, akış bitene kadar eşzamanlılık yuvasını tutar. Döngüyü, kodunuz yolda bir hata verirse (örneğin bir istemci bağlantısı koptuğunda) akışı kapatan bir finally bloğu ile bir try bloğu içine alın. Akışı her zaman sonlandırın veya kapatın, aksi takdirde akışları terk eden bir döngü, hiçbir faydalı iş yapmadan eşzamanlılık sınırına çarpar.
JSON modu
Çıktı başka kodu beslediğinde bir JSON nesnesi isteyin. Beklenen şekli modele bildirmek için JSON'u istemde de belirtin:
import json
resp = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply with a JSON object only."},
{"role": "user", "content": "Give a character with keys name, age, motto."},
],
)
data = json.loads(resp.choices[0].message.content)
print(data["name"])Hala üretim kodunda json.loads'i bir try bloğuna sarın. JSON modu geçerli bir çıkış olasılığını artırır, ancak bir durdurma dizisi veya kendi sınırınız tarafından kesilen bir istek hala kesik bir nesne bırakabilir. Aynı girdiyle bir kez yeniden denemek ucuz bir çözümdür ve başarısız istekler ücretlendirilmediğinden, yeniden denemenin maliyeti yalnızca başarılı olan çağrıdır.
Araç çağırma
Araç çağırma OpenAI formatını izler: tools içinde fonksiyonları tanımlarsınız, model tool_calls döndürür, onları çalıştırırsınız ve sonuçları tool rolüyle geri gönderirsiniz. Tam bir dönüş:
import json
tools = [{
"type": "function",
"function": {
"name": "roll_dice",
"description": "Roll a die with the given number of sides.",
"parameters": {
"type": "object",
"properties": {"sides": {"type": "integer"}},
"required": ["sides"],
},
},
}]
messages = [{"role": "user", "content": "Roll a twenty-sided die for me."}]
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 = {"value": 17, "sides": args["sides"]} # replace with real logic
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
final = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools
)
print(final.choices[0].message.content)
else:
print(msg.content)Döngü, zar örneğinin ayrıntılarından daha önemlidir. Model bir çağrı ister, kodunuz bunu çalıştırır ve tekrar sormadan önce hem asistan mesajını hem de araç sonucunu eklersiniz. Asistan mesajını atlarsanız sonuçtaki tool_call_id ile eşleşecek bir şey olmaz ki bu genellikle kafa karıştırıcı ikinci yanıtın nedenidir. tool_choice auto olarak ayarlandığında model bir aracı çağırıp çağırmayacağına karar verir, bu nedenle yukarıdaki kodun yaptığı gibi doğrudan yanıt verdiği dalı her zaman işleyin. Akışlı yanıtlar da tool_calls taşıyabilir, parçalar halinde teslim edilirler ve argümanları ayrıştırmadan önce indeksle birleştirirsiniz.
Argümanları kullanmadan önce doğrulayın. Model bozuk bir çağrı üretebilir ve kodunuz argümanları bir kullanıcıdan gelen her şey gibi güvenilmeyen girdi olarak ele almalıdır.
Sınırlar dahilinde eşzamanlı toplu işler
Birden fazla istemi aynı anda göndermek için AsyncOpenAI ile eşzamanlılık sınırınıza uygun bir semafor kullanın. Tam anahtar 8 eşzamanlı istek, deneme anahtarı ise 2 isteğe izin verir:
import asyncio, os
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url="https://api.glmapi.cc/v1",
api_key=os.environ["GLM_API_KEY"],
)
gate = asyncio.Semaphore(8) # use 2 on a trial key
async def one(prompt):
async with gate:
r = await client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
)
return r.choices[0].message.content
async def main():
prompts = [f"Write a one-line tagline for product {i}." for i in range(40)]
results = await asyncio.gather(*(one(p) for p in prompts))
print(len(results))
asyncio.run(main())Semafor eşzamanlılığı yönetir ancak dakika başına 300 istek sınırını yönetmez. Uzun toplu işlemler için küçük bir gecikme veya token-kova limitleyici ekleyin. 1M girdi token başı $0.15 ve 1M çıktı token başı $0.50 fiyatla, yaklaşık 60 token girdisi ve 25 token çıktısı olan 40 slogan isteği toplamda $0.00036 + $0.0005 = $0.00086 tutarında maliyet oluşturur; bu nedenle limitler, fiyat değil, toplu iş tasarımını belirler. Bakiye yüklemek için fiyatlandırma sayfasına bakın.
Hız limitleri, yeniden denemeler ve başlıklar
Bir sınırı aşarsanız API HTTP 429 döndürür. Hata kodu, dakikada çok fazla istek için rate_limited ve aynı anda çok fazla istek için concurrency'dir. Geçici aşırı yüklenme de Retry-After: 5 başlığıyla 429 döndürür. SDK bazı hataları kendi başına yeniden dener ve istemcide max_retries ayarlayabilirsiniz, ancak açık işleme daha nettir:
import time
from openai import RateLimitError
def ask(prompt, tries=4):
for attempt in range(tries):
try:
raw = client.chat.completions.with_raw_response.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
)
print("balance:", raw.headers.get("X-Balance-USD"))
return raw.parse().choices[0].message.content
except RateLimitError as e:
wait = float(e.response.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
raise RuntimeError("still rate limited")Burada with_raw_response, X-Balance-USD, X-Request-Id ve hız limiti başlıklarına erişim sağlar. Rapor etmek istediğiniz herhangi bir hata ile birlikte istek kimliğini günlüğe kaydedin. Anahtarı commit ettiğiniz bir not defterine veya ön uç koduna koymayın.
Kredi harcamadan test etme ve yaygın hatalar
Python entegrasyonunun çoğu altyapıdır ve altyapının canlı bir modele ihtiyacı yoktur. Ağ çağrısını bir işlevin arkasında tutun ve testleriniz onu değiştirebilir. Yalnızca standart kütüphane ile:
from unittest.mock import MagicMock
def reply_text(client, prompt):
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
)
return r.choices[0].message.content.strip()
def test_reply_text_strips_whitespace():
fake = MagicMock()
fake.chat.completions.create.return_value.choices = [
MagicMock(message=MagicMock(content=" hello "))
]
assert reply_text(fake, "hi") == "hello"Gerçek çağrıları yalnızca uçlarda çalıştırın: her dağıtım için bir duman testi ve kayıtlı istem setinizin periyodik bir çalıştırması. Yaklaşık 100 token giriş ve 20 çıkış içeren tek bir duman testi $0.000015 + $0.00001 = $0.000025 maliyetinde olur, bu da bir şey değildir ve başarısız istekler tamamen ücretlendirilmez. $0.50 deneme kredisi bir test paketi için gerekenlerden çok daha fazlasıdır.
İstem işleri için seed ve temperature'i sabitleyin, böylece bir sistem isteminin iki sürümünü eşit koşullarda karşılaştırabilirsiniz. Çalıştırmalar arasında hem istemi hem de örnekleme ayarlarını değiştirmek sonuçları okunamaz hale getirir. Her çalıştırmanın çıktısını X-Request-Id başlığından istek kimliğiyle birlikte saklayın ve şaşırtıcı bir yanıtı daha sonra izleyebilirsiniz.
Yaygın Python hataları
Python kullanıcılarından gelen destek sorularının çoğunu bunlar oluşturur:
- Anahtarı yalnızca
OPENAI_API_KEYolarak geçirme. Koddabase_urlayarlarsanız ancak anahtar değişkenini unutursanız, SDK boş veya yanlış anahtar gönderir.api_key'i açıkça iletin. /v1'i unutma. Base URL/v1ile biter. SDK/chat/completions'i kendisi ekler.- Başka bir hizmetten bir model adı kullanma. Burada yalnızca
uncensoredgeçerlidir. - Sınırsız eşzamanlılık. Semafor olmadan binlerce korutin üzerinde
asyncio.gatherçalıştırmak,concurrencyhatalarından oluşan bir duvar üretir. - Akışlı bir yanıtı tek bir dize olarak ele alma. Delta'ları birleştirin ve boş bir
choiceslistesi içeren parçaları atlayın. - Bağlam sınırını görmezden gelme. Geçmiş ve tamamlama 100.000 token içine sığmalıdır. Ona ulaşmadan önce eski mesajları kırpın.
Bakiye yüklemek ve güncel fiyat listesine bakmak için fiyatlandırma sayfasına bakın. Hizmet yalnızca metin içindir, bu nedenle bağlanacak resim, ses veya gömme çağrıları yoktur ve istemler eğitim için kullanılmaz.
Daha fazla kılavuz
Sorular ve cevaplar
Hangi Python paketine ihtiyacım var?
Standart openai paketi, sürüm 1 veya sonrası. base_url'yi https://api.glmapi.cc/v1 olarak ayarlayın ve modeli uncensored olarak ayarlayın.
Akış çalışıyor mu?
Evet. stream=True parametresini iletin ve parçalar üzerinden döngü kurun. Akış, kullanım bilgisiyle sona erer ve bitene kadar eşzamanlılık slotunu işgal eder.
Aynı anda kaç istek çalıştırabilirim?
Tam anahtar 8 eşzamanlı istek ve dakikada 300'e izin verir. Deneme anahtarı 2 ve 60'a izin verir.
LangChain veya LiteLLM kullanabilir miyim?
Her ikisi de base URL'yi, API anahtarını ve uncensored model adını verdiğinizde OpenAI-uyumlu bir uç noktayla iletişim kurabilir. Doğru parametre adları için her projenin dokümantasyonunu kontrol edin.
Anahtarınız tek bir formun uzağında
Bir hesap oluşturun, anahtarı kopyalayın ve base URL'yi değiştirin. Kurulum bu kadar basit.
