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

WordPress não aparece no Google: noindex esquecido e robots.txt virtual

Site novo há semanas e nenhuma página indexada? Confira a caixinha de visibilidade em Leitura, o noindex no HTML e…

1 dia atrás

array_map perde as chaves do array no PHP: como manter o índice

O retorno do array_map voltou com índice 0, 1, 2 e o código que dependia da chave quebrou. Entenda quando…

2 dias atrás

Backup do Magento 2 com mysqldump: dump leve sem as tabelas de log

Dump de 12 GB que demora horas porque arrasta report_event e cron_schedule. Faça o backup em duas passadas, guarde só…

2 dias atrás

Preference do di.xml não aplica no Magento 2: o que checar antes

Escreveu a preference e o Magento 2 continua usando a classe original? Confira a área do di.xml, o generated/code e…

3 dias atrás

Filtro por atributo do WooCommerce vazio: global x personalizado

Cadastrou Cor direto na aba Atributos do produto e o filtro por atributo vem vazio. Veja como identificar o tipo,…

4 dias atrás

wp db query: rodar SQL no WordPress pelo WP-CLI sem phpMyAdmin

Precisa de um SELECT no banco do cliente e só tem SSH? O wp db query pega a senha do…

4 dias atrás