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 Custom LLM’s kun je je eigen OpenAI API-sleutel gebruiken of een volledig eigen LLM-server uitvoeren.

Een custom LLM kan niet worden gebruikt met een Realtime model.

Overzicht

Standaard gebruiken we onze eigen interne credentials voor populaire modellen zoals OpenAI. Om een custom LLM-server te gebruiken, moet deze voldoen aan een van de volgende OpenAI-compatibele request-/responsestructuren:

De Responses API is de nieuwere API-indeling van OpenAI die aanvullende functies ondersteunt. Beide API-indelingen worden volledig ondersteund voor custom LLM-integratie.

De volgende handleidingen behandelen beide use cases:

  1. Gebruik je eigen OpenAI-sleutel: Gebruik je eigen OpenAI API-sleutel met ons platform.
  2. Custom LLM-server: Host en koppel je eigen implementatie van een LLM-server.

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 custom endpoint verwijst
  • Naar behoefte extra parameters doorgeeft aan je LLM

Samenvatting van redenering

Je endpoint moet de redenering los van het definitieve antwoord retourneren. ElevenLabs genereert geen redenering op basis van het definitieve antwoord.

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

Redenering retourneren

Gebruik de indeling die bij je endpoint past:

Stream redenering in het veld reasoning of reasoning_content van elke responsdelta.

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

Zie Samenvatting van redenering voor opslag, levering en beperkingen.

Je eigen OpenAI-sleutel gebruiken

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

1

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

Secret toevoegen

2

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

3

Voer de server-URL en de model-ID van je custom 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 de LLM-modal te sluiten en klik op “Publish” om je wijzigingen op te slaan.

Custom LLM-server

Om een custom LLM-server te gebruiken, stel je een compatibel serverendpoint 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 reacties 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 met een tunnelingtool zoals ngrok een openbare URL te maken:

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 custom 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 communiceren via je eigen LLM-server.

Optimaliseren voor LLM’s met trage verwerking

Als je aangepaste LLM trage verwerkingstijden heeft (bijvoorbeeld door agentisch redeneren of vereisten voor voorverwerking), kun je de gespreksflow verbeteren door bufferwoorden in je streamingreacties te implementeren. Deze techniek helpt de natuurlijke spraakprosodie te behouden terwijl je LLM de volledige reactie genereert.

Bufferwoorden

Wanneer je LLM meer tijd nodig heeft om de volledige reactie te verwerken, retourneer je een eerste reactie die eindigt op "... " (beletselteken gevolgd door een spatie). Zo kan het Text to Speech-systeem de natuurlijke flow behouden en blijft het gesprek dynamisch aanvoelen. Hierdoor ontstaan natuurlijke pauzes die goed overgaan in volgende content waarover de 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 in je agent zijn geconfigureerd.

Hoe systeemtools werken

  1. LLM-beslissing: Je aangepaste LLM bepaalt op basis van de gesprekscontext wanneer deze tools moeten worden aangeroepen
  2. Toolreactie: De LLM reageert 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 gids

Beschikbare systeemtools

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

Voorwaarden voor activering: De LLM moet deze tool aanroepen wanneer:

  • De hoofdtaak is voltooid en de gebruiker tevreden is
  • Het gesprek op natuurlijke wijze en met wederzijdse instemming is afgerond
  • De gebruiker expliciet aangeeft het gesprek te willen beëindigen

Parameters:

  • reason (string, vereist): De reden om het gesprek te beëindigen
  • 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 deze als systeemtool in je agentinstellingen. De 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.

Voorwaarden voor activering: De LLM moet deze tool aanroepen wanneer:

  • De gebruiker in een andere taal spreekt dan de huidige gesprekstaal
  • De gebruiker expliciet vraagt om van taal te wisselen
  • Meertalige ondersteuning nodig is voor het gesprek

Parameters:

  • reason (string, vereist): De reden voor de taalwissel
  • language (string, vereist): De taalcode om naar over te schakelen (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 schakelt automatisch van stem en reacties om overeen te komen met de gedetecteerde talen.

Meer informatie: Tool voor taaldetectie

Doel: Gesprekken overdragen tussen gespecialiseerde AI-agents op basis van de behoeften van de gebruiker.

Voorwaarden voor activering: De 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 agenttype nodig is

Parameters:

  • reason (string, optioneel): De reden voor de agentoverdracht
  • agent_number (integer, vereist): Het vanaf nul geïndexeerde nummer 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 aan specifieke agent-ID’s koppelen. Configureer naar welke agents de huidige agent kan overdragen. Agents worden in de overdrachtsconfiguratie aangeduid met vanaf nul geïndexeerde nummers.

Meer informatie: Tool voor agentoverdracht

Doel: Gesprekken soepel doorgeven aan menselijke medewerkers wanneer AI-ondersteuning niet toereikend is.

Voorwaarden voor activering: De 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 voor het specifieke verzoek bereikt
  • Escalatieprotocollen worden geactiveerd

Parameters:

  • reason (string, optioneel): De reden voor de overdracht
  • transfer_number (string, vereist): Het telefoonnummer waarnaar moet worden doorverbonden (moet overeenkomen met geconfigureerde nummers)
  • client_message (string, vereist): Bericht dat aan de klant wordt voorgelezen tijdens het wachten op de 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 overdragen aan een medewerker

Doel: De agent laten pauzeren en op invoer van de gebruiker laten wachten zonder te spreken.

Voorwaarden voor activering: De LLM moet deze tool aanroepen wanneer:

  • De gebruiker aangeeft een moment nodig te hebben (“Geef me even”, “Laat me 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: Er is geen aanvullende configuratie nodig. De tool geeft de agent alleen het signaal 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 die de tools in de standaardindeling van OpenAI bevatten:

{
"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 functieaanroepen ondersteunen om systeemtools te gebruiken. Zorg dat je model correcte reacties voor functieaanroepen in OpenAI-indeling kan genereren.

Aanvullende functies

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

1

Definieer de extra parameters

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

Werk de LLM-implementatie bij

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

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"
}
}