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.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/jambots/bot.rb', line 46

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

  bot_yml_path = "#{@bot_dir}/bot.yml"

  bot_options = load_bot_options(bot_yml_path)
  args = bot_options.merge(args)

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

  @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.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def bot_dir
  @bot_dir
end

#clientObject (readonly)

Returns the value of attribute client.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def client
  @client
end

#current_conversationObject (readonly)

Returns the value of attribute current_conversation.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def current_conversation
  @current_conversation
end

#modelObject (readonly)

Returns the value of attribute model.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def model
  @model
end

#nameObject (readonly)

Returns the value of attribute name.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def name
  @name
end

#optionsObject (readonly)

Returns the value of attribute options.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def options
  @options
end

#promptObject (readonly)

Returns the value of attribute prompt.



14
15
16
# File 'lib/jambots/bot.rb', line 14

def prompt
  @prompt
end

Class Method Details

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



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

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



40
41
42
43
44
# File 'lib/jambots/bot.rb', line 40

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



83
84
85
86
87
# File 'lib/jambots/bot.rb', line 83

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

#load_conversation(conversation_name) ⇒ Object



96
97
98
99
100
101
102
103
104
105
# File 'lib/jambots/bot.rb', line 96

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:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/jambots/bot.rb', line 65

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 ChatClientError, handle_error(response) if response["error"]

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

#new_conversationObject



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

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