PoC validado com conta ChatGPT Plus e client_id do Hermes. Device flow
OAuth funciona, gera access_token + refresh_token auto-refresh. Chat e
function calling funcionaram em gpt-5.4, gpt-5.4-mini, gpt-5.2 e
gpt-5.3-codex.
Descobertas pro adapter final:
- Endpoint: /responses (não /chat/completions)
- Streaming obrigatório (stream: true)
- store: false obrigatório
- Sem temperature/top_p (modelos reasoning)
- input[] no lugar de messages[]
- instructions top-level no lugar de system role
- Tools sem wrapping function: {}
- Output via events response.output_item.done (não response.completed)
Pasta scripts/captain_codex_poc/ está excluída do Rubocop (scripts
standalone, não rodam em contexto Rails).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.0 KiB
Ruby
Executable File
67 lines
2.0 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# Qualidade conversacional: simula a Jasmine via /responses.
|
|
|
|
require_relative 'codex_client'
|
|
|
|
JASMINE_SYSTEM = <<~PROMPT.freeze
|
|
Você é a Jasmine, recepcionista dos Hoteis 1001 Noites. Atende no WhatsApp.
|
|
|
|
Regras:
|
|
- Sempre em português do Brasil, tom acolhedor mas direto, frases curtas
|
|
- Se souber o nome do cliente, SEMPRE começa com "Oi, {primeiro_nome}!"
|
|
- Nunca invente preços, diárias ou disponibilidade — se não souber, diga que vai verificar
|
|
- Identifique o cenário em 1-2 mensagens: pré-reserva, check-in, reclamação, dúvida geral
|
|
- Se for pré-reserva, colete: datas, número de hóspedes, tipo de quarto, forma de pagamento
|
|
|
|
Unidades:
|
|
- 1001 Noites Prime (Brasília)
|
|
- 1001 Noites Express (Águas Lindas)
|
|
- Dolce Amore (Natal)
|
|
PROMPT
|
|
|
|
SCENARIOS = [
|
|
{
|
|
name: 'Pré-reserva com nome',
|
|
contact_name: 'Rodrigo Borba Machado',
|
|
user: 'Oi, boa tarde. Queria ver uma diária para esse fim de semana'
|
|
},
|
|
{
|
|
name: 'Cliente anônimo',
|
|
contact_name: nil,
|
|
user: 'vcs tem quarto pra essa sexta?'
|
|
},
|
|
{
|
|
name: 'Reclamação',
|
|
contact_name: 'Maria Silva',
|
|
user: 'Acabei de sair do hotel e o ar condicionado não funcionou a noite toda. Paguei R$400 por noite, isso é uma falta de respeito.'
|
|
}
|
|
].freeze
|
|
|
|
MODEL = ENV.fetch('CODEX_MODEL', 'gpt-5.4')
|
|
|
|
client = CodexPoc::Client.new
|
|
puts "Modelo: #{MODEL}\n\n"
|
|
|
|
SCENARIOS.each do |scenario|
|
|
puts "=== #{scenario[:name]} ==="
|
|
puts "Contato: #{scenario[:contact_name] || '(desconhecido)'}"
|
|
puts "Cliente: #{scenario[:user]}"
|
|
puts
|
|
|
|
system_prompt = JASMINE_SYSTEM.dup
|
|
system_prompt += "\n\nDados do contato: nome = #{scenario[:contact_name]}." if scenario[:contact_name]
|
|
|
|
begin
|
|
resp = client.responses(
|
|
model: MODEL,
|
|
system_prompt: system_prompt,
|
|
user_messages: scenario[:user]
|
|
)
|
|
out = CodexPoc::Client.extract(resp)
|
|
puts "Jasmine: #{out[:text]}"
|
|
rescue CodexPoc::Error => e
|
|
warn "FALHOU: #{e.message[0, 300]}"
|
|
end
|
|
puts "\n---\n\n"
|
|
end
|