Integre seu próprio modelo

Conecte um agente ao seu próprio LLM ou hospede seu próprio servidor.

O LLM personalizado permite conectar suas conversas ao seu próprio LLM por meio de um endpoint externo. A ElevenLabs também oferece suporte a LLMs integrados nativamente

Os LLMs personalizados permitem que você use sua própria chave de API da OpenAI ou execute um servidor LLM totalmente personalizado.

Visão geral

Por padrão, usamos nossas próprias credenciais internas para modelos populares como o OpenAI. Para usar um servidor LLM personalizado, ele precisa seguir uma das seguintes estruturas de solicitação/resposta compatíveis com OpenAI:

A API Responses é o formato mais recente de API da OpenAI e oferece recursos adicionais. Os dois formatos de API são totalmente compatíveis com a integração de LLMs personalizados.

Os guias a seguir abordam os dois casos de uso:

  1. Use sua própria chave da OpenAI: use sua própria chave de API da OpenAI com nossa plataforma.
  2. Servidor LLM personalizado: hospede e conecte sua própria implementação de servidor LLM.

Você aprenderá a:

  • Armazenar sua chave de API da OpenAI na ElevenLabs
  • Hospedar um servidor que replique o endpoint Chat Completions ou Responses da OpenAI
  • Direcionar a ElevenLabs ao seu endpoint personalizado
  • Transmitir parâmetros extras ao seu LLM conforme necessário

Resumo do raciocínio

Seu endpoint precisa retornar o raciocínio separadamente da resposta final. A ElevenLabs não gera o raciocínio a partir da resposta final.

Para solicitar raciocínio de um endpoint compatível, ative Resumo do raciocínio nas configurações de LLM do agente ou defina enable_reasoning_summary pela API.

Retornar raciocínio

Use o formato correspondente ao seu endpoint:

Transmita o raciocínio no campo reasoning ou reasoning_content de cada delta de resposta.

Para endpoints compatíveis com Gemini, a ElevenLabs solicita pensamentos com google.thinking_config.include_thoughts e lê o conteúdo marcado com extra_content.google.thought.

Consulte Resumo do raciocínio para saber sobre armazenamento, entrega e limitações.

Usando sua própria chave da OpenAI

Para integrar uma chave personalizada da OpenAI, atualize as configurações do seu agente no painel da ElevenLabs para apontar para seu servidor LLM personalizado e crie um segredo com sua OPENAI_API_KEY:

1

Nas configurações do seu agente no painel da ElevenLabs, selecione “Custom LLM” no menu suspenso “LLM”, à direita.

Adicionar segredo

2

Clique no campo abaixo de “LLM” e role para baixo para selecionar “Custom LLM”.

3

Informe a URL do servidor e o ID do modelo do seu servidor LLM personalizado.

Inserir URL

4

Clique no menu suspenso abaixo de “API key” e selecione “Create new secret”. Dê à chave o nome OPENAI_API_KEY, adicione-a ao campo “value” e clique em “Add secret”.

5

Clique no botão “x” para fechar o modal de LLM e em “Publish” para salvar suas alterações.

Servidor LLM personalizado

Para usar um servidor LLM personalizado, configure um endpoint de servidor compatível usando o padrão da OpenAI. Você pode implementar a API Chat Completions (/v1/chat/completions) ou a API Responses (/v1/responses).

Ambos os endpoints precisam retornar respostas no formato SSE (Server-Sent Events) com Content-Type: text/event-stream.

A API Chat Completions usa o endpoint /v1/chat/completions.

Cada bloco precisa estar no formato data: {json}\n\n, e o stream precisa terminar com data: [DONE]\n\n.

Veja um exemplo de implementação de servidor:

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)

Execute este código ou o código do seu próprio servidor.

Configurando uma URL pública para seu servidor

Para tornar seu servidor acessível, crie uma URL pública usando uma ferramenta de tunelamento como o ngrok:

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

Configurando o CustomLLM da ElevenLabs

Em seguida, atualize as configurações do seu agente no painel da ElevenLabs para apontar para seu servidor LLM personalizado.

Direcione a URL do seu servidor para o endpoint do ngrok e defina “Limit token usage” como 5000.

Agora você pode começar a interagir com seu agente usando seu próprio servidor LLM.

Otimização para LLMs com processamento lento

Se o seu LLM personalizado tem tempos de processamento lentos (talvez devido a raciocínio agêntico ou requisitos de pré-processamento), você pode melhorar o fluxo da conversa implementando palavras de preenchimento nas suas respostas de streaming. Essa técnica ajuda a manter a prosódia natural da fala enquanto seu LLM gera a resposta completa.

Palavras de preenchimento

Quando seu LLM precisar de mais tempo para processar a resposta completa, retorne uma resposta inicial terminando com "... " (reticências seguidas de um espaço). Isso permite que o sistema Text to Speech mantenha um fluxo natural e preserve o dinamismo da conversa. Isso cria pausas naturais que se conectam bem ao conteúdo subsequente, sobre o qual o LLM pode raciocinar por mais tempo. O espaço extra é fundamental para garantir que o conteúdo subsequente não seja anexado a "...", o que pode causar distorções no áudio.

Implementação

Veja como modificar seu servidor de LLM personalizado para implementar palavras de preenchimento:

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

Integração com ferramentas do sistema

Seu LLM personalizado pode acionar ferramentas do sistema para controlar o fluxo e o estado da conversa. Essas ferramentas são incluídas automaticamente no parâmetro tools das suas solicitações de conclusão de chat quando configuradas no seu agente.

Como as ferramentas do sistema funcionam

  1. Decisão do LLM: seu LLM personalizado decide quando chamar essas ferramentas com base no contexto da conversa
  2. Resposta da ferramenta: o LLM responde com chamadas de função no formato padrão da OpenAI
  3. Processamento de backend: a ElevenLabs processa as chamadas de ferramenta e atualiza o estado da conversa

Para mais informações sobre as ferramentas do sistema, consulte nosso guia

Ferramentas do sistema disponíveis

Finalidade: encerrar automaticamente conversas quando as condições adequadas forem atendidas.

Condições de acionamento: o LLM deve chamar esta ferramenta quando:

  • A tarefa principal foi concluída e o usuário está satisfeito
  • A conversa chegou a uma conclusão natural com acordo mútuo
  • O usuário indica explicitamente que deseja encerrar a conversa

Parâmetros:

  • reason (string, obrigatório): o motivo para encerrar a chamada
  • message (string, opcional): uma mensagem de despedida para enviar ao usuário antes de encerrar a chamada

Formato da chamada de função:

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

Implementação: configure como uma ferramenta do sistema nas configurações do seu agente. O LLM receberá instruções detalhadas sobre quando chamar esta função.

Saiba mais: ferramenta de encerramento de chamada

Finalidade: mudar automaticamente para o idioma detectado do usuário durante as conversas.

Condições de acionamento: o LLM deve chamar esta ferramenta quando:

  • O usuário fala em um idioma diferente do idioma atual da conversa
  • O usuário solicita explicitamente a mudança de idioma
  • É necessário suporte a vários idiomas para a conversa

Parâmetros:

  • reason (string, obrigatório): o motivo para a mudança de idioma
  • language (string, obrigatório): o código do idioma para o qual mudar (deve estar na lista de idiomas compatíveis)

Formato da chamada de função:

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

Implementação: configure os idiomas compatíveis nas configurações do agente e adicione a ferramenta do sistema de detecção de idioma. O agente mudará automaticamente a voz e as respostas para corresponder aos idiomas detectados.

Saiba mais: ferramenta de detecção de idioma

Finalidade: transferir conversas entre agentes de IA especializados com base nas necessidades do usuário.

Condições de acionamento: o LLM deve chamar esta ferramenta quando:

  • A solicitação do usuário exigir conhecimento especializado ou recursos de outro agente
  • O agente atual não puder lidar adequadamente com a consulta
  • O fluxo da conversa indicar a necessidade de outro tipo de agente

Parâmetros:

  • reason (string, opcional): o motivo para a transferência de agente
  • agent_number (integer, obrigatório): número, indexado a partir de zero, do agente para o qual transferir (com base nas regras de transferência configuradas)

Formato da chamada de função:

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

Implementação: defina regras de transferência que associem condições a IDs específicos de agentes. Configure para quais agentes o agente atual pode transferir. Os agentes são referenciados por números indexados a partir de zero na configuração de transferência.

Saiba mais: ferramenta de transferência de agente

Finalidade: transferir conversas sem interrupções para atendentes humanos quando a assistência de IA não for suficiente.

Condições de acionamento: o LLM deve chamar esta ferramenta quando:

  • Houver problemas complexos que exijam julgamento humano
  • O usuário solicitar explicitamente assistência humana
  • A IA atingir os limites de capacidade para a solicitação específica
  • Os protocolos de escalonamento forem acionados

Parâmetros:

  • reason (string, opcional): o motivo para a transferência
  • transfer_number (string, obrigatório): o número de telefone para o qual transferir (deve corresponder aos números configurados)
  • client_message (string, obrigatório): mensagem lida ao cliente enquanto aguarda a transferência
  • agent_message (string, obrigatório): mensagem para o atendente humano que recebe a chamada

Formato da chamada de função:

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

Implementação: configure números de telefone e condições de transferência. Defina mensagens tanto para o cliente quanto para o atendente humano que recebe a chamada. Funciona com Twilio e troncos SIP.

Saiba mais: ferramenta de transferência para humano

Finalidade: permitir que o agente faça uma pausa e aguarde a entrada do usuário sem falar.

Condições de acionamento: o LLM deve chamar esta ferramenta quando:

  • O usuário indicar que precisa de um momento (“Me dê um segundo”, “Deixe-me pensar”)
  • O usuário solicitar uma pausa no fluxo da conversa
  • O agente detectar que o usuário precisa de tempo para processar informações

Parâmetros:

  • reason (string, opcional): motivo livre explicando por que a pausa é necessária

Formato da chamada de função:

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

Implementação: não é necessária nenhuma configuração adicional. A ferramenta simplesmente sinaliza para o agente permanecer em silêncio até que o usuário fale novamente.

Saiba mais: ferramenta de pular turno

Parâmetros:

  • reason (string, obrigatório): o motivo para detectar a caixa postal (por exemplo, “saudação automática detectada”, “nenhuma resposta humana”)

Formato de chamada da função:

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

Saiba mais: ferramenta de detecção de caixa postal

Exemplo de solicitação com ferramentas do sistema

Quando as ferramentas do sistema estão configuradas, seu LLM personalizado receberá solicitações que incluem as ferramentas no formato padrão da 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": []
}
}
}
]
}

Seu LLM personalizado precisa oferecer suporte a chamadas de função para usar as ferramentas do sistema. Verifique se o modelo consegue gerar respostas de chamadas de função adequadas no formato da OpenAI.

Recursos adicionais

Você pode passar parâmetros adicionais para sua implementação de LLM personalizado.

1

Defina os parâmetros extras

Crie um objeto que contenha seus parâmetros personalizados:

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

Atualize a implementação do LLM

Modifique o código do seu LLM personalizado para lidar com os parâmetros adicionais:

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)

Exemplo de solicitação

Com essa configuração de mensagem personalizada, seu LLM receberá solicitações neste formato:

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