-
-
Save jweir/57c4e1c305e0aefabc9e8da609314f71 to your computer and use it in GitHub Desktop.
Ruby interface to OpenAI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
# frozen_string_literal: true | |
require_relative 'ai' | |
bot = OpenAIChatbot.new(ENV.fetch('OPENAI_API_KEY', nil)) | |
bot.read_input |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
# frozen_string_literal: true | |
require 'readline' | |
require 'httparty' | |
require 'json' | |
# nodoc | |
class OpenAIChatbot | |
include HTTParty | |
GPT = 'gpt-3.5-turbo' | |
GPT4X = 'gpt-4' | |
GPT4 = 'gpt-4-1106-preview' | |
# Command takes a func (lambda) and help | |
# Help describes what the command will do | |
Command = Data.define(:func, :help) | |
CMDS = { | |
'GPT' => Command.new(->(o, _input) { o.model = GPT }, 'Sets the model to GPT'), | |
'GPT3_16' => Command.new(->(o, _input) { o.model = GPT3_16 }, 'Sets the model to GPT 3.5 16K'), | |
'GPT4' => Command.new(->(o, _input) { o.model = GPT4 }, 'Sets the model to GPT4'), | |
'+' => Command.new(->(o, input) { o.prompt File.read(input) }, 'Reads a file and | |
sets the prompt to its contents'), | |
'!' => Command.new(->(o, _input) { o.messages = [] }, 'Clears the chat history'), | |
':' => Command.new(lambda { |o, input| | |
x = `#{input}` | |
puts "```#{x}```" | |
o.prompt(x) | |
}, 'Run the command and add the out to the prompt.'), | |
'mt:' => Command.new(lambda { |o, input| | |
o.max_tokens = input.to_i | |
puts "max_tokens: #{o.max_tokens}" | |
}, 'Sets the maximum number of tokens'), | |
'exit' => Command.new(->(_, _) { exit }, 'Exits the chatbot'), | |
'quit' => Command.new(->(_, _) { exit }, 'Exits the chatbot'), | |
'info' => Command.new(->(o, _) { puts o.model }, 'Prints the model info'), | |
'?' => Command.new(->(_, _) { puts(CMDS.map { |k, v| "#{k}: #{v.help}" }) }, 'Displays a list of | |
available commands') | |
}.freeze | |
attr_accessor :messages, :model, :max_tokens | |
def initialize(api_key) | |
@api_key = api_key | |
@messages = [{ role: 'system', content: 'General questions' }] | |
@max_tokens = 800 | |
@model = GPT4 | |
end | |
def headers | |
{ | |
authorization: "Bearer #{@api_key}", | |
'Content-Type': 'application/json' | |
} | |
end | |
def post | |
url = 'https://api.openai.com/v1/chat/completions' | |
self.class.post url, { | |
headers:, | |
body: JSON.generate({ | |
model: @model, | |
max_tokens: @max_tokens, | |
temperature: 0, | |
messages: @messages | |
}) | |
} | |
end | |
def iterate(input) | |
cmd, *words = input.split(' ') | |
x = CMDS[cmd] | |
if x | |
x.func.call self, words.join(' ') | |
nil | |
elsif input.empty? | |
puts '' | |
print_response(post) | |
puts '' | |
else | |
prompt input | |
end | |
end | |
def prompt(input) | |
@messages = @messages << { role: 'user', content: input } | |
end | |
def print_response(resp) | |
if resp['choices'] | |
puts wrap_word(resp['choices'].first['message']['content']) | |
else | |
puts resp | |
end | |
end | |
def read_input | |
while (buf = Readline.readline('> ', true)) | |
iterate buf | |
end | |
end | |
def wrap_word(input_string, given_width = 80) | |
# <default value> to be replaced with an integer by user | |
array_of_characters = input_string.split('') | |
output_string = [] | |
counter_variable = 0 | |
array_of_characters.each do |character| | |
# first check if the original character is a carriage return. | |
# If so, reset the counter variable. | |
if character == "\n" | |
counter_variable = 0 | |
# if not, check if the counter is greater than the desired width, | |
# also checking if the original character is a space. | |
# if so, replace it with a carriage return. | |
elsif counter_variable >= given_width && character == ' ' | |
character = "\n" | |
counter_variable = 0 | |
end | |
output_string << character | |
counter_variable += 1 | |
end | |
output_string.join('').to_s | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment