Intégrez votre propre modèle

Connectez un agent à votre propre LLM ou hébergez votre propre serveur.

Custom LLM vous permet de connecter vos conversations à votre propre LLM via un point de terminaison externe. ElevenLabs prend également en charge les LLM intégrés nativement

Les LLM personnalisés vous permettent d’utiliser votre propre clé API OpenAI ou d’exécuter un serveur LLM entièrement personnalisé.

Vue d’ensemble

Par défaut, nous utilisons nos propres identifiants internes pour des modèles populaires tels qu’OpenAI. Pour utiliser un serveur LLM personnalisé, celui-ci doit respecter l’une des structures de requête/réponse compatibles avec OpenAI suivantes :

L’API Responses est le format d’API plus récent d’OpenAI et prend en charge des fonctionnalités supplémentaires. Les deux formats d’API sont entièrement pris en charge pour l’intégration de LLM personnalisés.

Les guides suivants couvrent les deux cas d’usage :

  1. Utiliser votre propre clé OpenAI : utilisez votre propre clé API OpenAI avec notre plateforme.
  2. Serveur LLM personnalisé : hébergez et connectez votre propre implémentation de serveur LLM.

Vous apprendrez à :

  • Stocker votre clé API OpenAI dans ElevenLabs
  • Héberger un serveur qui reproduit le point de terminaison Chat Completions ou Responses d’OpenAI
  • Diriger ElevenLabs vers votre point de terminaison personnalisé
  • Transmettre des paramètres supplémentaires à votre LLM selon vos besoins

Résumé du raisonnement

Votre point de terminaison doit renvoyer le raisonnement séparément de la réponse finale. ElevenLabs ne génère pas le raisonnement à partir de la réponse finale.

Pour demander le raisonnement à un point de terminaison pris en charge, activez Résumé du raisonnement dans les paramètres LLM de l’agent ou définissez enable_reasoning_summary via l’API.

Renvoyer le raisonnement

Utilisez le format correspondant à votre point de terminaison :

Diffusez le raisonnement dans le champ reasoning ou reasoning_content de chaque delta de réponse.

Pour les points de terminaison compatibles avec Gemini, ElevenLabs demande les pensées avec google.thinking_config.include_thoughts et lit le contenu marqué avec extra_content.google.thought.

Consultez Résumé du raisonnement pour en savoir plus sur le stockage, la diffusion et les limites.

Utiliser votre propre clé OpenAI

Pour intégrer une clé OpenAI personnalisée, mettez à jour les paramètres de votre agent dans le Dashboard ElevenLabs afin de le diriger vers votre serveur LLM personnalisé, puis créez un secret contenant votre OPENAI_API_KEY :

1

Dans les paramètres de votre agent du Dashboard ElevenLabs, sélectionnez « Custom LLM » dans le menu déroulant « LLM » à droite.

Ajouter un secret

2

Cliquez sur le champ sous « LLM » et faites défiler la liste pour sélectionner « Custom LLM ».

3

Saisissez l’URL du serveur et l’ID du modèle de votre serveur LLM personnalisé.

Saisir l’URL

4

Cliquez sur le menu déroulant sous « API key » et sélectionnez « Create new secret ». Nommez la clé OPENAI_API_KEY, ajoutez-la dans le champ « value », puis cliquez sur « Add secret ».

5

Cliquez sur le bouton « x » pour fermer la fenêtre LLM, puis sur « Publish » pour enregistrer vos modifications.

Serveur LLM personnalisé

Pour utiliser un serveur LLM personnalisé, configurez un point de terminaison de serveur compatible, suivant le style d’OpenAI. Vous pouvez implémenter l’API Chat Completions (/v1/chat/completions) ou l’API Responses (/v1/responses).

Les deux points de terminaison doivent renvoyer des réponses au format SSE (Server-Sent Events) avec Content-Type: text/event-stream.

L’API Chat Completions utilise le point de terminaison /v1/chat/completions.

Chaque bloc doit être formaté comme data: {json}\n\n et le flux doit se terminer par data: [DONE]\n\n.

Voici un exemple d’implémentation de serveur :

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)

Exécutez ce code ou le code de votre propre serveur.

Configurer une URL publique pour votre serveur

Pour rendre votre serveur accessible, créez une URL publique à l’aide d’un outil de tunneling tel que ngrok :

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

Configurer CustomLLM d’ElevenLabs

Mettez ensuite à jour les paramètres de votre agent dans le Dashboard ElevenLabs afin de le diriger vers votre serveur LLM personnalisé.

Dirigez l’URL de votre serveur vers le point de terminaison ngrok et définissez « Limit token usage » sur 5000.

Vous pouvez désormais interagir avec votre agent à l’aide de votre propre serveur LLM.

Optimiser les LLM à traitement lent

Si votre LLM personnalisé présente des temps de traitement lents, par exemple en raison du raisonnement agentique ou d’exigences de prétraitement, vous pouvez améliorer le flux conversationnel en implémentant des mots tampons dans vos réponses en streaming. Cette technique aide à préserver une prosodie naturelle pendant que votre LLM génère la réponse complète.

Mots tampons

Lorsque votre LLM a besoin de plus de temps pour traiter la réponse complète, renvoyez une réponse initiale se terminant par "... " (points de suspension suivis d’une espace). Cela permet au système Text to Speech de maintenir un flux naturel tout en gardant une conversation dynamique. Cela crée des pauses naturelles qui s’enchaînent bien avec le contenu suivant, sur lequel le LLM peut raisonner plus longtemps. L’espace supplémentaire est essentielle pour éviter que le contenu suivant ne soit ajouté à « … », ce qui peut entraîner des distorsions audio.

Implémentation

Voici comment modifier votre serveur LLM personnalisé pour implémenter les mots tampons :

@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")

Intégration des outils système

Votre LLM personnalisé peut déclencher des outils système afin de contrôler le flux et l’état de la conversation. Ces outils sont automatiquement inclus dans le paramètre tools de vos requêtes de complétion de chat lorsqu’ils sont configurés dans votre agent.

Fonctionnement des outils système

  1. Décision du LLM : votre LLM personnalisé détermine quand appeler ces outils selon le contexte de la conversation
  2. Réponse de l’outil : le LLM répond avec des appels de fonction au format OpenAI standard
  3. Traitement côté backend : ElevenLabs traite les appels d’outils et met à jour l’état de la conversation

Pour en savoir plus sur les outils système, consultez notre guide

Outils système disponibles

Objectif : terminer automatiquement les conversations lorsque les conditions appropriées sont réunies.

Conditions de déclenchement : le LLM doit appeler cet outil lorsque :

  • La tâche principale est terminée et l’utilisateur est satisfait
  • La conversation est arrivée à une conclusion naturelle avec un accord mutuel
  • L’utilisateur indique explicitement vouloir terminer la conversation

Paramètres :

  • reason (chaîne, requis) : le motif de fin de l’appel
  • message (chaîne, facultatif) : un message d’adieu à envoyer à l’utilisateur avant de terminer l’appel

Format d’appel de fonction :

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

Implémentation : configurez cet outil comme outil système dans les paramètres de votre agent. Le LLM recevra des instructions détaillées sur le moment où appeler cette fonction.

En savoir plus : Outil de fin d’appel

Objectif : basculer automatiquement vers la langue détectée de l’utilisateur pendant les conversations.

Conditions de déclenchement : le LLM doit appeler cet outil lorsque :

  • L’utilisateur parle dans une langue différente de celle de la conversation en cours
  • L’utilisateur demande explicitement à changer de langue
  • La conversation nécessite une prise en charge multilingue

Paramètres :

  • reason (chaîne, requis) : le motif du changement de langue
  • language (chaîne, requis) : le code de la langue vers laquelle basculer, qui doit figurer dans la liste des langues prises en charge

Format d’appel de fonction :

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

Implémentation : configurez les langues prises en charge dans les paramètres de l’agent et ajoutez l’outil système de détection de langue. L’agent basculera automatiquement sa voix et ses réponses pour correspondre aux langues détectées.

En savoir plus : Outil de détection de langue

Objectif : transférer les conversations entre des agents IA spécialisés selon les besoins de l’utilisateur.

Conditions de déclenchement : le LLM doit appeler cet outil lorsque :

  • La demande de l’utilisateur requiert des connaissances spécialisées ou des capacités d’agent différentes
  • L’agent actuel ne peut pas traiter correctement la requête
  • Le flux de la conversation indique qu’un autre type d’agent est nécessaire

Paramètres :

  • reason (chaîne, facultatif) : le motif du transfert d’agent
  • agent_number (entier, requis) : le numéro de l’agent vers lequel transférer, indexé à partir de zéro et basé sur les règles de transfert configurées

Format d’appel de fonction :

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

Implémentation : définissez des règles de transfert qui associent des conditions à des ID d’agent spécifiques. Configurez les agents vers lesquels l’agent actuel peut transférer les conversations. Les agents sont référencés par des numéros indexés à partir de zéro dans la configuration de transfert.

En savoir plus : Outil de transfert d’agent

Objectif : transférer facilement les conversations à des opérateurs humains lorsque l’assistance IA ne suffit pas.

Conditions de déclenchement : le LLM doit appeler cet outil lorsque :

  • Les problèmes complexes nécessitent un jugement humain
  • L’utilisateur demande explicitement une assistance humaine
  • L’IA atteint les limites de ses capacités pour la demande spécifique
  • Les protocoles d’escalade sont déclenchés

Paramètres :

  • reason (chaîne, facultatif) : le motif du transfert
  • transfer_number (chaîne, requis) : le numéro de téléphone vers lequel transférer, qui doit correspondre aux numéros configurés
  • client_message (chaîne, requis) : message lu au client pendant l’attente du transfert
  • agent_message (chaîne, requis) : message destiné à l’opérateur humain qui reçoit l’appel

Format d’appel de fonction :

{
"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.\"}"
}
}

Implémentation : configurez les numéros de téléphone et les conditions de transfert. Définissez les messages destinés au client comme à l’opérateur humain qui reçoit l’appel. Fonctionne avec Twilio et le trunking SIP.

En savoir plus : Outil de transfert vers un humain

Objectif : permettre à l’agent de faire une pause et d’attendre la saisie de l’utilisateur sans parler.

Conditions de déclenchement : le LLM doit appeler cet outil lorsque :

  • L’utilisateur indique avoir besoin d’un moment (« Donnez-moi une seconde », « Laissez-moi réfléchir »)
  • L’utilisateur demande une pause dans le flux de la conversation
  • L’agent détecte que l’utilisateur a besoin de temps pour traiter les informations

Paramètres :

  • reason (chaîne, facultatif) : motif libre expliquant pourquoi la pause est nécessaire

Format d’appel de fonction :

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

Implémentation : aucune configuration supplémentaire n’est nécessaire. L’outil indique simplement à l’agent de rester silencieux jusqu’à ce que l’utilisateur parle de nouveau.

En savoir plus : Outil de passage de tour

Paramètres :

  • reason (chaîne, obligatoire) : raison de la détection de messagerie vocale (par exemple, « message d’accueil automatisé détecté », « aucune réponse humaine »)

Format d’appel de fonction :

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

En savoir plus : Outil de détection de messagerie vocale

Exemple de requête avec des outils système

Lorsque les outils système sont configurés, votre LLM personnalisé reçoit des requêtes incluant les outils au format OpenAI standard :

{
"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": []
}
}
}
]
}

Votre LLM personnalisé doit prendre en charge les appels de fonction pour utiliser les outils système. Assurez-vous que votre modèle peut générer des réponses d’appel de fonction correctes au format OpenAI.

Fonctionnalités supplémentaires

Vous pouvez transmettre des paramètres supplémentaires à votre implémentation de LLM personnalisé.

1

Définir les paramètres supplémentaires

Créez un objet contenant vos paramètres personnalisés :

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

Mettre à jour l’implémentation du LLM

Modifiez le code de votre LLM personnalisé pour gérer les paramètres supplémentaires :

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)

Exemple de requête

Avec cette configuration de message personnalisée, votre LLM reçoit des requêtes dans ce format :

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