Belangrijkste punten
- ChatOpenAI werkt ongewijzigd: stel base_url, api_key en model in op
uncensored. - De API ondersteunt function calling, dus bind_tools en de vooraf gebouwde agent werken beide.
- Beperk het aantal loop-iteraties en valideer tool-argumenten; open-weight models maken hier soms fouten in.
- Houd rekening met 8 gelijktijdige verzoeken op een volledige sleutel als je agents parallel uitvoert.
Wat je nodig hebt voordat je begint
Je hebt Python 3.10 of nieuwer nodig, een API-sleutel en een paar pakketten. De sleutel vind je op de API-sleutelpagina: meld je aan met Google of met e-mail en wachtwoord, en claim het $0,50 gratis proeftegoed met één klik. De proefsleutel staat 2 gelijktijdige verzoeken en 60 per minuut toe, wat genoeg is voor alles in dit artikel als je één agent tegelijk uitvoert.
pip install langchain-openai langchain-core langgraph
export API_KEY="paste-your-key-here"De API exposeert POST /v1/chat/completions en GET /v1/models. LangChain heeft alleen de eerste nodig. Het model is een enkel open-weight model dat is afgestemd op het beantwoorden zonder inhoudelijke weigeringen, voor legaal gebruik door volwassenen; het wordt gerund door een onafhankelijke provider en is niet de officiële API van een modelleverancier. De docs vermelden de headers en limieten als je ze naast je editor wilt hebben.
Hoe de onderdelen aan de API gekoppeld zijn
Het helpt om te weten wat LangChain in de datastroom doet. Een HumanMessage wordt een bericht met de rol user. Een AIMessage wordt assistant, en als het toolaanroepen bevat, verschijnen die in het assistantbericht als een tool_calls-array. Een ToolMessage krijgt de rol tool met de bijbehorende call-ID. De system prompt komt als eerste met de rol system.
Deze koppeling is belangrijk voor foutopsporing. Als een agent zich vreemd gedraagt, print je de lijst met berichten voor elke aanroep en lees je deze als een transcript. Je ziet meestal binnen een minuut waar het misgaat: een leeg toolresultaat, een call-ID die niet overeenkomt, of een geschiedenis die veel langer is geworden dan je verwachtte. Het woord agentic kan dit als magie laten lijken, maar elke stap is een gewoon chat completion-verzoek.
Stap 1: ChatOpenAI verbinden
De hele integratie bestaat uit drie argumenten. LangChain bouwt standaard verzoeken in OpenAI-stijl, dus de server kan het verschil niet zien.
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.uncensoredvideo.cc/v1",
api_key=os.environ["API_KEY"],
temperature=0.7,
max_retries=2,
)
print(llm.invoke("Name three beats of a heist scene, one line each.").content)Als dit drie regels afdrukt, werkt de infrastructuur. Als je een 401-fout krijgt, controleer dan de sleutel. Als je een 404-fout krijgt, controleer dan of de URL eindigt op /v1 en geen extra pad bevat. max_retries is een clientoptie, en het helpt bij de tijdelijke 429-fouten die Retry-After: 5 bevatten.
Streaming werkt op dezelfde manier als bij elk OpenAI-model: je roept llm.stream(...) aan en itereert. Het laatste chunk bevat de usage-informatie, zodat je het tokenaantal per aanroep kunt loggen.
Stap 2: Tools definiëren
Een agent is een loop: het model leest het gesprek, antwoordt of vraagt om een tool, jouw code voert de tool uit en het resultaat gaat terug naar het model. De tools hieronder zijn gewone Python-functies. Ze zijn bewust saai, omdat het doel is om de werking te zien.
from langchain_core.tools import tool
@tool
def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
@tool
def spoken_minutes(words: int, words_per_minute: int = 150) -> float:
"""Estimate how many minutes a script takes to read aloud."""
return round(words / words_per_minute, 2)
tools = [word_count, spoken_minutes]De docstring en de type hints worden de toolbeschrijving en het schema die het model ziet. Schrijf ze alsof je een collega briefet. Een vage docstring is de meest voorkomende reden dat een agent de verkeerde tool kiest. Als je scripts voor video schrijft, schaalt dit patroon naar tools die shotlijsten opzoeken of een lengtebudget controleren, een onderwerp dat wordt behandeld op de Sora 2 script generator pagina.
Stap 3: De agentlus met de hand draaien
De vooraf gebouwde helpers verbergen de loop. Het een keer zelf schrijven maakt elke latere bug makkelijker te vinden.
from langchain_core.messages import HumanMessage, ToolMessage
by_name = {t.name: t for t in tools}
llm_tools = llm.bind_tools(tools)
messages = [HumanMessage(
"Here is a draft: 'The vault door hums. Nina counts to three, "
"then cuts the power.' How many words is it, and how long is it read aloud?"
)]
for step in range(6):
ai = llm_tools.invoke(messages)
messages.append(ai)
if not ai.tool_calls:
break
for call in ai.tool_calls:
result = by_name[call["name"]].invoke(call["args"])
messages.append(ToolMessage(content=str(result), tool_call_id=call["id"]))
print(messages[-1].content)Drie details zijn belangrijk. De range(6)-limiet stopt een verward model dat eindeloos blijft lussen, en beperkt ook je uitgaven. De tool_call_id moet overeenkomen met de aanroep die het beantwoordt. En het model kan meerdere tools in één antwoord aanvragen, vandaar dat de binnenste lus een lijst verwerkt.
Onder de motorkap bevat het verzoek een tools-array en bevat het antwoord tool_calls, waarbij resultaten worden teruggegeven als berichten met role: "tool". Je kunt een specifieke tool forceren met tool_choice, wat LangChain beschikbaar maakt als argument van bind_tools.
Stap 4: De vooraf gebouwde LangGraph-agent gebruiken
Zodra de handmatige loop duidelijk is, bespaart de vooraf gebouwde agent regels. Hij gebruikt hetzelfde model en dezelfde tools.
import os
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.uncensoredvideo.cc/v1",
api_key=os.environ["API_KEY"],
)
agent = create_react_agent(llm, tools)
out = agent.invoke({"messages": [("user", "How long is a 450 word script read aloud?")]})
print(out["messages"][-1].content)LangChain en LangGraph veranderen hun APIs tussen releases, en sommige helpers zijn hernoemd of verplaatst. Als een import faalt, controleer dan de huidige LangChain-documentatie voor de equivalente agent constructor. Het verbindingsdeel, ChatOpenAI met een base URL, blijft hetzelfde.
Kiezen tussen een loop en een graph
De handgeschreven loop is genoeg voor agents die kiezen uit een paar tools en stoppen. Het is makkelijk te lezen, makkelijk te loggen en heeft geen verrassingen van het framework. Stap over op LangGraph als je vertakkingen nodig hebt die van de status afhangen: een reviewstap die werk terugstuurt voor een nieuwe ronde, een menselijke goedkeuring voordat een riskante tool draait, of meerdere gespecialiseerde sub-agents die resultaten aan elkaar doorgeven.
Wat je ook kiest, houd elke node klein en geef hem één taak. Een planningsnode die een korte genummerde lijst als JSON uitvoert, een uitvoeringsnode die tools draait en een schrijfnode die de eindtekst produceert, zijn makkelijker te testen dan één enorme prompt. Ze laten je ook verschillende temperaturen gebruiken: laag voor planning en toolgebruik, hoger voor de schrijfstap. Omdat elke node een normale chat completion call is, dienen dezelfde sleutel, URL en modelnaam ze allemaal, en de kosten zijn simpelweg de som van de calls.
Een laatste gewoonte: print het lopende totaal aan tokens. Agents die goedkoop lijken in een demo kunnen tien keer meer uitgeven aan een rommelige echte taak, en de gebruikscijfers bij elk antwoord maken dat zichtbaar bij de eerste run, voordat het een verrassing op je saldo wordt.
Geheugen, testen en gestructureerde uitvoer
De loop hierboven vergeet alles als het script eindigt. Het eenvoudigste geheugen is de berichtenlijst zelf: bewaar die tussen gebruikersbeurten, voeg elke nieuwe vraag toe en knip de oudste berichten weg als de lijst lang wordt. Voor lange sessies vervang je oude berichten door een korte samenvatting geschreven door het model. Omdat invoer per token wordt gefactureerd, wint een samenvatting van 500 tokens het van 20.000 tokens aan ruwe geschiedenis, zowel qua kosten als qua focus.
Agents testen is vooral gedrag controleren dat je kunt observeren. Stel temperature in op 0 of geef een vaste seed door, die de API doorgeeft, zodat runs beter herhaalbaar zijn. Schrijf dan een handvol vragen waar je weet welke tool moet worden aangeroepen, en controleer (assert) de toolnamen en argumenten in de berichtenlijst, niet de exacte formulering van het antwoord. Voer deze uit na elke wijziging in een prompt of een toolbeschrijving. Een docstring wijzigen kan veranderen welke tool het model kiest, en een test is de goedkoopste manier om dat op te merken.
Log drie dingen bij elke run: het aantal stappen, de toolaanroepen met hun argumenten en het tokengebruik. Als een run misgaat, vertellen die drie regels je of het model slecht koos, een tool faalde, of de loop zonder stappen kwam te zitten.
Gestructureerde uitvoer en JSON-modus
Agents moeten vaak gegevens teruggeven, geen lopende tekst. De API ondersteunt de JSON-modus via response_format: {"type":"json_object"}. In LangChain kun je erom vragen met llm.bind(response_format={"type": "json_object"}). Vertel het model in de prompt dat het antwoord een JSON-object moet zijn en noem de sleutels die je verwacht, parseer dan de string en valideer die met Pydantic. Vertrouw er niet op dat de parseerstap altijd slaagt; verpak die in een retry die de foutmelding één keer terugstuurt naar het model.
Valkuilen en hoe ze op te lossen
- Slechte toolargumenten. Een open-weight model stuurt soms een string waar je een integer hebt gedeclareerd. Valideer argumenten, geef een korte foutmelding terug vanuit de tool, en laat het model zichzelf corrigeren in de volgende stap.
- Op hol geslagen loops. Beperk altijd iteraties. Log elke stap terwijl je ontwikkelt.
- Parallelle agents. Een volledige sleutel staat 8 gelijktijdige verzoeken toe. Als je een batch draait, stel dan
config={"max_concurrency": 4}in opllm.batchom ruimte over te laten. Het overschrijden van de limiet retourneert 429 met de codeconcurrency; het overschrijden van 300 verzoeken per minuut retourneertrate_limited. - Streaming plus tools. Een gestreamd verzoek houdt zijn concurrency-slot vast tot de stream eindigt, dus start geen nieuwe aanroepen vanuit een stream-handler met een proefsleutel.
- Groeiende geschiedenis. Elke stap stuurt de volledige berichtenlijst opnieuw mee. Het contextvenster is 100.000 tokens, maar je betaalt voor invoer bij elke aanroep.
Wat een agentrun kost
Neem een bescheiden agent die 4 model calls maakt om een taak te voltooien, met een gemiddelde prompt van 3.000 tokens en 200 output tokens per call. Invoer: 4 x 3.000 = 12.000 tokens, wat 12.000 x $0,15 / 1.000.000 = $0,0018 is. Uitvoer: 4 x 200 = 800 tokens, wat $0,0004 is. Eén run kost $0,0022, dus 1.000 runs kosten $2,20. Het $0,50 gratis proeftegoed dekt ongeveer 227 dergelijke runs. Mislukte of geweigerde verzoeken worden niet gefactureerd en tegoed vervalt nooit. Zie de prijzen voor opwaardeerbedragen en bonussen. Deze site accepteert alleen crypto, USDT op TRC20 of USDC op Base.
