ask-ai 0.0.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9aac9c44ecfb8fd4a68b1329f7dc48e37b09910011b7a1d1ad085f2afd48407
4
- data.tar.gz: c3b58592fce1e23ae7184a3b6d37d58451b8da82992c90dd503c4705a1fb94ff
3
+ metadata.gz: 3d0033fda00a5a8399a6e9b71c75338b02269df54edb791bd82215e939492d15
4
+ data.tar.gz: 391d4cc9fe240289358f2489b61224b8d0706254174f9ad4a5ec7a109b7b3a89
5
5
  SHA512:
6
- metadata.gz: f075fc93f55659c6f8d9331f5e508dcc6ac9f77e52cf4a8e2df2d25e3e727a8bef5f8f253588a4de06b8c67f7f2704792ed62f7c7e98d4337b5df0b843f34652
7
- data.tar.gz: 4d74731c56a046231dc11bd889c37c42e591dfcaebef7e1aaba11d6a0dd64c4942e01474e67f526b2a061a1681d806befa9934f60c070d2b0ead4fa45bc75d8e
6
+ metadata.gz: 6f749624e465e35a8ebcae8b7b9b312d1f4ffdbd8e390043a0fc87dae5eaf680931975eb87369eba855043eff52206c2daf47af95fc5136e7fb0134520275a28
7
+ data.tar.gz: 81d6f56f465808352087d5f53bab44b7a1af2d63292dbba4b5fab7f91b44fd3d78c6a591718d142f6348c6ab78bae8a54d84b2cba73e2164efd32dd3b27d4e1d
data/lib/config.rb ADDED
@@ -0,0 +1,110 @@
1
+ require_relative './files.rb'
2
+
3
+ module Config
4
+ extend Files
5
+ def load_key()
6
+ config = YAML.load_file(config_path)
7
+ config['OPENAI_API_KEY']
8
+ end
9
+
10
+ def save_key(api_key)
11
+ config = YAML.load_file(config_path)
12
+ if config == false
13
+ config = {}
14
+ end
15
+ config['OPENAI_API_KEY'] = api_key
16
+ File.open(config_path, 'w') { |f| YAML.dump(config, f) }
17
+ end
18
+
19
+ def load_temperature
20
+ config = YAML.load_file(config_path)
21
+ unless config == false
22
+ config['TEMPERATURE']
23
+ end
24
+ end
25
+
26
+ def save_temperature(temperature)
27
+ config = YAML.load_file(config_path)
28
+ if config == false
29
+ config = {}
30
+ end
31
+ config['TEMPERATURE'] = temperature.to_f
32
+ File.open(config_path, 'w') { |f| YAML.dump(config, f) }
33
+ end
34
+
35
+ def load_context_length
36
+ config = YAML.load_file(config_path)
37
+ unless config == false
38
+ config['CONTEXT_LENGTH']
39
+ end
40
+ end
41
+
42
+ def save_context_length(context_length)
43
+ config = YAML.load_file(config_path)
44
+ if config == false
45
+ config = {}
46
+ end
47
+ config['CONTEXT_LENGTH'] = context_length.to_i
48
+ File.open(config_path, 'w') { |f| YAML.dump(config, f) }
49
+ end
50
+
51
+ def set_config(value)
52
+ if value.include?('key')
53
+ stript_value = value.sub(/^key/, '').strip
54
+ if stript_value.empty?
55
+ return 'No API key given'
56
+ end
57
+ save_key(stript_value)
58
+ return 'API key saved'
59
+ elsif value.include?('temp')
60
+ stript_value = value.sub(/^temp/, '').strip.to_f
61
+ if stript_value.to_f > 1.0 || stript_value.to_f < 0.1
62
+ return 'Temperature must be between 0.1 and 1.0'
63
+ end
64
+ save_temperature(stript_value)
65
+ return 'Temperature saved'
66
+ elsif value.include?('context')
67
+ stript_value = value.sub(/^context/, '').strip.to_i
68
+ if stript_value.to_i > 100 || stript_value.to_i < 1
69
+ return 'Context length must be between 1 and 100'
70
+ end
71
+ save_context_length(stript_value)
72
+ return 'Context length saved'
73
+ else
74
+ return 'Invalid config value'
75
+ end
76
+ end
77
+
78
+ def set_key(api_key: nil)
79
+ if api_key.nil?
80
+ log("Setting API key...")
81
+ log("Enter API key: (or press enter to exit)")
82
+
83
+ while input = Readline.readline("> ", true) do
84
+ if input.empty?
85
+ log("Exiting.")
86
+ exit
87
+ else
88
+ api_key = input.strip
89
+ break
90
+ end
91
+ end
92
+ log("Saving API key...")
93
+ end
94
+
95
+ FileUtils.mkdir_p(File.dirname(config_path))
96
+ File.open(config_path, "w") do |f|
97
+ f.write(YAML.dump({ "OPENAI_API_KEY" => api_key }))
98
+ end
99
+ log("API key saved.")
100
+ log("")
101
+ end
102
+
103
+ def load_env()
104
+ #Config.load_key()
105
+ YAML.load(File.read(config_path))
106
+
107
+ rescue Errno::ENOENT
108
+ log("No config.yml found.")
109
+ end
110
+ end
data/lib/context.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require_relative './files.rb'
2
-
2
+ require_relative './config.rb'
3
3
  class Context
4
- include Files
4
+ extend Files, Config, Logging
5
5
  def self.load_context()
6
- if File.exist?(Files.context_path)
7
- conversation = File.readlines(Files.context_path).map { |line| JSON.parse(line) }
6
+ if File.exist?(context_path)
7
+ conversation = File.readlines(context_path).map { |line| JSON.parse(line) }
8
8
  else
9
9
  conversation = []
10
10
  end
@@ -27,46 +27,51 @@ class Context
27
27
  ## Here we save the context to a file.
28
28
  ## Max 10 previous Q / A to save tokens.
29
29
  def self.save_context(context)
30
+ return if context.nil?
30
31
  tmp_arr = []
31
- unless File.exist?(Files.context_path)
32
- File.open(Files.context_path, "w") {}
32
+ unless File.exist?(context_path)
33
+ File.open(context_path, "w") {}
33
34
  end
34
- File.readlines(Files.context_path).map { |line| tmp_arr.push(JSON.parse(line)) }
35
- if tmp_arr.length > 9
35
+ File.readlines(context_path).map { |line| tmp_arr.push(JSON.parse(line)) }
36
+ length = load_context_length().nil? ? 10 : load_context_length()
37
+ if tmp_arr.length > length
36
38
  tmp_arr.shift()
37
39
  end
38
- File.truncate(Files.context_path, 0)
39
- tmp_arr.each { |line| File.open(Files.context_path, "a") { |file| file.write("#{line.to_json}\n") } }
40
- File.open(Files.context_path, "a") { |file| file.write("#{context.to_json}\n") }
40
+ File.truncate(context_path, 0)
41
+ tmp_arr.each { |line| File.open(context_path, "a") { |file| file.write("#{line.to_json}\n") } }
42
+ File.open(context_path, "a") { |file| file.write("#{context.to_json}\n") }
41
43
  end
42
44
 
43
45
  def self.delete_context()
44
- Logging.log("Deleting previous context.")
45
- File.truncate(Files.context_path, 0)
46
+ log("Deleting previous context.")
47
+ File.truncate(context_path, 0)
46
48
  end
47
49
 
48
50
  def self.save_context_file(file_path)
49
51
  unless file_path.nil?
50
52
  file_in = File.open(file_path, 'r')
51
- file_out = File.open(Files.context_file_path, 'w')
53
+ file_out = File.open(context_file_path, 'w')
52
54
  char_count = 0
53
55
  file_in.each do |line|
56
+ puts "Line: #{line}"
54
57
  char_count += line.length
55
58
  file_out.write(line)
56
59
  end
60
+ file_in.close
61
+ file_out.close
57
62
 
58
63
  if char_count > 10000
59
- Logging.log("Warning: The file you are trying to feed to the API is #{char_count} characters long. This consumes a lot of tokens.")
64
+ log("Warning: The file you are trying to feed to the API is #{char_count} characters long. This consumes a lot of tokens.")
60
65
  end
61
66
  else
62
- Logging.log("No file path given.")
67
+ log("No file path given.")
63
68
  end
64
69
  rescue Errno::ENOENT
65
- Logging.log("No file at '#{file_path}' found.")
70
+ log("No file at '#{file_path}' found.")
66
71
  end
67
72
 
68
73
  def self.load_context_file()
69
- file = File.open(Files.context_file_path, 'r')
74
+ file = File.open(context_file_path, 'r')
70
75
  file_as_string = ""
71
76
  file.each do |line|
72
77
  file_as_string += line
@@ -74,8 +79,8 @@ class Context
74
79
 
75
80
  return file_as_string
76
81
  rescue Errno::ENOENT
77
- Logging.log("No file at '#{Files.context_file_path}' found.")
78
- Logging.log("Load a file with 'aa -lf <file_path>'")
82
+ log("No file at '#{context_file_path}' found.")
83
+ log("Load a file with 'aa -lf <file_path>'")
79
84
  return ""
80
85
  end
81
86
 
data/lib/files.rb CHANGED
@@ -1,21 +1,21 @@
1
1
  module Files
2
- def self.root
2
+ def root
3
3
  File.expand_path("./../", __dir__)
4
4
  end
5
5
 
6
- def self.file_path
6
+ def file_path
7
7
  File.expand_path("./../files/", __dir__)
8
8
  end
9
9
 
10
- def self.context_path
10
+ def context_path
11
11
  File.expand_path("./../files/context.jsonl", __dir__)
12
12
  end
13
13
 
14
- def self.config_path
14
+ def config_path
15
15
  File.expand_path("./../config/config.yml", __dir__)
16
16
  end
17
17
 
18
- def self.context_file_path
18
+ def context_file_path
19
19
  File.expand_path("./../files/context_file.txt", __dir__)
20
20
  end
21
21
  end
data/lib/help.rb CHANGED
@@ -1,48 +1,49 @@
1
1
  require 'rubygems'
2
2
 
3
- class Help
4
- def self.display_help()
5
- Logging.log("Usage: aa [options] [input]")
6
- Logging.log(" -lf, --loadfile <path>: Load file into context")
7
- Logging.log(" -f, --file: Read from context file")
8
- Logging.log(" -c, --conversation: Append to conversation (max 10 Questions / Answers pairs saved)")
9
- Logging.log(" -d, --delete: Delete conversation")
10
- Logging.log(" -i, --interactive: Interactive mode, always a conversation. Clear context with 'clear' (exit with 'exit' or 'quit')")
11
- Logging.log(" -w, --whisper <path>: Transcribe audio file")
12
- Logging.log(" -t, --translate <path>: Translate audio file")
13
- Logging.log("\n Options:")
14
- Logging.log(" --config: Edit config file")
15
- Logging.log(" -v, --version: Display version")
16
- Logging.log(" -h, --help: Display this help message")
17
3
 
18
- end
19
-
20
- def self.display_api_key()
21
- Logging.log("You need to set your API key in the file: ./config/config.yml")
22
- Logging.log("Create the file if it doesn't exist.")
23
- Logging.log("Add the following line to the file:")
24
- Logging.log(" OPENAI_API_KEY: <your API key>")
25
- Logging.log("You can get your API key from: https://openai.com/")
26
- end
4
+ class Help
5
+ extend Logging
27
6
 
28
- ## This don't work yet. Need to rework the way we handle args.
29
- def self.display_help_file()
30
- ## TODO: How to work with files
7
+ def self.display_version()
8
+ ## Without using gemspec
9
+ spec = Gem::Specification::find_by_name("ask-ai")
10
+ log("Version: ask-ai-#{spec.version}")
31
11
  end
32
12
 
33
- ## This don't work yet. Need to rework the way we handle args.
34
- def self.display_help_conversation()
35
- ## TODO: How to work with conversation
36
- end
13
+ def self.interactive_help(command)
14
+ case command
15
+ when '-w'
16
+ log("Ex: -w /home/name/sound_file.m4a")
17
+ log("Will transcribe the audio file.")
18
+ when '-t'
19
+ log("Ex: -t /home/name/sound_file.m4a")
20
+ log("Will translate the audio file to English.")
21
+ when '-lf'
22
+ log("Ex: -lf /home/name/some_text_file.txt'")
23
+ log("Will load the file into context.")
24
+ log("The file should a [txt, CSV]. More formats coming soon.")
25
+ when '-f'
26
+ log("Ex: -f Can you describe the file i provided?")
27
+ when 'config'
28
+ log("Ex: config key <your API key>")
29
+ log("Ex: config temp <0.0 - 1.0>")
30
+ log("Ex: config context <0 - 100>")
31
+ log("Beaware that the more context you use, the more expensive it will be.")
32
+ else
33
+ log("No help for: #{command}")
34
+ end
37
35
 
38
- def self.display_version()
39
- spec = Gem::Specification::load("ask-ai.gemspec")
40
- Logging.log("Version: #{spec.version}")
41
36
  end
42
37
 
43
- def self.display_usage()
44
- Logging.log("Usage: ./main.rb [options] [input]")
45
-
46
- Logging.log("There are two types of options, flags and arguments.")
38
+ def self.interactive_desc()
39
+ log("Type 'exit' or 'quit' to exit.")
40
+ log("Type 'clear' to clear context.")
41
+ log("Type 'show' to show context.")
42
+ log("Type 'help' to show help.")
43
+ log("Type 'config [key, temp, context]' to change config.")
44
+ log("Type '-w <filepath>' to whisper transcribe.")
45
+ log("Type '-t' <filepath> to whisper translate.")
46
+ log("Type '-lf' <filepath> to load file.")
47
+ log("Type '-f' to use loaded file as context.")
47
48
  end
48
49
  end
data/lib/logging.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'logger'
2
2
 
3
3
  module Logging
4
- def self.log(msg)
4
+ def log(msg)
5
5
  logger = Logger.new(STDOUT)
6
6
  logger.formatter = proc { |_severity, _datetime, _progname, msg| "#{msg}\n" }
7
7
  logger.info(msg)
data/lib/main.rb CHANGED
@@ -6,175 +6,80 @@ require 'readline'
6
6
  require 'io/console'
7
7
  require_relative './logging.rb'
8
8
  require_relative './prompt.rb'
9
- require_relative './handle_args.rb'
10
9
  require_relative './help.rb'
11
10
  require_relative './context.rb'
12
11
  require_relative './files.rb'
12
+ require_relative './config.rb'
13
13
 
14
14
  class Main
15
- include Logging
16
- include Files
17
- def self.run()
18
- config = load_env()
19
-
20
- ## This does not work. Need to fix this.
21
- if config == false
22
- Logging.log("No API key found.")
23
- Help.display_api_key()
24
- Logging.log('If you want to set your API key now, type (y)es and press enter.')
25
- while input = Readline.readline("> ", true) do
26
- if input.empty?
27
- Logging.log("Exiting.")
28
- exit
29
- elsif input == "y" || input == "yes" || input == "Y" || input == "Yes"
30
- set_key()
31
- exit
32
- else
33
- Logging.log('Invalid input (y)es or press enter to exit.')
34
- end
35
- end
36
- end
37
-
38
- context = Context.load_context()
39
- options_and_input = HandleArgs.handle_args()
40
- options = options_and_input.select { |k, v| k.start_with?("option_") }
41
- input = options_and_input["input"]
15
+ extend Logging, Files, Config
16
+ LIST = [
17
+ "exit", "quit", "version", "clear", "help", "show",
18
+ "-w", "-t", "-lf", "-f", "config", "temp", "context"
19
+ ].sort
42
20
 
43
- halt_options = ["-h", "--help", "-v", "--version", "--key"]
21
+ def self.run()
44
22
 
45
- ## Hack... Need to fix this.
46
- if options.empty?
47
- options = { "option_0" => "simple" }
48
- end
23
+ ## When using Readline, TAB will auto-complete
24
+ ## But it will only auto-complete from the LIST
25
+ ## Need to handle directories and files when -lf, -w, -t are used
26
+ #comp = proc { |s| LIST.grep(/^#{Regexp.escape(s)}/) }
27
+ #Readline.completion_append_character = ""
28
+ #Readline.completion_proc = comp
49
29
 
50
- options.each do |k, v|
51
- if halt_options.include?(v)
52
- ## Options that halt the program.
53
- case v
54
- when "-h", "--help"
55
- Help.display_help()
56
- exit
57
- when "-v", "--version"
58
- Help.display_version()
59
- exit
60
-
61
- when "--key"
62
- set_key(api_key: nil)
63
- else
64
- Help.display_help()
65
- exit
30
+ Help.interactive_desc()
31
+ while input = Readline.readline("\n> ", true) do
32
+ case input
33
+ when "exit", "quit"
34
+ break
35
+ when "version"
36
+ Help.display_version()
37
+ when "clear"
38
+ log("Clearing context...")
39
+ Context.delete_context()
40
+ when 'help'
41
+ Help.interactive_desc()
42
+ when /^help/
43
+ strip_input = input.sub(/^help/, "").strip
44
+ Help.interactive_help(strip_input)
45
+ when "show"
46
+ log("\n")
47
+ log(Context.load_context())
48
+ when /^-w/
49
+ stript_input = input.sub(/^-w/, "").strip
50
+ log(Prompt.whisper_transcribe(stript_input, interactive: true))
51
+ when /^-t/
52
+ stript_input = input.sub(/^-t/, "").strip
53
+ log(Prompt.whisper_translate(stript_input, interactive: true))
54
+ when /^-lf/
55
+ stript_input = input.sub(/^-lf/, "").strip
56
+ log("Loading File #{stript_input}")
57
+ Context.save_context_file(stript_input)
58
+ when /^-f/
59
+ stript_input = input.sub(/^-f/, "").strip
60
+ file_as_string = Context.load_context_file()
61
+ if file_as_string.empty?
62
+ log("No file loaded.")
63
+ next
66
64
  end
67
- else
68
- ## Options that don't halt the program.
69
- case v
70
- when "-f", "--file"
71
- file_as_string = Context.load_context_file()
72
- if file_as_string.empty?
73
- exit
74
- end
75
- Prompt.stream_prompt(input, file_as_string)
76
- when "-lf", "--loadfile"
77
- Logging.log("Loading File #{input}")
78
- Context.save_context_file(input)
79
- when "-d", "--delete"
80
- if input.nil?
81
- Context.delete_context()
82
- else
83
- Context.delete_context()
84
- Context.save_context(Prompt.stream_prompt(input, context))
85
- end
86
- when "-c", "--conversation"
87
- Logging.log(input)
88
- Context.save_context(Prompt.stream_prompt(input, context))
89
- when "-w", "--whisper"
90
- Logging.log(Prompt.whisper_transcribe(input))
91
- when "-t", "--translate"
92
- Logging.log(Prompt.whisper_translate(input))
93
- when "-i", "--interactive"
94
- Logging.log("Interactive mode...")
95
- Logging.log("Type 'exit' or 'quit' to exit.")
96
- Logging.log("Type 'clear' to clear context.")
97
- Logging.log("Type 'show' to show context.")
98
- Logging.log("Type 'help' to show help.")
99
- Logging.log("Type 'config' to change config.")
100
- Logging.log("Type '-w' to whisper transcribe.")
101
- Logging.log("Type '-t' to whisper translate.")
102
-
103
- while input = Readline.readline("\n> ", true) do
104
- case input
105
- when "exit", "quit"
106
- break
107
- when "clear"
108
- Logging.log("Clearing context...")
109
- Context.delete_context()
110
- when "help"
111
- #TODO: This should be a specific help for interactive.
112
- Help.display_help()
113
- when "show"
114
- Logging.log("\n")
115
- Logging.log(Context.load_context())
116
- when /^-w/
117
- stript_input = input.sub(/^-w/, "").strip
118
- Logging.log(Prompt.whisper_transcribe(stript_input, interactive: true))
119
- when /^-t/
120
- stript_input = input.sub(/^-t/, "").strip
121
- Logging.log(Prompt.whisper_translate(stript_input, interactive: true))
122
- when "config"
123
- set_key(api_key: nil)
124
- else
125
- #options_and_input = HandleArgs.handle_args()
126
- context = Context.load_context()
127
- Logging.log("")
128
- Context.save_context(Prompt.stream_prompt(input, context))
129
- Logging.log("")
130
- end
131
- end
132
- Logging.log("Exiting...")
133
- when "simple"
134
- if !input.nil?
135
- Prompt.stream_prompt(input)
136
- else
137
- Logging.log("No input given.")
138
- Help.display_help()
139
- end
140
- else
141
- Help.display_help()
142
- end
143
- end
144
- end
145
- end
146
-
147
- private
148
-
149
- def self.set_key(api_key: nil)
150
- if api_key.nil?
151
- Logging.log("Setting API key...")
152
- Logging.log("Enter API key: (or press enter to exit)")
153
-
154
- while input = Readline.readline("> ", true) do
155
- if input.empty?
156
- Logging.log("Exiting.")
157
- exit
158
- else
159
- api_key = input.strip
160
- break
65
+ log("")
66
+ Prompt.stream_prompt(stript_input, file_as_string)
67
+ log("")
68
+ when ""
69
+ log("No input given.")
70
+ when /^config/
71
+ strip_input = input.sub(/^config/, "").strip
72
+ res = set_config(strip_input)
73
+ if res.is_a?(String)
74
+ log(res)
161
75
  end
76
+ else
77
+ context = Context.load_context()
78
+ log("")
79
+ Context.save_context(Prompt.stream_prompt(input, context))
80
+ log("")
162
81
  end
163
- Logging.log("Saving API key...")
164
82
  end
165
-
166
- FileUtils.mkdir_p(File.dirname(Files.config_path))
167
- File.open(Files.config_path, "w") do |f|
168
- f.write(YAML.dump({ "OPENAI_API_KEY" => api_key }))
169
- end
170
- Logging.log("API key saved.")
171
- end
172
-
173
- def self.load_env()
174
- YAML.load(File.read(Files.config_path))
175
-
176
- rescue Errno::ENOENT
177
- Logging.log("No config.yml found.")
178
83
  end
179
84
  end
180
85
 
data/lib/prompt.rb CHANGED
@@ -1,33 +1,39 @@
1
1
  require "openai"
2
2
  require_relative './files.rb'
3
+ require_relative './config.rb'
3
4
 
4
5
  class Prompt
5
- include Files
6
+ extend Files, Config, Logging
6
7
  ## Streams the response, VERY NICE
7
- def self.stream_prompt(input, conversation = '', temp = 0.7)
8
+ def self.stream_prompt(input, conversation = '', temp = load_temperature())
9
+ if temp.nil?
10
+ temp = 0.7
11
+ end
8
12
  if conversation.length == 0
9
13
  conversation += input
10
14
  else
11
15
  conversation += "\n My question: #{input}"
12
16
  end
13
17
  response = ''
14
- client.chat(
15
- parameters: {
16
- model: "gpt-3.5-turbo",
17
- messages: [{ role: "user", content: conversation}],
18
- temperature: temp, ## Should be a parameter
19
- stream: proc do |chunk, _bytesize|
20
- response += chunk.dig("choices", 0, "delta", "content") unless chunk.dig("choices", 0, "delta", "content").nil?
21
- print chunk.dig("choices", 0, "delta", "content")
22
- end
18
+ unless client.nil?
19
+ client.chat(
20
+ parameters: {
21
+ model: "gpt-3.5-turbo",
22
+ messages: [{ role: "user", content: conversation}],
23
+ temperature: temp, ## Should be a parameter
24
+ stream: proc do |chunk, _bytesize|
25
+ response += chunk.dig("choices", 0, "delta", "content") unless chunk.dig("choices", 0, "delta", "content").nil?
26
+ print chunk.dig("choices", 0, "delta", "content")
27
+ end
28
+ }
29
+ )
30
+ context = {
31
+ "input" => input,
32
+ "response" => response,
23
33
  }
24
- )
25
- context = {
26
- "input" => input,
27
- "response" => response,
28
- }
29
34
 
30
- return context
35
+ return context
36
+ end
31
37
  end
32
38
 
33
39
  ## Not implemented only scaffolding
@@ -42,7 +48,7 @@ class Prompt
42
48
 
43
49
  def self.whisper_translate(file_path, interactive = false)
44
50
  if (file_path.nil? || !file_path.end_with?(*['.mp3', '.wav', '.m4a', '.webm', '.mpeg', '.mpga']))
45
- Logging.log("No file given or wrong file type")
51
+ log("No file given or wrong file type")
46
52
  unless interactive
47
53
  exit
48
54
  end
@@ -54,27 +60,29 @@ class Prompt
54
60
  exit
55
61
  end
56
62
  else
57
- response = client.audio.translate(
58
- parameters: {
59
- model: "whisper-1",
60
- file: File.open(file_path, "rb"),
61
- })
62
- if (response["text"].nil? || response["text"].empty?)
63
- Logging.log("No text found")
64
- unless interactive
65
- exit
63
+ unless client.nil?
64
+ response = client.audio.translate(
65
+ parameters: {
66
+ model: "whisper-1",
67
+ file: File.open(file_path, "rb"),
68
+ })
69
+ if (response["text"].nil? || response["text"].empty?)
70
+ log("No text found")
71
+ unless interactive
72
+ exit
73
+ end
66
74
  end
75
+ return response["text"]
67
76
  end
68
- return response["text"]
69
77
  end
70
78
  end
71
79
  rescue Errno::ENOENT => e
72
- Logging.log(e)
80
+ log(e)
73
81
  end
74
82
 
75
83
  def self.whisper_transcribe(file_path, interactive = false)
76
84
  if (file_path.nil? || !file_path.end_with?(*['.mp3', '.wav', '.m4a', '.webm', '.mpeg', '.mpga']))
77
- Logging.log("No file given")
85
+ log("No file given")
78
86
  unless interactive
79
87
  exit
80
88
  end
@@ -86,31 +94,40 @@ class Prompt
86
94
  exit
87
95
  end
88
96
  else
89
- response = client.audio.transcribe(
90
- parameters: {
91
- model: "whisper-1",
92
- file: File.open(file_path, "rb"),
93
- })
94
- if (response["text"].nil? || response["text"].empty?)
95
- Logging.log("No text found")
96
- unless interactive
97
- exit
97
+ unless client.nil?
98
+ response = client.audio.transcribe(
99
+ parameters: {
100
+ model: "whisper-1",
101
+ file: File.open(file_path, "rb"),
102
+ })
103
+ if (response["text"].nil? || response["text"].empty?)
104
+ log("No text found")
105
+ unless interactive
106
+ exit
107
+ end
98
108
  end
109
+ return response["text"]
99
110
  end
100
- return response["text"]
101
111
  end
102
112
  end
103
113
  rescue Errno::ENOENT => e
104
114
  #Logging.log("File not found")
105
- Logging.log(e)
115
+ log(e)
106
116
  end
107
117
 
108
118
  private
109
119
 
110
120
  def self.client()
111
- conf = YAML.load(File.read(Files.config_path))
112
- key = conf["OPENAI_API_KEY"]
121
+ conf = YAML.load(File.read(config_path))
122
+ unless conf == false
123
+ key = conf["OPENAI_API_KEY"]
124
+ end
113
125
 
114
- OpenAI::Client.new(access_token: key)
126
+ begin
127
+ OpenAI::Client.new(access_token: key)
128
+ rescue OpenAI::ConfigurationError => e
129
+ log("OpenAI API key not found, run 'config key' to set it")
130
+ return nil
131
+ end
115
132
  end
116
133
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oskar Franck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-03 00:00:00.000000000 Z
11
+ date: 2023-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-openai
@@ -36,13 +36,12 @@ files:
36
36
  - config/config.yml
37
37
  - files/context.jsonl
38
38
  - files/context_file.txt
39
+ - lib/config.rb
39
40
  - lib/context.rb
40
41
  - lib/files.rb
41
- - lib/handle_args.rb
42
42
  - lib/help.rb
43
43
  - lib/logging.rb
44
44
  - lib/main.rb
45
- - lib/paths.rb
46
45
  - lib/prompt.rb
47
46
  homepage: https://github.com/OskarFranck/terminal_chat
48
47
  licenses:
data/lib/handle_args.rb DELETED
@@ -1,61 +0,0 @@
1
- class HandleArgs
2
- def self.permitted_options()
3
- ## TODO: Add more options.
4
- ## -t --translate
5
- ## -temp --temperature (need to handle value after input)
6
-
7
- [
8
- '-h',
9
- '--help',
10
- '-v',
11
- '--version',
12
- '-f',
13
- '--file',
14
- '-lf',
15
- '--loadfile',
16
- '-d',
17
- '--delete',
18
- '-c',
19
- '--conversation',
20
- '--finetune',
21
- '-w', '--whisper',
22
- '-t', '--translate',
23
- '-i', '--interactive',
24
- '--key',
25
- ]
26
- end
27
-
28
- def self.handle_args()
29
- p_args = HandleArgs.permitted_options()
30
- ## This is the hash that will be returned.
31
- args_hash = {}
32
-
33
- ## This handles args then called as ruby script.
34
- ARGV.each_with_index do |arg, i|
35
- #Logging.log("Arg: #{arg}")
36
-
37
- if arg.start_with?('-')
38
- ## This is an option.
39
- if p_args.include?(arg)
40
- ## This is a permitted / available option.
41
- #Logging.log("Option: #{arg}")
42
- args_hash["option_#{i}"] = arg
43
- else
44
- ## This is an unknown option.
45
- ## TODO: Handle unknown option. display help? discard?
46
- Logging.log("Unknown option: #{arg}")
47
- args_hash["option_#{i}"] = arg
48
- end
49
- else
50
- ## This is input.
51
- ## This if statement append all 'input' args to one string.
52
- if args_hash["input"].nil?
53
- args_hash["input"] = arg
54
- else
55
- args_hash["input"] = "#{args_hash['input']} #{arg}"
56
- end
57
- end
58
- end
59
- return args_hash
60
- end
61
- end
data/lib/paths.rb DELETED
@@ -1,26 +0,0 @@
1
-
2
- module Files
3
- def self.root
4
- File.expand_path("./../", __dir__)
5
- end
6
-
7
- def self.context
8
- File.expand_path("./../files/context.jsonl", __dir__)
9
- end
10
-
11
- def self.files
12
- FILE_PATH
13
- end
14
-
15
- def self.config
16
- CONFIG_PATH
17
- end
18
-
19
- def self.context_file
20
- CONTEXT_FILE_PATH
21
- end
22
- end
23
- CONTEXT_PATH = File.expand_path("./../files/context.jsonl", __dir__)
24
- FILE_PATH = File.expand_path("./../files/", __dir__)
25
- CONFIG_PATH = File.expand_path("./../config/config.yml", __dir__)
26
- CONTEXT_FILE_PATH = File.expand_path("./../files/context_file.txt", __dir__)