> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Integre seu próprio modelo

> **Note**
>
> 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](/docs/pt/eleven-agents/customization/llm)

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:

* [API Chat Completions](https://platform.openai.com/docs/api-reference/chat/create) (`/v1/chat/completions`)
* [API Responses](https://platform.openai.com/docs/api-reference/responses/create) (`/v1/responses`)

> **Info**
>
> 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](https://platform.openai.com/docs/api-reference/chat/create) ou [Responses](https://platform.openai.com/docs/api-reference/responses/create) 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:

#### API Chat Completions

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`.

#### API Responses

Retorne um item de saída `reasoning` com o texto do resumo no campo `summary`.

Com o esforço de raciocínio configurado e o Resumo do raciocínio ativado, a ElevenLabs define
`reasoning.summary` como `auto` na solicitação.

Consulte [Resumo do raciocínio](/docs/pt/eleven-agents/customization/llm#reasoning-summary) 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`:

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

![Adicionar segredo](/docs/_fern-img/83c62b81ef04860b9d884e28e1b4ac7bbceaa6e481e72e15ae82a76ec9bbad8e.webp)

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

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

![Inserir URL](/docs/_fern-img/85ed8154868096a5c8de4c5e1c09d83c861069ea098c7643a960cac1736b67cb.webp)

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

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`.

#### API Chat Completions

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:

```python
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)
```

#### API Responses

A API Responses usa o endpoint `/v1/responses`.

Cada bloco precisa estar no formato `event: {type}\ndata: {json}\n\n`, e o stream precisa terminar com `data: [DONE]\n\n`. Os eventos mínimos necessários são:

* `response.output_text.delta` - para transmitir conteúdo de texto
* `response.completed` - para sinalizar a conclusão

**`server.py`**

```python title="server.py"
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_dotenv()

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 InputMessage(BaseModel):
    role: str
    content: str

class ResponseCreateRequest(BaseModel):
    model: str
    input: List[InputMessage]
    instructions: Optional[str] = None
    temperature: Optional[float] = 0.7
    max_output_tokens: Optional[int] = None
    stream: Optional[bool] = False

@app.post("/v1/responses")
async def create_response(request: ResponseCreateRequest) -> StreamingResponse:
    input_messages = [{"role": msg.role, "content": msg.content} for msg in request.input]

    response_stream = await oai_client.responses.create(
        model=request.model,
        input=input_messages,
        instructions=request.instructions,
        temperature=request.temperature,
        max_output_tokens=request.max_output_tokens,
        stream=True
    )

    async def event_stream():
        try:
            async for event in response_stream:
                if event.type == "response.output_text.delta":
                    yield f"event: response.output_text.delta\ndata: {json.dumps({'type': 'response.output_text.delta', 'delta': event.delta})}\n\n"
                elif event.type == "response.completed":
                    yield f"event: response.completed\ndata: {json.dumps({'type': 'response.completed', 'response': {'id': event.response.id, 'status': 'completed'}})}\n\n"

            yield "data: [DONE]\n\n"

        except Exception as e:
            logging.error("An error occurred: %s", str(e))
            yield f"event: error\ndata: {json.dumps({'type': 'error', 'error': {'message': str(e)}})}\n\n"

    return StreamingResponse(event_stream(), media_type="text/event-stream")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8013)

```

**`server.ts`**

```typescript title="server.ts"
import express, { Request, Response } from "express";
import OpenAI from "openai";

const app = express();
app.use(express.json());

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

interface InputMessage {
  role: string;
  content: string;
}

interface ResponseCreateRequest {
  model: string;
  input: InputMessage[];
  instructions?: string;
  temperature?: number;
  max_output_tokens?: number;
  stream?: boolean;
}

app.post("/v1/responses", async (req: Request, res: Response) => {
  const request = req.body as ResponseCreateRequest;

  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  try {
    const stream = await openai.responses.create({
      model: request.model,
      input: request.input,
      instructions: request.instructions,
      temperature: request.temperature ?? 0.7,
      max_output_tokens: request.max_output_tokens,
      stream: true,
    });

    for await (const event of stream) {
      if (event.type === "response.output_text.delta") {
        res.write(
          `event: response.output_text.delta\ndata: ${JSON.stringify({ type: "response.output_text.delta", delta: event.delta })}\n\n`
        );
      } else if (event.type === "response.completed") {
        res.write(
          `event: response.completed\ndata: ${JSON.stringify({ type: "response.completed", response: { id: event.response.id, status: "completed" } })}\n\n`
        );
      }
    }

    res.write("data: [DONE]\n\n");
    res.end();
  } catch (error) {
    console.error("An error occurred:", error);
    res.write(
      `event: error\ndata: ${JSON.stringify({ type: "error", error: { message: String(error) } })}\n\n`
    );
    res.end();
  }
});

app.listen(8013, () => console.log("Server running on port 8013"));
```

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

![](/docs/_fern-img/8032697eeac9a62bb084feb13ab05294df2fee44f14a97897f0b7c10ffee813c.webp)

### 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:

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

![](/docs/_fern-img/16d139cc2889d46e026c8aa7578fcdcd8d228dbe0f4df245091ea6de2ceb345a.webp)

### 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.

![](/docs/_fern-img/d57d81e44dffb7e6f581a4eed449d887f6c365b8ceb4f4f0174bd7e2ffd62537.webp)

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:

**`server.py`**

```python title="server.py"
@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")

```

**`server.ts`**

```typescript title="server.ts"
app.post("/v1/chat/completions", async (req: Request, res: Response) => {
  const request = req.body as ChatCompletionRequest;
  const oaiRequest = { ...request };

  if (oaiRequest.user_id) {
    oaiRequest.user = oaiRequest.user_id;
    delete oaiRequest.user_id;
  }

  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  try {
    // Send initial buffer chunk while processing
    const initialChunk = {
      id: "chatcmpl-buffer",
      object: "chat.completion.chunk",
      created: Math.floor(Date.now() / 1000),
      model: request.model,
      choices: [
        {
          delta: { content: "Let me think about that... " },
          index: 0,
          finish_reason: null,
        },
      ],
    };
    res.write(`data: ${JSON.stringify(initialChunk)}\n\n`);

    // Process the actual LLM response
    const stream = await openai.chat.completions.create({
      ...oaiRequest,
      stream: true,
    });

    for await (const chunk of stream) {
      res.write(`data: ${JSON.stringify(chunk)}\n\n`);
    }

    res.write("data: [DONE]\n\n");
    res.end();
  } catch (error) {
    console.error("An error occurred:", error);
    res.write(`data: ${JSON.stringify({ error: "Internal error occurred!" })}\n\n`);
    res.end();
  }
});
```

## Integração com ferramentas do sistema

Seu LLM personalizado pode acionar [ferramentas do sistema](/docs/pt/eleven-agents/customization/tools/system-tools) 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](/docs/pt/eleven-agents/customization/tools/system-tools)

### Ferramentas do sistema disponíveis

#### Encerrar chamada

**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**:

```json
{
  "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](/docs/pt/eleven-agents/customization/tools/system-tools/end-call)

#### Detecção de idioma

**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**:

```json
{
  "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](/docs/pt/eleven-agents/customization/tools/system-tools/language-detection)

#### Transferência de agente

**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**:

```json
{
  "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](/docs/pt/eleven-agents/customization/tools/system-tools/agent-transfer)

#### Transferir para humano

**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**:

```json
{
  "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](/docs/pt/eleven-agents/customization/tools/system-tools/transfer-to-number)

#### Pular turno

**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**:

```json
{
  "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](/docs/pt/eleven-agents/customization/tools/system-tools/skip-turn)

#### Detecção de caixa postal

**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**:

```json
{
  "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](/docs/pt/eleven-agents/customization/tools/system-tools/voicemail-detection)

### 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:

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

> **Note**
>
> 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

#### Parâmetros de LLM personalizado

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

#### Python

#### Defina os parâmetros extras

Crie um objeto que contenha seus parâmetros personalizados:

```python
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,
)
```

#### Atualize a implementação do LLM

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

```python
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:

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