Skip to navigation

Integreer je eigen model

Koppel een agent aan je eigen LLM of host je eigen server.

Met Custom LLM kun je je gesprekken via een extern endpoint koppelen aan je eigen LLM. ElevenLabs ondersteunt ook native geïntegreerde LLM’s

Met aangepaste LLM’s kun je je eigen OpenAI API-sleutel gebruiken of een volledig aangepaste LLM-server uitvoeren.

Overzicht

Standaard gebruiken we onze eigen interne gegevens voor populaire modellen zoals OpenAI. Om een aangepaste LLM-server te gebruiken, moet deze overeenkomen met een van de volgende OpenAI-compatibele request/response-structuren:

De Responses API is de nieuwere API-indeling van OpenAI en ondersteunt extra functies. Beide API-indelingen worden volledig ondersteund voor aangepaste LLM-integratie.

De volgende handleidingen behandelen beide gebruiksscenario’s:

  1. Gebruik je eigen OpenAI-sleutel: Gebruik je eigen OpenAI API-sleutel met ons platform.
  2. Aangepaste LLM-server: Host en koppel je eigen LLM-serverimplementatie.

Je leert hoe je:

  • Je OpenAI API-sleutel opslaat in ElevenLabs
  • Een server host die het Chat Completions- of Responses-endpoint van OpenAI nabootst
  • ElevenLabs naar je aangepaste endpoint verwijst
  • Indien nodig extra parameters doorgeeft aan je LLM

Samenvatting van de redenering

Je endpoint moet de redenering afzonderlijk van het definitieve antwoord teruggeven. ElevenLabs genereert geen redenering op basis van het definitieve antwoord.

Om redenering op te vragen bij een ondersteund endpoint, schakel je Reasoning summary in bij de LLM-instellingen van de agent of stel je enable_reasoning_summary in via de API.

Redenering teruggeven

Gebruik de indeling die bij je endpoint past:

Stream redenering in het veld reasoning of reasoning_content van elke response-delta.

Voor Gemini-compatibele endpoints vraagt ElevenLabs gedachten op met google.thinking_config.include_thoughts en leest het content die is gemarkeerd met extra_content.google.thought.

Zie Reasoning summary voor opslag, levering en beperkingen.

Je eigen OpenAI-sleutel gebruiken

Om een aangepaste OpenAI-sleutel te integreren, werk je de instellingen van je agent in het ElevenLabs-dashboard bij zodat deze naar je aangepaste LLM-server verwijzen, en maak je een geheim met je OPENAI_API_KEY:

1

Selecteer in de agentinstellingen in het ElevenLabs-dashboard “Custom LLM” in het dropdownmenu “LLM” aan de rechterkant.

Geheim toevoegen

2

Klik op het veld onder “LLM” en scrol omlaag om “Custom LLM” te selecteren.

3

Voer de server-URL en de model-ID van je aangepaste LLM-server in.

URL invoeren

4

Klik op het dropdownmenu onder “API key” en selecteer “Create new secret”. Geef de sleutel de naam OPENAI_API_KEY, voeg de sleutel toe aan het veld “value” en klik op “Add secret”.

5

Klik op de knop “x” om het LLM-venster te sluiten en klik op “Publish” om je wijzigingen op te slaan.

Aangepaste LLM-server

Om een aangepaste LLM-server te gebruiken, stel je een compatibel server-endpoint in volgens de stijl van OpenAI. Je kunt de Chat Completions API (/v1/chat/completions) of de Responses API (/v1/responses) implementeren.

Beide endpoints moeten responses retourneren in SSE-indeling (Server-Sent Events) met Content-Type: text/event-stream.

De Chat Completions API gebruikt het endpoint /v1/chat/completions.

Elk chunk moet de indeling data: {json}\n\n hebben en de stream moet eindigen met data: [DONE]\n\n.

Hier is een voorbeeld van een serverimplementatie:

import json
import os
import fastapi
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
import uvicorn
import logging
from dotenv import load_dotenv
from pydantic import BaseModel
from typing import List, Optional
# Load environment variables from .env file
load_dotenv()
# Retrieve API key from environment
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
if not OPENAI_API_KEY:
raise ValueError("OPENAI_API_KEY not found in environment variables")
app = fastapi.FastAPI()
oai_client = AsyncOpenAI(api_key=OPENAI_API_KEY)
class Message(BaseModel):
role: str
content: str
class ChatCompletionRequest(BaseModel):
messages: List[Message]
model: str
temperature: Optional[float] = 0.7
max_tokens: Optional[int] = None
stream: Optional[bool] = False
user_id: Optional[str] = None
@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest) -> StreamingResponse:
oai_request = request.dict(exclude_none=True)
if "user_id" in oai_request:
oai_request["user"] = oai_request.pop("user_id")
chat_completion_coroutine = await oai_client.chat.completions.create(**oai_request)
async def event_stream():
try:
async for chunk in chat_completion_coroutine:
# Convert the ChatCompletionChunk to a dictionary before JSON serialization
chunk_dict = chunk.model_dump()
yield f"data: {json.dumps(chunk_dict)}\n\n"
yield "data: [DONE]\n\n"
except Exception as e:
logging.error("An error occurred: %s", str(e))
yield f"data: {json.dumps({'error': 'Internal error occurred!'})}\n\n"
return StreamingResponse(event_stream(), media_type="text/event-stream")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8013)

Voer deze code of je eigen servercode uit.

Een openbare URL instellen voor je server

Maak je server toegankelijk door een openbare URL te maken met een tunnelingtool zoals ngrok:

ngrok http --url=<Your url>.ngrok.app 8013

ElevenLabs CustomLLM configureren

Werk vervolgens de instellingen van je agent in het ElevenLabs-dashboard bij zodat deze naar je aangepaste LLM-server verwijzen.

Verwijs je server-URL naar het ngrok-endpoint en stel “Limit token usage” in op 5000.

Je kunt nu met je agent en je eigen LLM-server communiceren.

Optimaliseren voor LLM’s met trage verwerking

Als je aangepaste LLM trage verwerkingstijden heeft (bijvoorbeeld vanwege agentische redenering of vereisten voor voorverwerking), kun je de gespreksflow verbeteren door bufferwoorden te implementeren in je streaming responses. Deze techniek helpt de natuurlijke spraakprosodie te behouden terwijl je LLM de volledige response genereert.

Bufferwoorden

Wanneer je LLM meer tijd nodig heeft om de volledige response te verwerken, geef je een eerste response terug die eindigt op "... " (beletselteken gevolgd door een spatie). Hierdoor kan het Text to Speech-systeem een natuurlijke flow behouden, terwijl het gesprek dynamisch blijft aanvoelen. Dit creëert natuurlijke pauzes die goed overgaan in volgende content waarover het LLM langer kan redeneren. De extra spatie is cruciaal om te voorkomen dat de volgende content aan de ”…” wordt toegevoegd, wat tot audiovervormingen kan leiden.

Implementatie

Zo pas je je aangepaste LLM-server aan om bufferwoorden te implementeren:

@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest) -> StreamingResponse:
oai_request = request.dict(exclude_none=True)
if "user_id" in oai_request:
oai_request["user"] = oai_request.pop("user_id")
async def event_stream():
try:
# Send initial buffer chunk while processing
initial_chunk = {
"id": "chatcmpl-buffer",
"object": "chat.completion.chunk",
"created": 1234567890,
"model": request.model,
"choices": [{
"delta": {"content": "Let me think about that... "},
"index": 0,
"finish_reason": None
}]
}
yield f"data: {json.dumps(initial_chunk)}\n\n"
# Process the actual LLM response
chat_completion_coroutine = await oai_client.chat.completions.create(**oai_request)
async for chunk in chat_completion_coroutine:
chunk_dict = chunk.model_dump()
yield f"data: {json.dumps(chunk_dict)}\n\n"
yield "data: [DONE]\n\n"
except Exception as e:
logging.error("An error occurred: %s", str(e))
yield f"data: {json.dumps({'error': 'Internal error occurred!'})}\n\n"
return StreamingResponse(event_stream(), media_type="text/event-stream")

Integratie van systeemtools

Je aangepaste LLM kan systeemtools activeren om de gespreksflow en -status te beheren. Deze tools worden automatisch opgenomen in de parameter tools van je chat-completion-requests wanneer ze zijn geconfigureerd in je agent.

Zo werken systeemtools

  1. LLM-beslissing: Je aangepaste LLM bepaalt op basis van de gesprekscontext wanneer deze tools moeten worden aangeroepen
  2. Toolresponse: Het LLM antwoordt met functieaanroepen in de standaardindeling van OpenAI
  3. Backendverwerking: ElevenLabs verwerkt de toolaanroepen en werkt de gespreksstatus bij

Zie voor meer informatie over systeemtools onze handleiding

Beschikbare systeemtools

Doel: Gesprekken automatisch beëindigen wanneer aan de juiste voorwaarden is voldaan.

Triggervoorwaarden: Het LLM moet deze tool aanroepen wanneer:

  • De hoofdtaak is voltooid en de gebruiker tevreden is
  • Het gesprek met wederzijdse instemming tot een natuurlijk einde is gekomen
  • De gebruiker expliciet aangeeft het gesprek te willen beëindigen

Parameters:

  • reason (string, vereist): De reden voor het beëindigen van het gesprek
  • message (string, optioneel): Een afscheidsbericht dat vóór het beëindigen van het gesprek naar de gebruiker wordt gestuurd

Indeling van functieaanroep:

{
"type": "function",
"function": {
"name": "end_call",
"arguments": "{\"reason\": \"Task completed successfully\", \"message\": \"Thank you for using our service. Have a great day!\"}"
}
}

Implementatie: Configureer dit als systeemtool in je agentinstellingen. Het LLM ontvangt gedetailleerde instructies over wanneer deze functie moet worden aangeroepen.

Meer informatie: Tool voor gesprek beëindigen

Doel: Tijdens gesprekken automatisch overschakelen naar de gedetecteerde taal van de gebruiker.

Triggervoorwaarden: Het LLM moet deze tool aanroepen wanneer:

  • De gebruiker een andere taal spreekt dan de huidige gesprekstaal
  • De gebruiker expliciet vraagt om van taal te wisselen
  • Ondersteuning voor meerdere talen nodig is voor het gesprek

Parameters:

  • reason (string, vereist): De reden voor de taalwissel
  • language (string, vereist): De taalcode waarnaar moet worden gewisseld (moet in de lijst met ondersteunde talen staan)

Indeling van functieaanroep:

{
"type": "function",
"function": {
"name": "language_detection",
"arguments": "{\"reason\": \"User requested Spanish\", \"language\": \"es\"}"
}
}

Implementatie: Configureer ondersteunde talen in de agentinstellingen en voeg de systeemtool voor taaldetectie toe. De agent wisselt automatisch van stem en responses om overeen te komen met gedetecteerde talen.

Meer informatie: Tool voor taaldetectie

Doel: Gesprekken op basis van gebruikersbehoeften overdragen tussen gespecialiseerde AI-agents.

Triggervoorwaarden: Het LLM moet deze tool aanroepen wanneer:

  • Het verzoek van de gebruiker gespecialiseerde kennis of andere agentmogelijkheden vereist
  • De huidige agent de vraag niet adequaat kan afhandelen
  • De gespreksflow aangeeft dat een ander type agent nodig is

Parameters:

  • reason (string, optioneel): De reden voor de agentoverdracht
  • agent_number (integer, vereist): Het nummer vanaf nul van de agent waarnaar moet worden overgedragen (op basis van geconfigureerde overdrachtsregels)

Indeling van functieaanroep:

{
"type": "function",
"function": {
"name": "transfer_to_agent",
"arguments": "{\"reason\": \"User needs billing support\", \"agent_number\": 0}"
}
}

Implementatie: Definieer overdrachtsregels die voorwaarden toewijzen aan specifieke agent-ID’s. Configureer naar welke agents de huidige agent kan overdragen. Agents worden met nummers vanaf nul aangeduid in de overdrachtsconfiguratie.

Meer informatie: Tool voor agentoverdracht

Doel: Gesprekken naadloos doorgeven aan menselijke medewerkers wanneer AI-ondersteuning onvoldoende is.

Triggervoorwaarden: Het LLM moet deze tool aanroepen wanneer:

  • Er complexe problemen zijn die menselijk oordeel vereisen
  • De gebruiker expliciet om menselijke hulp vraagt
  • AI de grenzen van zijn mogelijkheden bereikt voor het specifieke verzoek
  • Escalatieprotocollen worden geactiveerd

Parameters:

  • reason (string, optioneel): De reden voor de overdracht
  • transfer_number (string, vereist): Het telefoonnummer waarnaar moet worden overgedragen (moet overeenkomen met geconfigureerde nummers)
  • client_message (string, vereist): Bericht dat aan de klant wordt voorgelezen tijdens het wachten op overdracht
  • agent_message (string, vereist): Bericht voor de menselijke medewerker die het gesprek ontvangt

Indeling van functieaanroep:

{
"type": "function",
"function": {
"name": "transfer_to_number",
"arguments": "{\"reason\": \"Complex billing issue\", \"transfer_number\": \"+15551234567\", \"client_message\": \"I'm transferring you to a billing specialist who can help with your account.\", \"agent_message\": \"Customer has a complex billing dispute about order #12345 from last month.\"}"
}
}

Implementatie: Configureer telefoonnummers en voorwaarden voor overdracht. Definieer berichten voor zowel de klant als de ontvangende menselijke medewerker. Werkt met zowel Twilio als SIP-trunking.

Meer informatie: Tool voor overdracht aan een persoon

Doel: De agent laten pauzeren en wachten op gebruikersinvoer zonder te spreken.

Triggervoorwaarden: Het LLM moet deze tool aanroepen wanneer:

  • De gebruiker aangeeft even tijd nodig te hebben (“Geef me een moment”, “Even nadenken”)
  • De gebruiker vraagt om een pauze in de gespreksflow
  • De agent detecteert dat de gebruiker tijd nodig heeft om informatie te verwerken

Parameters:

  • reason (string, optioneel): Vrije tekst die uitlegt waarom de pauze nodig is

Indeling van functieaanroep:

{
"type": "function",
"function": {
"name": "skip_turn",
"arguments": "{\"reason\": \"User requested time to think\"}"
}
}

Implementatie: Geen extra configuratie nodig. De tool geeft de agent simpelweg het signaal om stil te blijven totdat de gebruiker opnieuw spreekt.

Meer informatie: Tool voor beurt overslaan

Parameters:

  • reason (string, verplicht): De reden voor het detecteren van voicemail (bijvoorbeeld “geautomatiseerde begroeting gedetecteerd”, “geen menselijke reactie”)

Indeling van functieaanroep:

{
"type": "function",
"function": {
"name": "voicemail_detection",
"arguments": "{\"reason\": \"Automated greeting detected with request to leave message\"}"
}
}

Meer informatie: Tool voor voicemaildetectie

Voorbeeldrequest met systeemtools

Wanneer systeemtools zijn geconfigureerd, ontvangt je aangepaste LLM requests waarin de tools zijn opgenomen in de standaardindeling van OpenAI:

{
"messages": [
{
"role": "system",
"content": "You are a helpful assistant. You have access to system tools for managing conversations."
},
{
"role": "user",
"content": "I think we're done here, thanks for your help!"
}
],
"model": "your-custom-model",
"temperature": 0.7,
"max_tokens": 1000,
"stream": true,
"tools": [
{
"type": "function",
"function": {
"name": "end_call",
"description": "Call this function to end the current conversation when the main task has been completed...",
"parameters": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "The reason for the tool call."
},
"message": {
"type": "string",
"description": "A farewell message to send to the user along right before ending the call."
}
},
"required": ["reason"]
}
}
},
{
"type": "function",
"function": {
"name": "language_detection",
"description": "Change the conversation language when the user expresses a language preference explicitly...",
"parameters": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "The reason for the tool call."
},
"language": {
"type": "string",
"description": "The language to switch to. Must be one of language codes in tool description."
}
},
"required": ["reason", "language"]
}
}
},
{
"type": "function",
"function": {
"name": "skip_turn",
"description": "Skip a turn when the user explicitly indicates they need a moment to think...",
"parameters": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Optional free-form reason explaining why the pause is needed."
}
},
"required": []
}
}
}
]
}

Je aangepaste LLM moet function calling ondersteunen om systeemtools te gebruiken. Zorg dat je model correcte responses voor functieaanroepen in OpenAI-indeling kan genereren.

Extra functies

Je kunt aanvullende parameters doorgeven aan je aangepaste LLM-implementatie.

1

De extra parameters definiëren

Maak een object met je aangepaste parameters:

from elevenlabs.conversational_ai.conversation import Conversation, ConversationInitiationData
extra_body_for_convai = {
"UUID": "123e4567-e89b-12d3-a456-426614174000",
"parameter-1": "value-1",
"parameter-2": "value-2",
}
config = ConversationInitiationData(
extra_body=extra_body_for_convai,
)
2

De LLM-implementatie bijwerken

Pas je aangepaste LLM-code aan om de aanvullende parameters te verwerken:

import json
import os
import fastapi
from fastapi.responses import StreamingResponse
from fastapi import Request
from openai import AsyncOpenAI
import uvicorn
import logging
from dotenv import load_dotenv
from pydantic import BaseModel
from typing import List, Optional
# Load environment variables from .env file
load_dotenv()
# Retrieve API key from environment
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
if not OPENAI_API_KEY:
raise ValueError("OPENAI_API_KEY not found in environment variables")
app = fastapi.FastAPI()
oai_client = AsyncOpenAI(api_key=OPENAI_API_KEY)
class Message(BaseModel):
role: str
content: str
class ChatCompletionRequest(BaseModel):
messages: List[Message]
model: str
temperature: Optional[float] = 0.7
max_tokens: Optional[int] = None
stream: Optional[bool] = False
user_id: Optional[str] = None
elevenlabs_extra_body: Optional[dict] = None
@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest) -> StreamingResponse:
oai_request = request.dict(exclude_none=True)
print(oai_request)
if "user_id" in oai_request:
oai_request["user"] = oai_request.pop("user_id")
if "elevenlabs_extra_body" in oai_request:
oai_request.pop("elevenlabs_extra_body")
chat_completion_coroutine = await oai_client.chat.completions.create(**oai_request)
async def event_stream():
try:
async for chunk in chat_completion_coroutine:
chunk_dict = chunk.model_dump()
yield f"data: {json.dumps(chunk_dict)}\n\n"
yield "data: [DONE]\n\n"
except Exception as e:
logging.error("An error occurred: %s", str(e))
yield f"data: {json.dumps({'error': 'Internal error occurred!'})}\n\n"
return StreamingResponse(event_stream(), media_type="text/event-stream")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8013)

Voorbeeldrequest

Met deze aangepaste berichtconfiguratie ontvangt je LLM requests in deze indeling:

{
"messages": [
{
"role": "system",
"content": "\n <Redacted>"
},
{
"role": "assistant",
"content": "Hey I'm currently unavailable."
},
{
"role": "user",
"content": "Hey, who are you?"
}
],
"model": "gpt-4o",
"temperature": 0.5,
"max_tokens": 5000,
"stream": true,
"elevenlabs_extra_body": {
"UUID": "123e4567-e89b-12d3-a456-426614174000",
"parameter-1": "value-1",
"parameter-2": "value-2"
}
}