Bouw een chatbot met een LLM-API: Python-tutorial
Abliterated-modellen zijn grote taalmodellen waarbij de mechanismen voor veiligheidsafwijzingen zijn verwijderd, waardoor het model controversiële, volwassen of niche-vragen kan beantwoorden zonder tegen een inhoudsfilter aan te lopen. Deze aanpak geeft ontwikkelaars volledige controle over de stem en de kennisafsnijding van het model, wat vooral waardevol is voor coderen, rollenspellen en creatief schrijven waar standaardbeveiligingsmaatregelen nuttige output kunnen blokkeren.
Bijgewerkt

Belangrijkste punten
- De API is stateless, dus jouw code beheert de gespreksgeschiedenis en stuurt die bij elk verzoek mee.
- Streaming, toolaanroepen en JSON-modus gebruiken allemaal de standaard OpenAI-parameters.
- Trim of vat de geschiedenis samen voordat deze het contextvenster van 100.000 tokens nadert.
- 1.000 chats van 2.000 invoer- en 400 uitvoertokens kosten ongeveer $0,50.
Het kernidee: een chatbot is een lus en een lijst
Een taalmodel onthoudt niets tussen verzoeken in. Elke aanroep van POST /v1/chat/completions is onafhankelijk. Wat als geheugen voelt, is jouw programma dat de eerdere berichten opnieuw verstuurt, elk gemarkeerd met een rol: system voor vaste instructies, user voor wat de gebruiker typte, assistant voor eerdere modelantwoorden.
De hele architectuur is dus klein. Houd een lijst bij. Voeg het bericht van de gebruiker toe. Stuur de lijst. Voeg het antwoord toe. Herhaal. Alles in deze tutorial, van streaming tot tools, is een variatie op die lus.
De API hier is OpenAI-compatibel, dus je gebruikt het reguliere openai-pakket. Stel de base URL in op https://api.abliterated.cc/v1, gebruik je sleutel en stel het model in op uncensored. Haal een sleutel op van de API-sleutelpagina; het proeftegoed van $0,50 is genoeg voor honderden korte testberichten.
Stap 1: een werkende console-chatbot
Installeer de SDK met pip install openai en voer dit uit.
from openai import OpenAI
client = OpenAI(
base_url="https://api.abliterated.cc/v1",
api_key="YOUR_KEY",
)
messages = [
{"role": "system", "content": "You are a concise, friendly support assistant for a bike shop."}
]
while True:
text = input("you: ")
if text.strip() in {"quit", "exit"}:
break
messages.append({"role": "user", "content": text})
resp = client.chat.completions.create(
model="uncensored",
messages=messages,
temperature=0.7,
)
answer = resp.choices[0].message.content
messages.append({"role": "assistant", "content": answer})
print("bot:", answer)
Dit is een complete chatbot. Het systeembericht definieert de taak, de lijst bevat het geheugen, en temperature bepaalt hoe gevarieerd de antwoorden zijn. Zet deze lager naar 0,2 voor feitelijke supportbots, en hoger naar 1,0 voor creatieve bots.
Schrijf een systeemprompt die de taak definieert
Het systeembericht is de goedkoopste plek om een chatbot te verbeteren. Houd het kort en specifiek. Noem de rol, het publiek, de lengte en toon van antwoorden, en wat de bot moet doen als hij het niet weet. Een prompt zoals "Je beantwoordt vragen voor een fietsenwinkel. Antwoord in maximaal drie zinnen. Als de vraag over reparatiekosten gaat, zeg dan dat een monteur de fiets moet inspecteren" doet meer dan een pagina algemene deugden.
Twee gewoontes betalen zich uit. Zet regels eerst in de vorm van acties, niet in houdingen: "stel één verduidelijkende vraag wanneer het verzoek ambigu is" in plaats van "wees behulpzaam". Test daarna met vijandige invoer, zoals een leeg bericht, een zeer lange geplakte tekst en een verzoek dat niets met jouw product te maken heeft. Pas de prompt aan op basis van wat je ziet, en bewaar die invoeren als regressielijst.
Omdat het systeembericht bij elke beurt opnieuw wordt verstuurd, wordt elk woord erin bij elk verzoek gefactureerd. Een prompt van 400 tokens over 1.000 chats van 5 beurten elk voegt 2.000.000 invoertokens toe, oftewel 2 x $0,15 = $0,30. Dat is weinig, maar het laat zien waarom uitgebreide prompts oplopen bij hoog volume.
Stap 2: stream het antwoord
Wachten op een volledig antwoord voelt traag in een chatvenster. Stel stream: true in en print stukken naarmate ze binnenkomen. De stream gebruikt server-sent events en eindigt met een usage-blok, zodat je tokenaantallen kunt loggen.
from openai import OpenAI
client = OpenAI(base_url="https://api.abliterated.cc/v1", api_key="YOUR_KEY")
messages = [{"role": "user", "content": "Explain tire pressure in two sentences."}]
stream = client.chat.completions.create(
model="uncensored",
messages=messages,
stream=True,
)
reply = ""
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
part = chunk.choices[0].delta.content
reply += part
print(part, end="", flush=True)
if getattr(chunk, "usage", None):
print("\ntokens:", chunk.usage.prompt_tokens, chunk.usage.completion_tokens)
Vergeet niet de samengestelde reply aan je geschiedenis toe te voegen, anders weet de volgende beurt niet wat de bot zei.
Stap 3: beheer context voordat deze groeit
Het contextvenster is 100.000 tokens, gedeeld tussen prompt en completion. De meeste chatbots komen dit nooit dichtbij, maar de kosten stijgen met de geschiedenis omdat je betaalt voor de hele prompt bij elke beurt. Een eenvoudig beleid houdt beide onder controle:
- Behoud altijd het systeembericht.
- Behoud de laatste 10 tot 20 berichten letterlijk.
- Wanneer de lijst een door jou gekozen groottelimiet overschrijdt, zoals 8.000 geschatte tokens, stuur dan het oudste blok naar het model met de instructie "vat deze conversatie samen in minder dan 150 woorden", en vervang dat blok door de samenvatting als systeembericht.
Een ruwe schatting van één token per vier Engelse tekens is genoeg voor de trigger. De usage-getallen in elk antwoord geven je de exacte cijfer achteraf, zodat je de limiet kunt afstellen.
Als je inkort door de oudste berichten te verwijderen, verwijder ze dan in user- en assistant-paren. Een antwoord zonder vraag, of een vraag zonder antwoord, brengt het model meer in de war dan je zou verwachten.
Stap 4: geef de bot tools
Tool calling stelt het model in staat je code iets te laten doen, zoals een bestelling opzoeken. Je beschrijft functies met tools, het model antwoordt met een tool_calls-entry, je voert de functie uit en je stuurt het resultaat terug als een role: "tool"-bericht.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.abliterated.cc/v1", api_key="YOUR_KEY")
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up the status of an order by its id",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}]
def get_order_status(order_id):
return {"order_id": order_id, "status": "shipped"}
messages = [{"role": "user", "content": "Where is order A1042?"}]
resp = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = resp.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_order_status(**args)
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)
Valideer altijd de argumenten voordat je iets met neveneffecten uitvoert. Het model stelt een aanroep voor; jouw code beslist of deze wordt uitgevoerd.
Stap 5: gestructureerde uitvoer met JSON-modus
Wanneer de volgende stap in jouw programma data nodig heeft in plaats van tekst, zoals het sorteren van een bericht in een categorie, gebruik dan JSON-modus met response_format. Noem het woord JSON en de verwachte keys in je prompt ook.
curl https://api.abliterated.cc/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"response_format": {"type": "json_object"},
"messages": [
{"role": "system", "content": "Reply with JSON: {\"intent\": string, \"urgent\": boolean}"},
{"role": "user", "content": "My brakes squeal and I ride tomorrow morning."}
]
}'
Wikkel json.loads nog steeds in een try-blok. Als parseren faalt, probeer het één keer opnieuw met de fouttekst erachter; mislukte verzoeken worden niet gefactureerd.
Fouten, kosten en implementatietips
Verwerk fouten, retries en rate limits
Echte gebruikers sturen verzoeken op ongelegen momenten, en netwerken falen. Verpak de aanroep zodat één slecht antwoord de conversatie niet laat crashen.
import time
from openai import OpenAI, APIError, RateLimitError
client = OpenAI(base_url="https://api.abliterated.cc/v1", api_key="YOUR_KEY")
def chat(messages, tries=3):
for attempt in range(tries):
try:
resp = client.chat.completions.create(
model="uncensored", messages=messages, temperature=0.7
)
return resp.choices[0].message.content
except RateLimitError:
time.sleep(2 ** attempt)
except APIError as exc:
if attempt == tries - 1:
raise
time.sleep(1)
return "Sorry, the assistant is busy. Please try again in a moment."
Een volledige sleutel staat 8 gelijktijdige verzoeken en 300 verzoeken per minuut toe; de proefsleutel staat 2 en 60 toe. Als je bot veel gebruikers tegelijk bedient, zet verzoeken dan in een wachtrij met een worker-limiet onder de 8 in plaats van te vertrouwen op retries. Omdat mislukte verzoeken niet worden gefactureerd, heeft retryen geen tokenkosten. Houd het retry-aantal klein zodat een echte uitval snel faalt.
Log ook de X-Request-Id-header bij elke conversatiebeurt. Als een antwoord er vreemd uitziet, kun je met de id het exacte verzoek later terugvinden.
Kosten en implementatie
De prijs is $0,15 per 1M invoertokens en $0,50 per 1M uitvoertokens. Stel een supportchat gebruikt in totaal 2.000 invoertokens en 400 uitvoertokens.
- Invoer: 0,002M x $0,15 = $0,0003
- Uitvoer: 0,0004M x $0,50 = $0,0002
- Eén chat: $0,0005, dus 1.000 chats kosten $0,50
Bekijk de huidige tarieven en top-up bonussen op de prijzenpagina. Houd voor productie de sleutel op je server, nooit in browsercode, en let op de X-Balance-USD response header om jezelf te waarschuwen voordat je tegoed op is. Een volledige sleutel staat 8 gelijktijdige verzoeken en 300 verzoeken per minuut toe, dus zet pieken in een wachtrij in plaats van ze allemaal tegelijk af te vuren. De docs vermelden elke ondersteunde parameter.
Meer handleidingen
Vragen en antwoorden
Heb je een framework nodig om een chatbot te bouwen?
Nee. De OpenAI SDK en een berichtlijst zijn genoeg voor een werkende bot. Voeg later pas een framework toe als je de extra's nodig hebt.
Onthoudt de API eerdere berichten?
Nee. Elk verzoek is onafhankelijk, dus je code moet de geschiedenis elke keer opnieuw versturen.
Hoe voorkom ik dat de geschiedenis te lang wordt?
Bewaar het systeembericht en recente beurten, en vat oudere beurten samen tot een korte notitie zodra de lijst een door jou ingestelde grootte overschrijdt.
Kan de bot mijn eigen functies aanroepen?
Ja. Stuur tools en tool_choice, voer de functie uit wanneer het antwoord tool_calls bevat, en retourneer het resultaat als een tool-bericht.
Je sleutel is nog maar één formulier verwijderd
Maak een account aan, kopieer de sleutel, pas de base URL aan. Dat is de hele setup.