Class: Bddgenx::IA::ChatGptCliente

Inherits:
Object
  • Object
show all
Defined in:
lib/bddgenx/ia/chatgtp_cliente.rb

Overview

Cliente para interação com a API do ChatGPT da OpenAI para gerar cenários BDD no formato Gherkin, com suporte a fallback para Gemini.

Constant Summary collapse

CHATGPT_API_URL =
ENV['CHATGPT_API_URL']
MODEL =
'gpt-4o'

Class Method Summary collapse

Class Method Details

.fallback_com_gemini(historia, idioma) ⇒ String

Método de fallback que chama o GeminiCliente para gerar cenários, usado quando a API do ChatGPT não está disponível ou ocorre erro.

Parameters:

  • historia (String)

    Texto da história para basear os cenários.

  • idioma (String)

    Código do idioma (‘pt’ ou ‘en’).

Returns:

  • (String)

    Cenários gerados pelo GeminiCliente.



136
137
138
139
# File 'lib/bddgenx/ia/chatgtp_cliente.rb', line 136

def self.fallback_com_gemini(historia, idioma)
  warn I18n.t('messages.fallback_gemini')
  GeminiCliente.gerar_cenarios(historia, idioma)
end

.gerar_cenarios(historia, idioma = 'pt') ⇒ String

Gera cenários BDD a partir de uma história fornecida, solicitando à API do ChatGPT a criação dos cenários em formato Gherkin. Se a API key não estiver configurada ou houver erro na requisição, utiliza fallback com o GeminiCliente.

Parameters:

  • historia (String)

    Texto com a história para basear os cenários.

  • idioma (String) (defaults to: 'pt')

    Código do idioma (‘pt’ ou ‘en’), padrão ‘pt’.

Returns:

  • (String)

    Cenários gerados em formato Gherkin com palavras-chave no idioma indicado.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/bddgenx/ia/chatgtp_cliente.rb', line 23

def self.gerar_cenarios(historia, idioma = 'pt')
  api_key = Bddgenx.configuration.openai_api_key  # para ChatGPT

  unless api_key
    warn I18n.t('errors.chatgpt_key_missing')
    return fallback_com_gemini(historia, idioma)
  end


  keywords_pt = {
    feature: "Funcionalidade",
    scenario: "Cenário",
    scenario_outline: "Esquema do Cenário",
    examples: "Exemplos",
    given: "Dado",
    when: "Quando",
    then: "Então",
    and: "E"
  }

  keywords_en = {
    feature: "Feature",
    scenario: "Scenario",
    scenario_outline: "Scenario Outline",
    examples: "Examples",
    given: "Given",
    when: "When",
    then: "Then",
    and: "And"
  }

  keywords = idioma == 'en' ? keywords_en : keywords_pt

  # Prompt base enviado ao ChatGPT, instruindo a saída no formato correto
  prompt_base = <<~PROMPT
                  Gere cenários BDD no formato Gherkin, utilizando as palavras-chave estruturais no idioma "#{idioma}":
                    Feature: #{keywords[:feature]}
                    Scenario: #{keywords[:scenario]}
                    Scenario Outline: #{keywords[:scenario_outline]}
                    Examples: #{keywords[:examples]}
                    Given: #{keywords[:given]}
                    When: #{keywords[:when]}
                    Then: #{keywords[:then]}
                    And: #{keywords[:and]}
                
                  Instruções:
                  - Todos os textos dos passos devem ser escritos em **português**.
                  - Use as palavras-chave Gherkin no idioma especificado ("#{idioma}").
                  - Gere **vários cenários**, incluindo positivos e negativos.
                  - Use `Scenario Outline` e `Examples` sempre que houver valores variáveis.
                  - Mantenha os parâmetros como `<email>`, `<senha>` e outros entre colchetes angulares, exatamente como aparecem.
                  - Se a história fornecer contexto (ex: `[CONTEXT]` ou "Dado que..."), utilize-o como base para os cenários.
                  - Se não houver contexto explícito, **crie um coerente** baseado na história.
                  - A primeira linha do resultado deve conter obrigatoriamente `# language: #{idioma}`.
                  - Evite passos vagos ou genéricos. Use ações claras e específicas.
                  - Gere apenas o conteúdo da feature, sem explicações adicionais.
                
                  História fornecida:
                  #{historia}
                PROMPT

  uri = URI(CHATGPT_API_URL)
  request_body = {
    model: MODEL,
    messages: [
      {
        role: "user",
        content: prompt_base
      }
    ]
  }

  headers = {
    "Content-Type" => "application/json",
    "Authorization" => "Bearer #{api_key}"
  }

  response = Net::HTTP.post(uri, request_body.to_json, headers)

  if response.is_a?(Net::HTTPSuccess)
    json = JSON.parse(response.body)
    texto_ia = json.dig("choices", 0, "message", "content")

    if texto_ia
      texto_limpo = Utils.limpar(texto_ia)
      Utils::remover_steps_duplicados(texto_ia, idioma)

      # Ajusta a linha de idioma no arquivo gerado
      texto_limpo.sub!(/^# language: .*/, "# language: #{idioma}")
      texto_limpo.prepend("# language: #{idioma}\n") unless texto_limpo.start_with?("# language:")
      return texto_limpo
    else
      warn I18n.t('errors.ia_no_content')
      warn JSON.pretty_generate(json)
      return fallback_com_gemini(historia, idioma)
    end
  else
    if response.code.to_i == 429
      warn I18n.t('errors.openai_quota')
      warn I18n.t('errors.openai_check_usage')
    end
    return fallback_com_gemini(historia, idioma)
  end
end