Class: Jambots::Bot

Inherits:
Object
  • Object
show all
Defined in:
lib/jambots/bot.rb

Constant Summary collapse

DEFAULT_MODEL =
"gpt-3.5-turbo"
DEFAULT_GLOBAL_BOTS_DIR =
"#{ENV["HOME"]}/.jambots"
DEFAULT_LOCAL_BOTS_DIR =
"./.jambots"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, args = {}) ⇒ Bot

Returns a new instance of Bot.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/jambots/bot.rb', line 48

def initialize(name, args = {})
  @bot_dir = "#{find_path(args[:path])}/#{name}"

  raise "Bot #{name} doesn't exist." unless File.exist?("#{bot_dir}/bot.yml")

  # Load options from bot.yml file if it exists
  bot_yml_path = "#{@bot_dir}/bot.yml"
  if File.exist?(bot_yml_path)
    bot_yml_options = YAML.safe_load(File.read(bot_yml_path), permitted_classes: [Symbol], symbolize_names: true)
    args = bot_yml_options.merge(args)
  end

  openai_api_key = args[:openai_api_key] || ENV["OPENAI_API_KEY"]
  @client = OpenAI::Client.new(access_token: openai_api_key, request_timeout: 240)

  @name = name
  @model = args[:model] || DEFAULT_MODEL
  @prompt = args[:prompt]

  FileUtils.mkdir_p(conversations_dir) unless Dir.exist?(conversations_dir)
end

Instance Attribute Details

#bot_dirObject (readonly)

Returns the value of attribute bot_dir.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def bot_dir
  @bot_dir
end

#clientObject (readonly)

Returns the value of attribute client.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def client
  @client
end

#current_conversationObject (readonly)

Returns the value of attribute current_conversation.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def current_conversation
  @current_conversation
end

#modelObject (readonly)

Returns the value of attribute model.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def model
  @model
end

#nameObject (readonly)

Returns the value of attribute name.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def name
  @name
end

#optionsObject (readonly)

Returns the value of attribute options.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def options
  @options
end

#promptObject (readonly)

Returns the value of attribute prompt.



16
17
18
# File 'lib/jambots/bot.rb', line 16

def prompt
  @prompt
end

Class Method Details

.create(name, path: DEFAULT_BOTS_DIR, model: DEFAULT_MODEL, prompt: nil) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/jambots/bot.rb', line 18

def self.create(
  name,
  path: DEFAULT_BOTS_DIR,
  model: DEFAULT_MODEL,
  prompt: nil
)
  bot_dir = "#{path}/#{name}"
  FileUtils.mkdir_p(bot_dir) unless Dir.exist?(bot_dir)
  conversations_dir = "#{bot_dir}/conversations"
  FileUtils.mkdir_p(conversations_dir) unless Dir.exist?(conversations_dir)
  bot_yml_path = "#{bot_dir}/bot.yml"
  raise "The bot file #{bot_yml_path} already exists" if File.exist?(bot_yml_path)

  bot_options = {
    model: model,
    prompt: prompt
  }

  bot_options_transformed = bot_options.transform_keys(&:to_s)
  File.write(bot_yml_path, bot_options_transformed.to_yaml)

  new(name, path: path)
end

.find_path(path = nil) ⇒ Object



42
43
44
45
46
# File 'lib/jambots/bot.rb', line 42

def self.find_path(path = nil)
  return path if path

  Dir.exist?(DEFAULT_LOCAL_BOTS_DIR) ? DEFAULT_LOCAL_BOTS_DIR : DEFAULT_GLOBAL_BOTS_DIR
end

Instance Method Details

#conversationsObject



88
89
90
91
92
# File 'lib/jambots/bot.rb', line 88

def conversations
  Dir.glob("#{conversations_dir}/*").map do |file|
    Conversation.new(file)
  end
end

#load_conversation(conversation_name) ⇒ Object



101
102
103
104
105
106
107
108
109
110
# File 'lib/jambots/bot.rb', line 101

def load_conversation(conversation_name)
  return nil unless conversation_name

  conversation_path = Dir.glob("#{conversations_dir}/#{conversation_name}*").first

  return nil unless conversation_path
  return nil unless File.exist?(conversation_path)

  Conversation.new(conversation_path)
end

#message(text, conversation) ⇒ Object

Raises:



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/jambots/bot.rb', line 70

def message(text, conversation)
  response = client.chat(
    parameters: {
      model: model,
      messages: conversation.messages.insert(-1, {role: "user", content: text}),
      temperature: 0.7
    }
  )

  message = response.dig("choices", 0, "message")

  raise OpenAIMessageError, response if message.nil?

  conversation.add_message("assistant", message["content"])
  conversation.save
  conversation.messages.last
end

#new_conversationObject



94
95
96
97
98
99
# File 'lib/jambots/bot.rb', line 94

def new_conversation
  new_conversation_path = "#{conversations_dir}/#{Time.now.strftime("%Y%m%d%H%M%S")}.yml"
  conversation = Conversation.new(new_conversation_path)
  conversation.add_message("system", prompt.to_s)
  conversation
end