Hoppa till navigering

Integrera din egen modell

Anslut en agent till din egen LLM eller hosta din egen server.

Med Custom LLM kan du ansluta dina samtal till din egen LLM via en extern slutpunkt. ElevenLabs stöder även inbyggt integrerade LLM:er

Custom LLMs låter dig använda din egen OpenAI API-nyckel eller köra en helt anpassad LLM-server.

En anpassad LLM kan inte användas med en Realtime-modell.

Översikt

Som standard använder vi våra egna interna autentiseringsuppgifter för populära modeller som OpenAI. För att använda en anpassad LLM-server måste den följa en av följande OpenAI-kompatibla strukturer för begäran och svar:

Responses API är OpenAI:s nyare API-format som stöder ytterligare funktioner. Båda API-formaten stöds fullt ut för integrering av anpassade LLM:er.

Följande guider täcker båda användningsfallen:

  1. Använd din egen OpenAI-nyckel: Använd din egen OpenAI API-nyckel med vår plattform.
  2. Anpassad LLM-server: Hosta och anslut din egen implementering av en LLM-server.

Du lär dig att:

  • Lagra din OpenAI API-nyckel i ElevenLabs
  • Hosta en server som replikerar OpenAI:s slutpunkt för Chat Completions eller Responses
  • Rikta ElevenLabs till din anpassade slutpunkt
  • Skicka extra parametrar till din LLM vid behov

Sammanfattning av resonemang

Din slutpunkt måste returnera resonemang separat från det slutliga svaret. ElevenLabs genererar inte resonemang från det slutliga svaret.

För att begära resonemang från en slutpunkt som stöds aktiverar du Sammanfattning av resonemang i agentens LLM-inställningar eller anger enable_reasoning_summary via API:t.

Returnera resonemang

Använd det format som matchar din slutpunkt:

Strömma resonemang i fältet reasoning eller reasoning_content i varje svarsdelta.

För Gemini-kompatibla slutpunkter begär ElevenLabs tankar med google.thinking_config.include_thoughts och läser innehåll markerat med extra_content.google.thought.

Se Sammanfattning av resonemang för lagring, leverans och begränsningar.

Använd din egen OpenAI-nyckel

För att integrera en anpassad OpenAI-nyckel uppdaterar du agentinställningarna i ElevenLabs instrumentpanel så att de pekar på din anpassade LLM-server och skapar en hemlighet som innehåller din OPENAI_API_KEY:

1

I agentinställningarna i ElevenLabs instrumentpanel väljer du “Custom LLM” i rullgardinsmenyn “LLM” till höger.

Lägg till hemlighet

2

Klicka på fältet under “LLM” och skrolla ned för att välja “Custom LLM”.

3

Ange server-URL:en och modell-ID:t för din anpassade LLM-server.

Ange URL

4

Klicka på rullgardinsmenyn under “API key” och välj “Create new secret”. Namnge nyckeln OPENAI_API_KEY, lägg till nyckeln i fältet “value” och klicka på “Add secret”.

5

Klicka på knappen “x” för att stänga LLM-modalrutan och klicka på “Publish” för att spara ändringarna.

Anpassad LLM-server

För att använda en anpassad LLM-server konfigurerar du en kompatibel serverslutpunkt enligt OpenAI:s modell. Du kan implementera antingen Chat Completions API (/v1/chat/completions) eller Responses API (/v1/responses).

Båda slutpunkterna måste returnera svar i SSE-format (Server-Sent Events) med Content-Type: text/event-stream.

Chat Completions API använder slutpunkten /v1/chat/completions.

Varje del måste formateras som data: {json}\n\n och strömmen måste avslutas med data: [DONE]\n\n.

Här är ett exempel på en serverimplementering:

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)

Kör den här koden eller din egen serverkod.

Konfigurera en offentlig URL för din server

För att göra servern tillgänglig skapar du en offentlig URL med ett tunnlingsverktyg som ngrok:

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

Konfigurera ElevenLabs CustomLLM

Uppdatera sedan agentinställningarna i ElevenLabs instrumentpanel så att de pekar på din anpassade LLM-server.

Rikta server-URL:en till ngrok-slutpunkten och ange “Limit token usage” till 5000.

Du kan nu börja interagera med din agent med din egen LLM-server.

Optimera för LLM:er med långsam bearbetning

Om din anpassade LLM har långa bearbetningstider (kanske på grund av agentbaserat resonemang eller krav på förbearbetning) kan du förbättra samtalsflödet genom att använda buffertord i dina streamade svar. Den här tekniken bidrar till att behålla ett naturligt talflyt medan din LLM genererar det fullständiga svaret.

Buffertord

När din LLM behöver mer tid för att bearbeta hela svaret ska du returnera ett första svar som slutar med "... " (tre punkter följt av ett mellanslag). Det gör att Text to Speech-systemet kan behålla ett naturligt flöde och samtidigt få samtalet att kännas dynamiskt. Det skapar naturliga pauser som flyter väl in i efterföljande innehåll som LLM:en kan resonera längre kring. Det extra mellanslaget är avgörande för att säkerställa att efterföljande innehåll inte läggs till efter ”…”, vilket kan leda till ljudförvrängningar.

Implementering

Så här ändrar du din anpassade LLM-server för att använda buffertord:

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

Integrering av systemverktyg

Din anpassade LLM kan utlösa systemverktyg för att styra samtalsflöde och tillstånd. Dessa verktyg inkluderas automatiskt i parametern tools för dina begäranden om chat completion när de har konfigurerats i din agent.

Så fungerar systemverktyg

  1. LLM-beslut: Din anpassade LLM avgör när dessa verktyg ska anropas baserat på samtalskontexten
  2. Verktygssvar: LLM:en svarar med funktionsanrop i standardformatet för OpenAI
  3. Bearbetning i backend: ElevenLabs bearbetar verktygsanropen och uppdaterar samtalstillståndet

Mer information om systemverktyg finns i vår guide

Tillgängliga systemverktyg

Syfte: Avsluta samtal automatiskt när lämpliga villkor är uppfyllda.

Utlösande villkor: LLM:en ska anropa det här verktyget när:

  • Huvuduppgiften har slutförts och användaren är nöjd
  • Samtalet har nått ett naturligt avslut med ömsesidig överenskommelse
  • Användaren uttryckligen anger att hen vill avsluta samtalet

Parametrar:

  • reason (sträng, krävs): Anledningen till att avsluta samtalet
  • message (sträng, valfritt): Ett avskedsmeddelande att skicka till användaren innan samtalet avslutas

Format för funktionsanrop:

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

Implementering: Konfigurera som ett systemverktyg i agentens inställningar. LLM:en får detaljerade instruktioner om när den ska anropa funktionen.

Läs mer: Verktyg för att avsluta samtal

Syfte: Växla automatiskt till användarens identifierade språk under samtal.

Utlösande villkor: LLM:en ska anropa det här verktyget när:

  • Användaren talar ett annat språk än det aktuella samtalsspråket
  • Användaren uttryckligen ber om att byta språk
  • Samtalet behöver stöd för flera språk

Parametrar:

  • reason (sträng, krävs): Anledningen till språkbytet
  • language (sträng, krävs): Språkkoden att byta till (måste finnas i listan över språk som stöds)

Format för funktionsanrop:

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

Implementering: Konfigurera språk som stöds i agentens inställningar och lägg till systemverktyget för språkidentifiering. Agenten växlar automatiskt röst och svar för att matcha identifierade språk.

Läs mer: Verktyg för språkidentifiering

Syfte: Överför samtal mellan specialiserade AI-agenter baserat på användarens behov.

Utlösande villkor: LLM:en ska anropa det här verktyget när:

  • Användarens begäran kräver specialiserad kunskap eller andra agentfunktioner
  • Den aktuella agenten inte kan hantera frågan på ett tillräckligt bra sätt
  • Samtalsflödet visar att en annan typ av agent behövs

Parametrar:

  • reason (sträng, valfritt): Anledningen till agentöverföringen
  • agent_number (heltal, krävs): Det nollindexerade numret för agenten som samtalet ska överföras till (baserat på konfigurerade överföringsregler)

Format för funktionsanrop:

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

Implementering: Definiera överföringsregler som kopplar villkor till specifika agent-ID:n. Konfigurera vilka agenter den aktuella agenten kan överföra till. Agenter refereras med nollindexerade nummer i överföringskonfigurationen.

Läs mer: Verktyg för agentöverföring

Syfte: Lämna smidigt över samtal till mänskliga operatörer när AI-hjälpen inte räcker till.

Utlösande villkor: LLM:en ska anropa det här verktyget när:

  • Komplexa frågor kräver mänskligt omdöme
  • Användaren uttryckligen begär mänsklig hjälp
  • AI:n når gränserna för vad den kan göra för den specifika begäran
  • Eskaleringsprotokoll utlöses

Parametrar:

  • reason (sträng, valfritt): Anledningen till överföringen
  • transfer_number (sträng, krävs): Telefonnummer att överföra till (måste matcha konfigurerade nummer)
  • client_message (sträng, krävs): Meddelande som läses upp för kunden medan överföringen väntar
  • agent_message (sträng, krävs): Meddelande till den mänskliga operatör som tar emot samtalet

Format för funktionsanrop:

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

Implementering: Konfigurera telefonnummer och villkor för överföring. Definiera meddelanden för både kunden och den mottagande mänskliga operatören. Fungerar med både Twilio och SIP-trunking.

Läs mer: Verktyg för överföring till människa

Syfte: Låt agenten pausa och vänta på användarens inmatning utan att tala.

Utlösande villkor: LLM:en ska anropa det här verktyget när:

  • Användaren anger att hen behöver en stund (“Ge mig en sekund”, “Låt mig tänka”)
  • Användaren ber om en paus i samtalsflödet
  • Agenten identifierar att användaren behöver tid för att bearbeta information

Parametrar:

  • reason (sträng, valfritt): Fritt formulerad anledning som förklarar varför pausen behövs

Format för funktionsanrop:

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

Implementering: Ingen ytterligare konfiguration krävs. Verktyget signalerar helt enkelt till agenten att vara tyst tills användaren talar igen.

Läs mer: Verktyg för att hoppa över tur

Parametrar:

  • reason (sträng, obligatorisk): Anledningen till att röstbrevlåda identifierades (t.ex. ”automatiskt hälsningsmeddelande identifierat”, ”inget mänskligt svar”)

Format för funktionsanrop:

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

Läs mer: Verktyg för röstbrevlådeidentifiering

Exempel på begäran med systemverktyg

När systemverktyg har konfigurerats får din anpassade LLM begäranden som inkluderar verktygen i OpenAIs standardformat:

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

Din anpassade LLM måste stödja funktionsanrop för att kunna använda systemverktyg. Kontrollera att din modell kan generera korrekta svar på funktionsanrop i OpenAI-format.

Ytterligare funktioner

Du kan skicka ytterligare parametrar till din anpassade LLM-implementering.

1

Definiera de extra parametrarna

Skapa ett objekt som innehåller dina anpassade parametrar:

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

Uppdatera LLM-implementeringen

Ändra din anpassade LLM-kod för att hantera de ytterligare parametrarna:

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)

Exempel på begäran

Med denna konfiguration för anpassade meddelanden får din LLM begäranden i följande 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"
}
}