Class: AskChatgpt::VoiceFlow::Voice

Inherits:
Object
  • Object
show all
Defined in:
lib/ask_chatgpt/voice.rb

Instance Method Summary collapse

Constructor Details

#initializeVoice

Returns a new instance of Voice.



72
73
74
75
76
77
78
79
# File 'lib/ask_chatgpt/voice.rb', line 72

def initialize
  @messages = []
  @wanna_quit = false
  @duration = (AskChatGPT.voice_max_duration.presence || 10).to_i
  @ffmpeg_wait_duration = 0.5
  @executing = true
  @spinner = nil
end

Instance Method Details

#clientObject



170
171
172
# File 'lib/ask_chatgpt/voice.rb', line 170

def client
  @client ||= OpenAI::Client.new(access_token: AskChatGPT.access_token)
end

#runObject



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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/ask_chatgpt/voice.rb', line 81

def run
  while @executing
    # Start the parallel process
    audio_recorder = AudioRecorder.new(@duration)
    audio_recorder.start

    begin
      Timeout.timeout(@duration + @ffmpeg_wait_duration) do
        @spinner = TTY::Spinner.new("[Recording]".red + " / Press any key to stop recording or \"Esc\" / \"q\" to quit ... ".blue + ":spinner".red, format: :spin)
        @spinner.auto_spin
        sleep(@ffmpeg_wait_duration) # five some time for ffmpeg to start
        # Listen for user input in the main process
        begin
          char = $stdin.getch
          if char.ord == 27 || char.upcase == "Q"
            audio_recorder.stop
            @executing = false
            @spinner.stop
            puts "Bye...".brown
          end
          break
        end while char.nil?
      end
    rescue Timeout::Error
    ensure
      audio_recorder.stop
      @spinner.stop
      break unless @executing
    end

    if !File.exist?("output.wav")
      puts "No audio file found, please try again.".brown
      sleep(0.5)
      next
    end

    @spinner = TTY::Spinner.new("Thinking :spinner".cyan, format: :dots)
    @spinner.auto_spin
    response = client.transcribe(parameters: { model: "whisper-1", file: File.open("output.wav", "rb") })
    @spinner.stop

    if response["error"]
      puts response["error"].inspect.brown
      @executing = false
      break
    end

    user_input = response["text"].to_s
    puts "USER> ".green + user_input
    @messages << { role: "user", content:user_input }
    print "ASSISTANT> ".magenta

    stop_stream = false
    reply = []

    keypresser = Thread.new do
      loop { stop_stream = true if $stdin.getch }
    end

    begin
      client.chat(
        parameters: {
          model: "gpt-3.5-turbo",
          messages: @messages,
          temperature: 0.7,
          stream: proc do |chunk, _bytesize|
            break if stop_stream
            message = chunk.dig("choices", 0, "delta", "content")
            next if message.to_s.empty?

            message = message.gsub("\n", "\r\n")

            print message
            reply += [message]
          end
        })
    rescue LocalJumpError
      puts
    ensure
      Thread.kill(keypresser)
      stop_stream = false
      @messages << { role: "assistant", content: reply.join }
      puts
    end

    audio_recorder.delete_audio_file
  end
end