Passer à la navigation

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 endpoint 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é.

Un LLM personnalisé ne peut pas être utilisé avec un modèle Realtime.

Vue d’ensemble

Par défaut, nous utilisons nos propres identifiants internes pour des modèles populaires comme 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 l’endpoint Chat Completions ou Responses d’OpenAI
  • Diriger ElevenLabs vers votre endpoint personnalisé
  • Transmettre des paramètres supplémentaires à votre LLM selon vos besoins

Résumé du raisonnement

Votre endpoint 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 endpoint 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 endpoint :

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

Pour les endpoints compatibles avec Gemini, ElevenLabs demande les réflexions avec google.thinking_config.include_thoughts et lit le contenu marqué avec extra_content.google.thought.

Consultez Résumé du raisonnement pour connaître 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 de 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 clé au champ « value », puis cliquez sur « Add secret ».

5

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

Serveur LLM personnalisé

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

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

L’API Chat Completions utilise l’endpoint /v1/chat/completions.

Chaque segment 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 l’endpoint ngrok et définissez « Limit token usage » sur 5000.

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

Optimisation pour les LLM à traitement lent

Si votre LLM personnalisé présente des temps de traitement lents, peut-être en raison d’un raisonnement agentique ou d’exigences de prétraitement, vous pouvez améliorer la fluidité des échanges en intégrant des mots tampons dans vos réponses en streaming. Cette technique aide à maintenir 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 "... " (des points de suspension suivis d’une espace). Cela permet au système Text to Speech de maintenir un flux naturel tout en gardant l’échange 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 soit ajouté à « … », ce qui pourrait entraîner des distorsions audio.

Implémentation

Voici comment modifier votre serveur LLM personnalisé pour implémenter des 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 pour 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écide 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 atteint une conclusion naturelle, d’un commun accord
  • L’utilisateur indique explicitement vouloir terminer la conversation

Paramètres :

  • reason (chaîne, obligatoire) : la raison de la fin de l’appel
  • message (chaîne, facultatif) : un message d’au revoir à 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 : passer automatiquement à 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 la langue actuelle de la conversation
  • L’utilisateur demande explicitement à changer de langue
  • La conversation nécessite une prise en charge multilingue

Paramètres :

  • reason (chaîne, obligatoire) : la raison du changement de langue
  • language (chaîne, obligatoire) : le code de la langue vers laquelle passer, 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 la langue. L’agent adaptera automatiquement sa voix et ses réponses aux langues détectées.

En savoir plus : outil de détection de la langue

Objectif : transférer les conversations entre 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 nécessite des connaissances spécialisées ou des capacités d’agent différentes
  • L’agent actuel ne peut pas traiter la demande de manière adéquate
  • Le flux de la conversation indique qu’un autre type d’agent est nécessaire

Paramètres :

  • reason (chaîne, facultatif) : la raison du transfert d’agent
  • agent_number (entier, obligatoire) : le numéro, indexé à partir de zéro, de l’agent vers lequel transférer la conversation, selon 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 associant des conditions à des identifiants d’agent spécifiques. Configurez les agents vers lesquels l’agent actuel peut transférer la conversation. 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 de manière fluide les conversations à des intervenants humains lorsque l’assistance IA ne suffit pas.

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

  • Des 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
  • Des protocoles d’escalade sont déclenchés

Paramètres :

  • reason (chaîne, facultatif) : la raison du transfert
  • transfer_number (chaîne, obligatoire) : le numéro de téléphone vers lequel transférer l’appel, qui doit correspondre à l’un des numéros configurés
  • client_message (chaîne, obligatoire) : message lu au client pendant l’attente du transfert
  • agent_message (chaîne, obligatoire) : message destiné à l’intervenant 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 des messages pour le client et pour l’intervenant humain qui reçoit l’appel. Fonctionne avec Twilio et le trunking SIP.

En savoir plus : outil de transfert vers un intervenant 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) : raison 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 pour ignorer le 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 des 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 votre code de 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é, votre LLM reçoit des requêtes au format suivant :

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