Discord-Bot-Coding-AI: Erstelle einen mit einer LLM-API
Ein Discord-Bot-Coding-AI beantwortet Programmierfragen in deinem Server, indem er ein Sprachmodell hinter einer API nutzt. Dieses Tutorial erstellt einen in etwa 70 Zeilen Python und behandelt die Teile, die normalerweise brechen.
Aktualisiert

Wichtige Punkte
- Der Bot benötigt discord.py, das openai-Paket, einen Bot-Token und einen LLM-API-Schlüssel.
- Aktiviere die Message-Content-Intention im Discord-Entwicklerportal, sonst sieht der Bot leere Nachrichten.
- Behalte einen kurzen Verlauf pro Kanal und kürze ihn, da sich das Modell zwischen Aufrufen an nichts erinnert.
- Teile Antworten bei 2.000 Zeichen und begrenze parallele Aufrufe, damit du unter der 8-Anfragen-Parallelitätsgrenze bleibst.
Was der Bot tun wird
Das Ziel ist ein Discord-Bot-Coding-AI, der reagiert, wenn jemand ihn erwähnt. Ein Benutzer schreibt „@helper, warum gibt meine List Comprehension None zurück?“, der Bot sendet die Nachricht an das Modell und die Antwort des Modells kommt als Antwort im selben Kanal zurück. Der Bot erinnert sich auch an die letzten paar Durchgänge jedes Kanals, damit Folgefragen funktionieren.
Das Design besteht aus drei Teilen. discord.py behandelt die Verbindung zu Discord. Das OpenAI Python SDK spricht mit der LLM-API, die hier funktioniert, weil die API OpenAI-kompatibel ist. Ein kleines Dictionary hält den Gesprächsverlauf. Du brauchst keine Datenbank zum Starten.
Du benötigst Python 3.9 oder neuer, ein Discord-Konto, das eine Anwendung erstellen kann, und einen API-Schlüssel von der API-Schlüssel-Seite. Neue Konten können mit einem Klick $0,50 Testguthaben beanspruchen, das ausreicht, um diesen Bot zu erstellen und zu testen.
Schritt 1: Erstelle die Discord-Anwendung
- Öffne das Discord-Entwicklerportal und erstelle eine neue Anwendung.
- Erstelle im Bot-Bereich den Bot-Benutzer und kopiere seinen Token. Behandle ihn wie ein Passwort.
- Schalte auf derselben Seite unter Privileged Gateway Intents Message Content Intent ein. Ohne ihn erhält der Bot Nachrichten mit leerem Text, und du verbringst eine Stunde damit zu rätseln, warum er nie antwortet.
- Generiere in OAuth2 einen Einladungslink mit der
bot-Scope und den Berechtigungen zum Lesen und Senden von Nachrichten. Öffne den Link und füge den Bot zu einem Testserver hinzu.
Installiere die Bibliotheken und setze zwei Umgebungsvariablen.
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}'Schritt 2: Der Bot-Code
Speichere dies als bot.py. Er antwortet bei Erwähnung, behält den Verlauf von zwölf Nachrichten pro Kanal bei, zeigt den Tipp-Indikator während des Wartens an und teilt lange Antworten.
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"])
Führe es mit python bot.py aus und erwähne den Bot dann in deinem Testserver. Die erste Antwort sollte innerhalb weniger Sekunden ankommen.
Warum der Code so geschrieben ist
Verlauf wird absichtlich gekürzt
Das Modell hat kein Gedächtnis, daher sendet jeder Aufruf die letzten Durchgänge. Ohne del log[:-MAX_TURNS] würde die Liste ewig wachsen. Irgendwann würde sie das 100.000-Token-Fenster erreichen und deine Kosten würden mit jeder Nachricht steigen. Zwölf Einträge reichen für ein Gespräch über einen Fehler. Für einen Server mit langen Threads erhöhe ihn oder fasse ältere Durchgänge zusammen.
Die 2.000-Zeichen-Grenze von Discord
Discord lehnt Nachrichten ab, die länger als 2.000 Zeichen sind, und Code-Antworten erreichen das schnell. Die split_reply-Hilfsfunktion schneidet bei einem Newline nahe der Grenze. Sie kennt keine Code-Fences, daher kann ein Block in der Mitte durchtrennt werden. Wenn dich das stört, füge Logik hinzu, die eine Fence am Ende eines Teils schließt und am Anfang des nächsten wieder öffnet.
Ein Semaphore für Parallelität
Ein vollständiger Schlüssel erlaubt 8 parallele Anfragen, ein Test-Schlüssel 2. Ein ausgelasteter Server kann mehrere Anfragen gleichzeitig auslösen. Das Semaphore stellt zusätzliche Aufrufe in deinem Prozess in eine Warteschlange, statt sie zu senden und einen 429-Fehler mit dem Code concurrency zu erhalten. Wenn du noch den Test-Schlüssel nutzt, ändere Semaphore(6) in Semaphore(2).
Fehler werden nicht berechnet
Fehlgeschlagene oder abgelehnte Anfragen werden nicht berechnet, daher verdoppelt ein Retry nach einem Fehler nicht die Kosten. Der Code entfernt die Nutzernachricht bei einem Fehler aus dem Verlauf, sodass ein Retry keine schwebende Frage hinterlässt, die das Modell bereits zweimal gesehen hat.
Antworten besser machen
Sobald die grundlegende Schleife funktioniert, verbessern ein paar kleine Änderungen sie erheblich.
- Stream die Antwort. Übergebe
stream=Trueund bearbeite die Nachricht des Bots etwa jede Sekunde mit dem bisherigen Text. Bearbeite sie nicht bei jedem Token, da Discord eigene Ratenlimits für Nachrichtenbearbeitungen anwendet. Eine gestreamte Anfrage belegt ihren Parallelitäts-Slot bis zum Ende, also halte das Semaphore um den gesamten Stream herum. - Nutze Slash-Befehle. Ein Befehl wie
/askvermeidet das Parsing der Erwähnungen und benötigt die Message Content-Intention überhaupt nicht, was den Bot später auch einfacher verifizierbar macht, wenn er über eine kleine Anzahl von Servern hinauswächst. - Pro-Benutzer-Verlauf. Verknüpfe den Verlauf nach Kanal und Benutzer, wenn mehrere Personen in einem Kanal unabhängige Fragen stellen.
- Passe das System-Prompt an. Nenne die Sprachen, die deine Community verwendet, bitte um kurze Antworten und teile dem Modell mit, bei vagen Problemen eine Klärungsfrage zu stellen. Prompt-Änderungen sind kostenlos und schlagen oft Modell-Änderungen.
- Senke die Temperatur. Für Code geben Werte zwischen 0,2 und 0,4 stabilere Ergebnisse als der Standard.
Fehlerbehebung bei den üblichen Ausfällen
Wenn ein neuer Bot schweigt, ist die Ursache fast immer einer der untenstehenden Punkte. Überprüfe sie in dieser Reihenfolge.
- Der Bot ist online, antwortet aber nie. Die Message-Content-Intention ist im Entwicklerportal deaktiviert, oder
intents.message_content = Truefehlt im Code. Beide müssen gesetzt sein. - Er antwortet nur in einigen Kanälen. Dem Bot fehlen Berechtigungen zum Lesen oder Senden von Nachrichten in den anderen. Überprüfe die Kanal-Berechtigungsüberschreibungen, nicht nur die serverweite Rolle.
- Jede Antwort ist eine "busy"-Nachricht. Du triffst wahrscheinlich auf einen 429-Fehler. Gib den Ausnahmetext einmal aus. Wenn der Code
rate_limitedlautet, hast du das pro Minute geltende Limit von 300 Anfragen bei einem vollständigen Schlüssel oder 60 bei einem Test-Schlüssel überschritten. Wenn esconcurrencylautet, reduziere die Semaphore-Größe. - Bei der ersten Anfrage tritt ein Authentifizierungsfehler auf. Der LLM-Schlüssel fehlt im Environment des Prozesses, der den Bot ausführt. Ein in einem Terminal-Tab exportierter Schlüssel ist für einen anders gestarteten Dienst nicht sichtbar.
- Die Antwort wird abgeschnitten. Das
max_tokens=900im Beispiel stoppt lange Antworten. Erhöhe es oder entferne es, damax_tokensoptional ist und die Vervollständigung den Rest des Fensters nutzen kann. - Der Bot antwortet auf sich selbst. Dies passiert, wenn du die
message.author.bot-Prüfung entfernst. Behalte sie.
Zum Debuggen protokolliere den Wert von X-Request-Id für jede Anfrage. Mit dem OpenAI SDK kannst du ihn aus der Rohantwort lesen, indem du llm.chat.completions.with_raw_response.create(...) aufrufst und dann .headers ausliest. Wenn du den Support wegen eines bestimmten Fehlers kontaktierst, ermöglicht diese ID ihnen, die genaue Anfrage zu finden.
Was das in der Ausführung kostet
Der Preis beträgt $0,15 pro 1 Mio. Input-Token und $0,50 pro 1 Mio. Output-Token, ohne Abonnement. Ein typischer Austausch: Der System-Prompt plus zwölf Verlaufseinträge ergeben etwa 2.500 Input-Token, und die Antwort ist etwa 400 Token lang.
Input: 2.500 x $0,15 / 1.000.000 = $0,000375. Output: 400 x $0,50 / 1.000.000 = $0,0002. Eine Antwort kostet etwa $0,000575. Eine Community, die an einem Tag 500 Fragen stellt, gibt 500 x $0,000575 = $0,2875 aus, etwas weniger als dreißig Cent. Deine Zahlen unterscheiden sich bei längeren Code-Einfügungen, also logge resp.usage für eine Woche und lies die echten Durchschnittswerte. Die Preisseite zeigt die Auflade-Optionen: jeder ganze Betrag von $20 bis $500, mit +5% ab $50, +10% ab $100 und +15% ab $200, bezahlt mit Karte oder Krypto.
Um Missbrauch zu begrenzen, füge einen Cooldown pro Benutzer und eine Längenbegrenzung für Fragen hinzu. Diese beiden Prüfungen schützen dein Guthaben besser als alles andere, das du hinzufügen kannst.
Hosting- und Sicherheitshinweise
Der Bot ist ein langlaufender Prozess. Eine kleine virtuelle Maschine oder ein Container-Host reicht aus, da die schwere Arbeit auf der API-Seite passiert. Führe ihn unter einem Prozess-Manager aus, damit er nach einem Absturz neu startet, und halte beide Token in Umgebungsvariablen oder einem Secrets-Store, niemals im Repository.
Denke darüber nach, was dein Server erlaubt. Das Modell ist darauf abgestimmt, ohne Inhaltsablehnungen für die rechtmäßige Erwachsenennutzung zu antworten, also wird es Sicherheitstests oder grenzwertige Fiktion diskutieren, die ein strengerer Assistent ablehnen würde. Wenn deine Community jüngere Mitglieder umfasst, lege Regeln im System-Prompt fest, beschränke den Bot auf bestimmte Kanäle und denke daran, dass auch die eigenen Bedingungen von Discord für deinen Bot gelten. Inhalte, die Minderjährige sexualisieren, sind auf dieser API ohne Ausnahme verboten.
Vollständige Parameterdetails, wie stop, seed und Function Calling, findest du in den API-Dokumentationen. Wenn du möchtest, dass der Bot Code ausführt oder Repositories liest, ist Function Calling der Weg, und du entscheidest, welche Funktionen das Modell anfordern darf. Für die programmierfokussierte Nutzung dieses Modells sieh dir die Seite über das unzensierte KI-Modell für Coding an.
Weitere Anleitungen
Fragen und Antworten
Brauche ich die Message Content-Intention?
Ja, wenn der Bot normale Nachrichten und Erwähnungen liest. Wenn du nur Slash-Befehle verwendest, brauchst du sie nicht.
Kann der Bot Antworten streamen?
Ja. Setze stream=True und bearbeite die Discord-Nachricht in einem ruhigen Intervall, z. B. einmal pro Sekunde, damit du innerhalb der eigenen Grenzen von Discord bleibst.
Was passiert, wenn zu viele Leute gleichzeitig fragen?
Nach 8 parallelen Anfragen auf einem vollständigen Schlüssel gibt die API HTTP 429 mit dem Code concurrency zurück. Ein Semaphore in deinem Code stellt die zusätzlichen Fragen stattdessen in eine Warteschlange.
Merkt sich der Bot Gespräche nach einem Neustart?
Nicht mit dem hier verwendeten Dictionary. Speichere den Verlauf in SQLite oder Redis, wenn du möchtest, dass er Neustarts überlebt.
Ist der API-Schlüssel in einem Discord-Bot sicher?
Ja, wenn er auf deinem Server in einer Umgebungsvariablen bleibt. Poste ihn niemals in einem Kanal oder commite ihn in ein öffentliches Repository.
Dein Schlüssel ist nur ein Formular entfernt
Erstelle ein Konto, kopiere den Schlüssel, ändere die Basis-URL. Das ist die gesamte Einrichtung.
API-Schlüssel erhalten