Inteligência Artificial

Chamar API de IA com cURL no PHP 8.3: o script mínimo que já funciona

Cansei de copiar resposta da telinha do chat e colar no editor. O que resolve isso é um ia.php de vinte linhas: curl_init apontando para o endpoint de mensagens, três headers e o payload em json_encode. Roda com php ia.php no terminal e a resposta volta em JSON, pronta pra entrar em qualquer rotina sua.

O ia.php inteiro

<?php
$payload = [
    'model'      => 'claude-opus-5',
    'max_tokens' => 16000,
    'messages'   => [
        ['role' => 'user', 'content' => 'Explique indice composto no MySQL 8 em 3 linhas.'],
    ],
];

$ch = curl_init('https://api.anthropic.com/v1/messages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_TIMEOUT        => 120,
    CURLOPT_HTTPHEADER     => [
        'content-type: application/json',
        'x-api-key: ' . getenv('ANTHROPIC_API_KEY'),
        'anthropic-version: 2023-06-01',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);

$corpo = curl_exec($ch);
$http  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($http !== 200) {
    fwrite(STDERR, "HTTP $http: $corpon");
    exit(1);
}

foreach (json_decode($corpo, true)['content'] as $bloco) {
    if ($bloco['type'] === 'text') {
        echo $bloco['text'], "n";
    }
}

Antes de rodar, exporte a chave no shell: export ANTHROPIC_API_KEY='sua-chave'. Chave escrita dentro do arquivo vaza no primeiro commit distraído; getenv custa a mesma linha e não vai pro Git.

Os dois tropeços do primeiro dia

O primeiro é o header de autenticação. Muita API usa Authorization: Bearer, e essa aqui não: a chave vai em x-api-key e o anthropic-version é obrigatório. Errou um dos dois e volta 401 com authentication_error no corpo — por isso o script joga $corpo no STDERR e sai com código 1, em vez de morrer calado.

O segundo é achar que content[0] é sempre o texto. É um array de blocos, e nos modelos atuais o bloco de raciocínio vem antes do text. Filtrar pelo type, como no foreach, evita o resultado vazio que parece bug da API e é só leitura errada do JSON. Pelo mesmo motivo não economize no max_tokens: esse raciocínio conta no mesmo teto, e um valor apertado corta a saída no meio, com stop_reason voltando max_tokens.

Com isso no terminal, o passo seguinte é mover o bloco pra dentro de uma classe e trocar o echo por um retorno. O CURLOPT_TIMEOUT generoso fica: resposta longa demora mesmo.

Post Recentes

Bloquear .env e .git no nginx: as regras que ainda deixam o arquivo vazar

Negar /.env no nginx parece resolvido até alguém pedir /wp-content/uploads/.env ou backup.sql. As regras que testei e os furos que…

12 horas atrás

Canonical errado no Yoast: corrigindo pelo filtro wpseo_canonical

O Search Console marca suas páginas 2, 3 e 4 como alternativas da página 1? Ajuste a tag canônica do…

16 horas atrás

Layout XML do Magento 2: remover bloco de módulo de terceiro

Um módulo de terceiro plantou um banner no topo da loja e você não quer desinstalar nada: tire o bloco…

1 dia atrás

Restaurar dump do Magento 2 em outro servidor: trocar a base_url no SQL

Importou o banco de produção e o site pula para o domínio antigo? Rode o UPDATE em core_config_data, limpe o…

2 dias atrás

Criar exceção customizada em PHP: quando estender Exception compensa

Seu catch trata pedido inexistente e banco fora do ar do mesmo jeito. Veja como criar exceção customizada em PHP…

3 dias atrás

DataProvider Magento 2: form do admin abre com campos vazios ao editar

O form do admin salva mas abre em branco na edição: veja o getData() indexado pelo id da entidade e…

4 dias atrás