Discord Bot Kodlama AI: Bir LLM API ile Oluşturun
Bir Discord bot kodlama AI, sunucunuzun içinde programlama sorularını bir API arkasındaki dil modeli kullanarak yanıtlar. Bu eğitim, genellikle sorun çıkaran kısımları kapsayan yaklaşık 70 satır Python ile bir bot oluşturur.
güncellendi

Temel noktalar
- Botun çalışması için discord.py, openai paketi, bir bot token'ı ve bir LLM API anahtarı gerekir.
- Discord geliştirici portalında Message Content (Mesaj İçeriği) intentini etkinleştirin, aksi takdirde bot boş mesajlar görür.
- Model her çağrı arasında hiçbir şeyi hatırlamadığı için kısa bir kanal başına geçmiş tutun ve onu kısaltın.
- Yanıtları 2.000 karakterde bölün ve eşzamanlı çağrıları sınırlandırın; böylece 8 istek eşzamanlılık sınırının altında kalırsınız.
Botun ne yapacağı
Amaç, birisi onu etiketlediğinde tepki veren bir Discord bot kodlama AI oluşturmaktır. Bir kullanıcı "@yardımcı neden liste anlama (list comprehension) None döndürüyor?" yazar, bot mesajı modele gönderir ve modelin yanıtı aynı kanalda bir yanıt olarak döner. Bot ayrıca her kanalın son birkaç dönüşünü de hatırlar, böylece takip soruları çalışır.
Tasarım üç parçadan oluşur. discord.py Discord bağlantısını yönetir. OpenAI Python SDK, LLM API ile iletişim kurar; bu API burada OpenAI uyumlu olduğu için çalışır. Küçük bir sözlük konuşma geçmişini tutar. Başlamak için bir veritabanına ihtiyacınız yoktur.
Python 3.9 veya daha yeni bir sürüme, bir uygulama oluşturabilen bir Discord hesabına ve API anahtarı sayfasından bir API anahtarına ihtiyacınız olacaktır. Yeni hesaplar tek tıkla $0,50 deneme kredisi talep edebilir; bu botu oluşturmak ve test etmek için yeterlidir.
Adım 1: Discord uygulamasını oluşturun
- Discord geliştirici portalını açın ve yeni bir uygulama oluşturun.
- Bot bölümünde bot kullanıcısını oluşturun ve token'ını kopyalayın. Bunu bir şifre gibi ele alın.
- Aynı sayfada, Privileged Gateway Intents altında Message Content Intent seçeneğini açın. Bu olmadan bot boş metinli mesajlar alır ve neden hiç yanıt vermediğini anlamak için bir saat harcarsınız.
- OAuth2'de
botkapsamı ile mesajları okuma ve mesaj gönderme izinlerine sahip bir davet bağlantısı oluşturun. Bağlantıyı açın ve botu bir test sunucusuna ekleyin.
Kütüphaneleri yükleyin ve iki ortam değişkeni ayarlayın.
pip install discord.py openai
export DISCORD_TOKEN="your-discord-bot-token"
export LLM_API_KEY="your-llm-api-key"
# quick check that the LLM key works, using model uncensored
curl -s https://api.codingllmapi.com/v1/chat/completions \
-H "Authorization: Bearer $LLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"uncensored","messages":[{"role":"user","content":"ping"}],"max_tokens":5}'Adım 2: bot kodu
Bunu bot.py olarak kaydedin. Etiketlendiğinde yanıt verir, kanal başına on iki mesajlık geçmiş tutar, beklerken yazma göstergesini gösterir ve uzun yanıtları böler.
import asyncio
import os
import discord
from openai import AsyncOpenAI, RateLimitError, APIError
llm = AsyncOpenAI(
base_url="https://api.codingllmapi.com/v1",
api_key=os.environ["LLM_API_KEY"],
)
SYSTEM = (
"You are a helpful programming assistant in a Discord server. "
"Answer briefly. Put code in fenced blocks. Say so when you are unsure."
)
MAX_TURNS = 12
history = {} # channel id -> list of messages
slots = asyncio.Semaphore(6) # stay under the 8 concurrent request cap
intents = discord.Intents.default()
intents.message_content = True
bot = discord.Client(intents=intents)
def split_reply(text, limit=1900):
parts = []
while len(text) > limit:
cut = text.rfind("\n", 0, limit)
if cut < limit // 2:
cut = limit
parts.append(text[:cut])
text = text[cut:].lstrip("\n")
parts.append(text)
return parts
@bot.event
async def on_message(message):
if message.author.bot or bot.user not in message.mentions:
return
question = message.clean_content.replace(f"@{bot.user.display_name}", "").strip()
if not question:
await message.reply("Ask me a coding question after the mention.")
return
log = history.setdefault(message.channel.id, [])
log.append({"role": "user", "content": question})
del log[:-MAX_TURNS]
async with message.channel.typing():
try:
async with slots:
resp = await llm.chat.completions.create(
model="uncensored",
messages=[{"role": "system", "content": SYSTEM}] + log,
temperature=0.4,
max_tokens=900,
)
except RateLimitError:
await message.reply("The model is busy. Try again in a few seconds.")
log.pop()
return
except APIError:
await message.reply("The model call failed. Try again shortly.")
log.pop()
return
answer = resp.choices[0].message.content or "(empty reply)"
log.append({"role": "assistant", "content": answer})
for part in split_reply(answer):
await message.reply(part)
bot.run(os.environ["DISCORD_TOKEN"])
python bot.py ile çalıştırın, ardından test sunucunuzda botu etiketleyin. İlk yanıt birkaç saniye içinde gelmelidir.
Kodun bu şekilde yazılma nedeni
Geçmiş bilerek kırpılır
Modelin hafızası yoktur, bu nedenle her çağrı son dönüşleri gönderir. del log[:-MAX_TURNS] olmadan liste sonsuza kadar büyür. Sonunda 100.000 token penceresine çarpar ve her mesajla maliyetleriniz artar. On iki kayıt, bir hata hakkında bir konuşma için yeterlidir. Uzun thread'leri olan bir sunucu için bunu artırın veya eski dönüşleri özetleyin.
Discord'un 2.000 karakterlik sınırı
Discord, 2.000 karakterden uzun mesajları reddeder ve kod yanıtları buna hızla ulaşır. split_reply yardımcı programı, sınıra yakın bir yeni satırda keser. Kod parçacıkları (code fences) hakkında bilgisi yoktur, bu nedenle bir blok ortadan kesilebilir. Bu sizi rahatsız ediyorsa, bir parçanın sonuna bir fence kapatma ve bir sonraki parçanın başında yeniden açma mantığı ekleyin.
Eşzamanlılık için bir semaphore
Tam bir anahtar 8 eşzamanlı istek yapmanıza olanak tanır, deneme anahtarı ise 2'ye izin verir. Yoğun bir sunucu aynı anda birden fazla istek alabilir. Semaphore, ek çağrıları gönderip concurrency hata kodlu bir 429 yanıtı almak yerine, işleminizin içinde kuyruğa alır. Hâlâ deneme anahtarındaysanız, Semaphore(6) değerini Semaphore(2) olarak değiştirin.
Hatalar ücretlendirilmez
Başarısız veya reddedilen istekler faturalandırılmaz, bu nedenle bir hatadan sonra yeniden deneme maliyeti iki katına çıkarmaz. Kod, başarısızlık durumunda kullanıcı dönüşünü geçmişten siler, böylece modelin zaten iki kez gördüğü asılı bir soru kalmaz.
Yanıtları daha iyi hale getirmek
Temel döngü çalıştıktan sonra, birkaç küçük değişiklik onu büyük ölçüde iyileştirir.
- Yanıtı akış (stream) yapın.
stream=Trueparametresini geçin ve botun mesajını şu ana kadar olan metinle yaklaşık olarak her saniye düzenleyin. Discord mesaj düzenlemeleri için kendi hız limitlerini uyguladığı için her token'da düzenleme yapmayın. Akışlı bir istek, sona erene kadar eşzamanlılık slotunu tutar, bu nedenle semaphore'u tüm akış boyunca koruyun. - Slash komutları kullanın.
/askgibi bir komut, etiket ayrıştırmasını önler ve Message Content intentine hiç gerek duymaz; bu da bot az sayıda sunucuyu aştığında sonradan doğrulanmasını kolaylaştırır. - Kullanıcı başına geçmiş. Birden fazla kişinin bir kanalda birbirinden bağımsız sorular sorduğu durumlarda, geçmişi kanal ve kullanıcı bazlı olarak gruplayın.
- Sistem istemini (system prompt) ince ayarlayın. Topluluğunuzun kullandığı dilleri adlandırın, kısa yanıtlar isteyin ve modelin sorun belirsiz olduğunda bir netleştirme sorusu sormasını söyleyin. İstem değişiklikleri ücretsizdir ve genellikle model değişikliklerinden daha iyi sonuç verir.
- Sıcaklığı (temperature) düşürün. Kod için 0.2 ile 0.4 arasındaki değerler varsayılandan daha istikrarlı sonuçlar verir.
Yaygın hataları giderme
Yeni bir bot sessiz kaldığında, neden neredeyse her zaman aşağıdaki maddelerden biridir. Bunları bu sırayla kontrol edin.
- Bot çevrimiçi ancak hiç yanıt vermiyor. Geliştirici portalında Message Content intenti kapalıdır veya kodda
intents.message_content = Trueeksiktir. İkisinin de ayarlanması gerekir. - Yalnızca bazı kanallarda yanıt veriyor. Botun diğerlerinde mesajları okuma veya gönderme izni yoktur. Sunucu genelindeki rolü değil, kanalın izin geçersiz kılma ayarlarını kontrol edin.
- Her yanıt bir "meşgul" mesajı. Muhtemelen bir 429'a çarpıyorsunuz. İstisna gövdesini bir kez yazdırın. Kod
rate_limiteddiyorsa, tam anahtarda dakikada 300 istek veya deneme anahtarında 60 istek sınırını aştınız.concurrencydiyorsa, semaphore boyutunu düşürün. - İlk çağrıda bir kimlik doğrulama hatası görünüyor. Botu çalıştıran işlemin ortamında LLM anahtarı eksik. Bir terminal sekmesinde dışa aktarılan bir anahtar, başka bir yerde başlatılan bir hizmet için görünmez.
- Yanıt kesiliyor. Örnekteki
max_tokens=900uzun yanıtları durdurur. Bunu artırın veya kaldırın; çünkümax_tokensisteğe bağlıdır ve tamamlama pencerenin geri kalanını kullanabilir. - Bot kendi mesajlarına yanıt veriyor. Bu döngü,
message.author.botkontrolünü atlayarsanız oluşur. Bunu koruyun.
Hata ayıklama için, her çağrı için X-Request-Id değerini günlüğe kaydedin. OpenAI SDK ile llm.chat.completions.with_raw_response.create(...) çağırarak ham yanıttan okuyabilir ve ardından .headers okuyabilirsiniz. Belirli bir hata hakkında destekle iletişime geçtiğinizde, bu ID onların tam isteği bulmasını sağlar.
Bunun çalışma maliyeti
Fiyatlandırma, 1M giriş token'ı başına $0,15 ve 1M çıktı token'ı başına $0,50'dir; abonelik yoktur. Tipik bir değişimi ele alalım: sistem istemi ve on iki geçmiş girdisi yaklaşık 2.500 giriş token'ı oluşturur ve yanıt yaklaşık 400 token'dır.
Girdi: 2.500 x $0,15 / 1.000.000 = $0,000375. Çıktı: 400 x $0,50 / 1.000.000 = $0,0002. Bir yanıt yaklaşık $0,000575'a mal olur. Bir günde 500 soru soran bir topluluk, 500 x $0,000575 = $0,2875 harcar; bu otuz kuruşun biraz altındadır. Daha uzun kod yapıştırmalarıyla sayılarınız farklı olacaktır, bu yüzden resp.usage'i bir hafta boyunca günlüğe kaydedin ve gerçek ortalamaları okuyun. fiyatlandırma sayfası, bakiye yükleme seçeneklerini gösterir: $20 ile $500 arasında tam tutarlar, $50'den itibaren +%5, $100'den itibaren +%10 ve $200'den itibaren +%15 eklenir; kart veya kripto ile ödenir.
Kötüye kullanımı sınırlamak için kullanıcı başına bir bekleme süresi ve soru uzunluğu için bir sınır ekleyin. Bu iki kontrol, ekleyebileceğiniz başka hiçbir şeyden daha iyi bakiyenizi korur.
Barındırma ve güvenlik notları
Bot uzun süre çalışan bir süreçtir. Ağır işler API tarafında gerçekleştiğinden küçük bir sanal makine veya konteyner sunucusu yeterlidir. Çökme sonrası yeniden başlatılması için bir süreç yöneticisi altında çalıştırın ve her iki token'ı da ortam değişkenlerinde veya bir gizli veri deposunda tutun; depoda saklamayın.
Sunucunuzun neye izin verdiğini düşünün. Model, yetişkinler için yasal kullanım için içerik reddi olmadan yanıt verecek şekilde ayarlanmıştır, bu nedenle güvenlik testi veya sınırları zorlayan kurgu hakkında konuşacaktır; daha katı bir asistan reddedebilir. Topluluğunuzda daha genç üyeler varsa, sistem isteminde kurallar belirleyin, botu belirli kanallarla sınırlayın ve Discord'un kendi şartlarının da botunuz için geçerli olduğunu unutmayın. Reşit olmayanların cinselleştirildiği içerik bu API'de istisnasız olarak yasaktır.
stop, seed ve fonksiyon çağırma gibi tam parametre ayrıntıları API belgelerinde yer alır. Botun kod çalıştırmasını veya depoları okumasını istiyorsanız, fonksiyon çağırma yolu budur ve modelin hangi fonksiyonları isteyebileceğine siz karar verirsiniz. Bu modelin programlamaya odaklı kullanımı için sansürsüz AI model için kodlama sayfasına bakın.
Daha fazla kılavuz
Sorular ve cevaplar
Message Content intentine mi ihtiyacım var?
Evet, bot normal mesajları ve etiketlemeleri okuyorsa. Yalnızca eğik çizgi komutları kullanıyorsanız buna ihtiyacınız yoktur.
Bot yanıtları akış yapabilir mi?
Evet. stream=True ayarlayın ve Discord'un kendi limitleri içinde kalmak için sakin bir aralıkta, örneğin saniyede bir, Discord mesajını düzenleyin.
Aynı anda çok fazla kişi soru sorarsa ne olur?
Tam bir anahtar üzerinde 8 eşzamanlı isteğin ötesine geçildiğinde, API HTTP 429 kodunu concurrency koduyla döndürür. Kodunuzdaki bir semaphore, ek soruları kuyruğa alır.
Bot yeniden başlatıldıktan sonra konuşmaları hatırlayacak mı?
Burada kullanılan sözlük ile hayır. Yeniden başlatmalardan hayatta kalmasını istiyorsanız geçmişi SQLite veya Redis'te saklayın.
API anahtarı bir Discord botunda güvenli mi?
Eğer sunucunuzda bir ortam değişkeninde kalıyorsa evet. Bunu bir kanalda asla yayınlamayın veya genel bir depoya asla commit etmeyin.
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.
API anahtarı al