Construa um Chatbot a partir de uma API LLM: Tutorial em Python
Os modelos Abliterated são modelos de linguagem de grande porte onde os mecanismos que impõem recusas de segurança foram removidos, permitindo que o modelo responda a perguntas controversas, para adultos ou de nicho sem acionar um filtro de conteúdo. Essa abordagem dá aos desenvolvedores controle total sobre a voz e o corte de conhecimento do modelo, o que é especialmente valioso para codificação, roleplay e escrita criativa, onde as proteções padrão podem bloquear saídas úteis.
Atualizado

Pontos principais
- A API é sem estado, então seu código é dono do histórico da conversa e o envia em cada requisição.
- Streaming, chamada de funções e modo JSON usam todos os parâmetros padrão da OpenAI.
- Reduza ou resuma o histórico antes que ele se aproxime da janela de 100.000 tokens.
- 1.000 conversas com 2.000 tokens de entrada e 400 tokens de saída custam cerca de $0,50.
A ideia central: um chatbot é um loop e uma lista
Um modelo de linguagem não lembra de nada entre as requisições. Cada chamada para POST /v1/chat/completions é independente. O que parece ser memória é seu programa enviando as mensagens anteriores novamente, cada uma marcada com um papel (role): system para instruções fixas, user para o que a pessoa digitou, assistant para respostas anteriores do modelo.
Então toda a arquitetura é pequena. Mantenha uma lista. Adicione a mensagem do usuário. Envie a lista. Adicione a resposta. Repita. Tudo o mais neste tutorial, de streaming a ferramentas, é uma variação desse loop.
A API aqui é compatível com OpenAI, então você usa o pacote openai padrão. Defina a Base URL como https://api.abliterated.cc/v1, use sua chave e defina o modelo como uncensored. Obtenha uma chave na página de chave de API; o crédito de teste de $0,50 é suficiente para centenas de mensagens curtas de teste.
Passo 1: um chatbot de console funcional
Instale o SDK com pip install openai e execute isto.
from openai import OpenAI
client = OpenAI(
base_url="https://api.abliterated.cc/v1",
api_key="YOUR_KEY",
)
messages = [
{"role": "system", "content": "You are a concise, friendly support assistant for a bike shop."}
]
while True:
text = input("you: ")
if text.strip() in {"quit", "exit"}:
break
messages.append({"role": "user", "content": text})
resp = client.chat.completions.create(
model="uncensored",
messages=messages,
temperature=0.7,
)
answer = resp.choices[0].message.content
messages.append({"role": "assistant", "content": answer})
print("bot:", answer)
Este é um chatbot completo. A mensagem do sistema define sua tarefa, a lista carrega a memória e temperature controla o quão variadas são as respostas. Reduza para perto de 0,2 para bots de suporte factual, aumente para perto de 1,0 para os criativos.
Escreva um prompt de sistema que defina a tarefa
A mensagem do sistema é o local mais barato para melhorar um chatbot. Mantenha-a curta e específica. Defina o papel, o público, o tamanho e o tom das respostas, e o que fazer quando o bot não souber a resposta. Um prompt como "Você responde perguntas para uma loja de bicicletas. Responda em no máximo três frases. Se a pergunta for sobre o preço de um reparo, diga que um mecânico precisa inspecionar a bicicleta" faz mais do que uma página de virtudes gerais.
Dois hábitos valem a pena. Primeiro, coloque regras na forma de ações, não atitudes: "faça uma pergunta de esclarecimento quando a solicitação for ambígua" em vez de "seja útil". Segundo, teste com entradas hostis, como uma mensagem vazia, uma colagem muito longa e uma solicitação que não tem nada a ver com seu produto. Corrija o prompt com base no que você vê e mantenha essas entradas como uma lista de regressão.
Como a mensagem do sistema é reenviada em cada rodada, cada palavra nela é cobrada em cada requisição. Um prompt de 400 tokens em 1.000 conversas de 5 rodadas cada adiciona 2.000.000 tokens de entrada, ou 2 x $0,15 = $0,30. Isso é pouco, mas mostra por que prompts inflados somam em volume.
Passo 2: faça streaming da resposta
Esperar por uma resposta completa parece lento em uma janela de chat. Defina stream: true e imprima os pedaços conforme chegam. O stream usa eventos enviados pelo servidor e termina com um bloco de uso, então você pode registrar as contagens de tokens.
from openai import OpenAI
client = OpenAI(base_url="https://api.abliterated.cc/v1", api_key="YOUR_KEY")
messages = [{"role": "user", "content": "Explain tire pressure in two sentences."}]
stream = client.chat.completions.create(
model="uncensored",
messages=messages,
stream=True,
)
reply = ""
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
part = chunk.choices[0].delta.content
reply += part
print(part, end="", flush=True)
if getattr(chunk, "usage", None):
print("\ntokens:", chunk.usage.prompt_tokens, chunk.usage.completion_tokens)
Lembre-se de anexar o reply montado ao seu histórico, ou a próxima interação não saberá o que o bot disse.
Passo 3: gerencie o contexto antes que ele cresça
A janela de contexto é de 100.000 tokens, compartilhada entre prompt e resposta gerada. A maioria dos chatbots nunca chega perto disso, mas o custo aumenta com o histórico porque você paga pelo prompt inteiro em cada rodada. Uma política simples mantém ambos sob controle:
- Mantenha sempre a mensagem do sistema.
- Mantenha as últimas 10 a 20 mensagens como estão.
- Quando a lista ultrapassar um limite de tamanho que você escolher, como 8.000 tokens estimados, envie o bloco mais antigo para o modelo com a instrução "resuma esta conversa em menos de 150 palavras" e substitua esse bloco pelo resumo como uma mensagem do sistema.
Uma estimativa aproximada de um token por quatro caracteres em inglês é suficiente para o gatilho. Os números de uso em cada resposta dão o valor exato posteriormente, então você pode calibrar o limite.
Se você truncar removendo as mensagens mais antigas, remova-as em pares de usuário e assistente. Uma resposta sem pergunta, ou uma pergunta sem resposta, confunde o modelo mais do que você esperaria.
Passo 4: dê ferramentas ao bot
A chamada de funções permite que o modelo peça ao seu código para fazer algo, como consultar um pedido. Você descreve funções com tools, o modelo responde com uma entrada tool_calls, você executa a função e envia o resultado de volta como uma mensagem role: "tool".
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.abliterated.cc/v1", api_key="YOUR_KEY")
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up the status of an order by its id",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}]
def get_order_status(order_id):
return {"order_id": order_id, "status": "shipped"}
messages = [{"role": "user", "content": "Where is order A1042?"}]
resp = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = resp.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_order_status(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
final = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools
)
print(final.choices[0].message.content)
Sempre valide os argumentos antes de executar qualquer coisa com efeitos colaterais. O modelo propõe uma chamada; seu código decide se deve executá-la.
Passo 5: saída estruturada com modo JSON
Quando o próximo passo no seu programa precisar de dados em vez de texto, como classificar uma mensagem em uma categoria, use o modo JSON com response_format. Mencione a palavra JSON e as chaves esperadas no seu prompt também.
curl https://api.abliterated.cc/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"response_format": {"type": "json_object"},
"messages": [
{"role": "system", "content": "Reply with JSON: {\"intent\": string, \"urgent\": boolean}"},
{"role": "user", "content": "My brakes squeal and I ride tomorrow morning."}
]
}'
Mesmo assim, coloque json.loads dentro de um bloco try. Se a análise falhar, tente novamente uma vez com o texto de erro anexado; requisições com falha não são cobradas.
Notas sobre erros, custos e implantação
Trate erros, tentativas e limites de requisições
Usuários reais enviam requisições em momentos estranhos e as redes falham. Encapsule a chamada em um tratamento de erros para que uma resposta ruim não quebre a conversa.
import time
from openai import OpenAI, APIError, RateLimitError
client = OpenAI(base_url="https://api.abliterated.cc/v1", api_key="YOUR_KEY")
def chat(messages, tries=3):
for attempt in range(tries):
try:
resp = client.chat.completions.create(
model="uncensored", messages=messages, temperature=0.7
)
return resp.choices[0].message.content
except RateLimitError:
time.sleep(2 ** attempt)
except APIError as exc:
if attempt == tries - 1:
raise
time.sleep(1)
return "Sorry, the assistant is busy. Please try again in a moment."
Uma chave completa permite 8 requisições simultâneas e 300 requisições por minuto; a chave de teste permite 2 e 60. Se seu bot atender muitos usuários ao mesmo tempo, coloque as requisições em uma fila com um limite de worker abaixo de 8 em vez de confiar em tentativas. Como requisições com falha não são cobradas, tentar novamente não tem custo de token. Mantenha a contagem de tentativas pequena para que uma falha real falhe rápido.
Registre também o cabeçalho X-Request-Id com cada rodada da conversa. Quando uma resposta parecer errada, o id permite encontrar a requisição exata depois.
Custos e implantação
O preço é $0,15 por 1M de tokens de entrada e $0,50 por 1M de tokens de saída. Digamos que um chat de suporte use 2.000 tokens de entrada no total e 400 tokens de saída.
- Entrada: 0,002M x $0,15 = $0,0003
- Saída: 0,0004M x $0,50 = $0,0002
- Uma conversa: $0,0005, então 1.000 conversas custam $0,50
Verifique as taxas atuais e bônus de recarga na página de preços. Para produção, mantenha a chave no seu servidor, nunca no código do navegador, e monitore o cabeçalho de resposta X-Balance-USD para alertar você antes que o crédito acabe. Uma chave completa permite 8 requisições simultâneas e 300 requisições por minuto, então enfileire picos em vez de dispará-los todos de uma vez. A documentação lista todos os parâmetros suportados.
Mais guias
Perguntas e respostas
Preciso de um framework para criar um chatbot?
Não. O SDK da OpenAI e uma lista de mensagens são suficientes para um bot funcional. Adicione um framework depois apenas se precisar dos recursos extras dele.
A API lembra das mensagens anteriores?
Não. Cada requisição é independente, então seu código deve reenviar o histórico toda vez.
Como evito que o histórico fique muito longo?
Mantenha a mensagem do sistema e as rodadas recentes, e resuma as antigas em uma nota curta assim que a lista ultrapassar o tamanho que você definir.
O bot pode chamar minhas próprias funções?
Sim. Passe as ferramentas e tool_choice, execute a função quando a resposta contiver tool_calls e retorne o resultado como uma mensagem de ferramenta.
Sua chave está a um formulário de distância
Crie uma conta, copie a chave e altere a URL base. Essa é toda a configuração.