monadic-chat 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -32,12 +32,8 @@ class MonadicApp
32
32
  false
33
33
  else
34
34
  replacements.each do |key, value|
35
- case @method
36
- when "completions"
37
- @template.gsub!(key, value)
38
- when "chat/completions"
39
- @template["messages"][0]["content"].gsub!(key, value)
40
- end
35
+ @messages[0]["content"].gsub!(key, value)
36
+ messages[0]["content"]
41
37
  end
42
38
  true
43
39
  end
@@ -68,34 +64,58 @@ class MonadicApp
68
64
  when "completions"
69
65
  m = /\n\n```json\s*(\{.+\})\s*```\n\n/m.match(@template)
70
66
  json = m[1].gsub(/(?!\\\\\\)\\\\"/) { '\\\"' }
71
- JSON.parse(json)
67
+ res = JSON.parse(json)
68
+ res["messages"] = @messages
69
+ res
72
70
  when "chat/completions"
73
- @template
71
+ @messages
74
72
  end
75
73
  end
76
74
 
77
75
  def prepare_params(input)
78
76
  params = @params.dup
77
+
78
+ @update_proc.call
79
79
  case @method
80
80
  when "completions"
81
- template = @template.dup.sub("{{PROMPT}}", input).sub("{{MAX_TOKENS}}", (@params["max_tokens"] / 2).to_s)
81
+ messages = +""
82
+ system = +""
83
+ @messages.each do |mes|
84
+ role = mes["role"]
85
+ content = mes["content"]
86
+ case role
87
+ when "system"
88
+ system << "#{content}\n"
89
+ when "assistant", "gpt"
90
+ system << "- #{mes["role"].strip}: #{content.sub("\n\n###\n\n", "")}\n\n###\n\n"
91
+ else
92
+ messages << "- #{mes["role"].strip}: #{mes["content"]}"
93
+ end
94
+ end
95
+ template = @template.dup.sub("{{SYSTEM}}", system)
96
+ .sub("{{PROMPT}}", input)
97
+ .sub("{{MESSAGES}}", messages.strip)
98
+
82
99
  params["prompt"] = template
100
+ @messages << { "role" => "user", "content" => input }
83
101
  when "chat/completions"
84
- @template["messages"] << { "role" => "user", "content" => input }
85
- params["messages"] = @template["messages"]
102
+ @messages << { "role" => "user", "content" => input }
103
+ @update_proc.call
104
+ params["messages"] = @messages
86
105
  end
106
+
87
107
  params
88
108
  end
89
109
 
90
110
  def update_template(res)
91
111
  case @method
92
112
  when "completions"
93
- updated = @update_proc.call(res)
94
- json = updated.to_json.strip
113
+ @metadata = res
114
+ @messages << { "role" => "assistant", "content" => res["response"] }
115
+ json = res.to_json.strip
95
116
  @template.sub!(/\n\n```json.+```\n\n/m, "\n\n```json\n#{json}\n```\n\n")
96
117
  when "chat/completions"
97
- @template["messages"] << { "role" => "assistant", "content" => res }
98
- @template["messages"] = @update_proc.call(@template["messages"])
118
+ @messages << { "role" => "assistant", "content" => res }
99
119
  end
100
120
  end
101
121
 
@@ -110,6 +130,7 @@ class MonadicApp
110
130
  wait
111
131
 
112
132
  params = prepare_params(input)
133
+
113
134
  print TTY::Cursor.save
114
135
 
115
136
  escaping = +""
@@ -158,6 +179,7 @@ class MonadicApp
158
179
  print "\n"
159
180
 
160
181
  update_template(res)
182
+ set_html if @html
161
183
  end
162
184
 
163
185
  def bind_research_mode(input, num_retry: 0)
@@ -166,6 +188,7 @@ class MonadicApp
166
188
  wait
167
189
 
168
190
  params = prepare_params(input)
191
+
169
192
  print TTY::Cursor.save
170
193
 
171
194
  @threads << true
@@ -179,7 +202,7 @@ class MonadicApp
179
202
  finished = false
180
203
  response = +""
181
204
  spinning = false
182
- res = @completion.run(params, num_retry: num_retry) do |chunk|
205
+ res = @completion.run(params, num_retry: num_retry, tmp_json_file: TEMP_JSON, tmp_md_file: TEMP_MD) do |chunk|
183
206
  if finished && !response_all_shown
184
207
  response_all_shown = true
185
208
  @responses << response.sub(/\s+###\s*".*/m, "")
@@ -265,5 +288,6 @@ class MonadicApp
265
288
  break
266
289
  end
267
290
  end
291
+ set_html if @html
268
292
  end
269
293
  end
@@ -9,16 +9,16 @@ class MonadicApp
9
9
  clear_screen
10
10
  print TTY::Cursor.save
11
11
  parameter = PROMPT_SYSTEM.select("Select function:", per_page: 10, cycle: true, filter: true, default: 1, show_help: :never) do |menu|
12
- menu.choice "#{BULLET} #{PASTEL.bold("cancel/return/escape")} cancel this menu", "cancel"
13
- menu.choice "#{BULLET} #{PASTEL.bold("params/settings/config")} show and change values of parameters", "params"
14
- menu.choice "#{BULLET} #{PASTEL.bold("data/context")} show currrent contextual info", "data"
15
- menu.choice "#{BULLET} #{PASTEL.bold("html")} view contextual info on the web browser", "html"
16
- menu.choice "#{BULLET} #{PASTEL.bold("reset")} reset context to original state", "reset"
17
- menu.choice "#{BULLET} #{PASTEL.bold("save")} save current contextual info to file", "save"
18
- menu.choice "#{BULLET} #{PASTEL.bold("load")} load current contextual info from file", "load"
19
- menu.choice "#{BULLET} #{PASTEL.bold("clear/clean")} clear screen", "clear"
20
- menu.choice "#{BULLET} #{PASTEL.bold("readme/documentation")} open readme/documentation", "readme"
21
- menu.choice "#{BULLET} #{PASTEL.bold("exit/bye/quit")} go back to main menu", "exit"
12
+ menu.choice "#{BULLET} #{PASTEL.bold("cancel/return/escape")} Cancel this menu", "cancel"
13
+ menu.choice "#{BULLET} #{PASTEL.bold("params/settings/config")} Show and change values of parameters", "params"
14
+ menu.choice "#{BULLET} #{PASTEL.bold("data/context")} Show currrent contextual info", "data"
15
+ menu.choice "#{BULLET} #{PASTEL.bold("html")} View contextual info on the web browser", "html"
16
+ menu.choice "#{BULLET} #{PASTEL.bold("reset")} Reset context to initial state", "reset"
17
+ menu.choice "#{BULLET} #{PASTEL.bold("save")} Save current contextual info to file", "save"
18
+ menu.choice "#{BULLET} #{PASTEL.bold("load")} Load current contextual info from file", "load"
19
+ menu.choice "#{BULLET} #{PASTEL.bold("clear/clean")} Clear screen", "clear"
20
+ menu.choice "#{BULLET} #{PASTEL.bold("readme/documentation")} Open readme/documentation", "readme"
21
+ menu.choice "#{BULLET} #{PASTEL.bold("exit/bye/quit")} Go back to main menu", "exit"
22
22
  end
23
23
 
24
24
  print TTY::Cursor.restore
@@ -33,7 +33,8 @@ class MonadicApp
33
33
  when "data"
34
34
  show_data
35
35
  when "html"
36
- set_html
36
+ @html = true
37
+ show_html
37
38
  when "reset"
38
39
  reset
39
40
  when "save"
@@ -52,14 +53,10 @@ class MonadicApp
52
53
  end
53
54
 
54
55
  def reset
55
- @params = @params_original.dup
56
-
57
- case @method
58
- when "completions"
59
- @template = @template_original.dup
60
- when "chat/completions"
61
- @template = JSON.parse @template_original
62
- end
56
+ @html = false
57
+ @params = @params_initial.dup
58
+ @messages = @messages_initial.dup
59
+ @template = @template_initial.dup
63
60
 
64
61
  if @placeholders.empty?
65
62
  print PROMPT_SYSTEM.prefix
@@ -133,9 +130,11 @@ class MonadicApp
133
130
  case @method
134
131
  when "completions"
135
132
  m = /\n\n```json\s*(\{.+\})\s*```\n\n/m.match(@template)
136
- f.write JSON.pretty_generate(JSON.parse(m[1]))
133
+ data = JSON.parse(m[1])
134
+ data["messages"] = @messages
135
+ f.write JSON.pretty_generate(data)
137
136
  when "chat/completions"
138
- f.write JSON.pretty_generate(@template)
137
+ f.write JSON.pretty_generate({ "messages" => @messages })
139
138
  end
140
139
 
141
140
  print "Data has been saved successfully\n"
@@ -170,14 +169,17 @@ class MonadicApp
170
169
  data = JSON.parse(json)
171
170
  case @method
172
171
  when "completions"
172
+ self.class.name.downcase.split("::")[-1]
173
+
173
174
  raise unless data["mode"] == self.class.name.downcase.split("::")[-1]
174
175
 
175
- new_template = @template.sub(/\n\n```json\s*\{.+\}\s*```\n\n/m, "\n\n```json\n#{JSON.pretty_generate(data).strip}\n```\n\n")
176
- @template = new_template
176
+ @messages = data.delete "messages"
177
+ @template = @template.sub(/\n\n```json\s*\{.+\}\s*```\n\n/m, "\n\n```json\n#{JSON.pretty_generate(data).strip}\n```\n\n")
177
178
  when "chat/completions"
179
+ pp data
178
180
  raise unless data["messages"] && data["messages"][0]["role"]
179
181
 
180
- @template["messages"] = data["messages"]
182
+ @messages = data["messages"]
181
183
  end
182
184
  print "Data has been loaded successfully\n"
183
185
  true
@@ -81,16 +81,15 @@ module OpenAI
81
81
  class Completion
82
82
  attr_reader :access_token
83
83
 
84
- def initialize(access_token, tmp_file: nil)
84
+ def initialize(access_token)
85
85
  @access_token = access_token
86
- @tmp_file = tmp_file
87
86
  end
88
87
 
89
88
  def models
90
89
  OpenAI.models(@access_token)
91
90
  end
92
91
 
93
- def run(params, num_retry: 1, &block)
92
+ def run(params, num_retry: 1, tmp_json_file: nil, tmp_md_file: nil, &block)
94
93
  method = OpenAI.model_to_method(params["model"])
95
94
 
96
95
  response = OpenAI.query(@access_token, "post", method, 60, params, &block)
@@ -102,7 +101,8 @@ module OpenAI
102
101
 
103
102
  case method
104
103
  when "completions"
105
- get_json response ["choices"][0]["text"]
104
+ File.open(tmp_md_file, "w") { |f| f.write params["prompt"] } if tmp_md_file
105
+ get_json(response["choices"][0]["text"], tmp_json_file: tmp_json_file)
106
106
  when "chat/completions"
107
107
  response ["choices"][0]["text"]
108
108
  end
@@ -115,7 +115,7 @@ module OpenAI
115
115
  end
116
116
  end
117
117
 
118
- def get_json(data)
118
+ def get_json(data, tmp_json_file: nil)
119
119
  case data
120
120
  when %r{<JSON>\n*(\{.+\})\n*</JSON>}m
121
121
  json = Regexp.last_match(1).gsub(/\r\n?/, "\n").gsub(/\r\n/) { "\n" }
@@ -126,7 +126,7 @@ module OpenAI
126
126
  else
127
127
  res = data
128
128
  end
129
- File.open(@tmp_file, "w") { |f| f.write json } if @tmp_file
129
+ File.open(tmp_json_file, "w") { |f| f.write json } if tmp_json_file
130
130
  res
131
131
  end
132
132
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MonadicChat
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/monadic_chat.rb CHANGED
@@ -46,6 +46,7 @@ module MonadicChat
46
46
 
47
47
  TEMP_HTML = File.join(Dir.home, "monadic_chat.html")
48
48
  TEMP_JSON = File.join(Dir.home, "monadic_chat.json")
49
+ TEMP_MD = File.join(Dir.home, "monadic_chat.md")
49
50
 
50
51
  style = +File.read(File.join(__dir__, "..", "assets", "github.css")).gsub(".markdown-") { "" }
51
52
  style << File.read(File.join(__dir__, "..", "assets", "pigments-default.css"))
@@ -126,7 +127,7 @@ module MonadicChat
126
127
  raise if OpenAI.models(token).empty?
127
128
 
128
129
  print "success\n"
129
- OpenAI::Completion.new(token, tmp_file: TEMP_JSON)
130
+ OpenAI::Completion.new(token)
130
131
  rescue StandardError
131
132
  print "failure.\n"
132
133
  false
data/monadic_chat.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  DESC
15
15
  spec.homepage = "https://github.com/yohasebe/monadic-chat"
16
16
  spec.license = "MIT"
17
- spec.required_ruby_version = ">= 2.6.0"
17
+ spec.required_ruby_version = ">= 2.6.10"
18
18
 
19
19
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
20
 
@@ -36,7 +36,6 @@ Gem::Specification.new do |spec|
36
36
  spec.add_development_dependency "bundler"
37
37
  spec.add_development_dependency "rake"
38
38
  spec.add_development_dependency "rspec"
39
- spec.add_development_dependency "solargraph"
40
39
 
41
40
  spec.add_dependency "http"
42
41
  spec.add_dependency "kramdown"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monadic-chat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yohasebe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-12 00:00:00.000000000 Z
11
+ date: 2023-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: solargraph
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: http
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -261,6 +247,7 @@ extensions: []
261
247
  extra_rdoc_files: []
262
248
  files:
263
249
  - ".rspec"
250
+ - ".ruby-version"
264
251
  - CHANGELOG.md
265
252
  - Gemfile
266
253
  - Gemfile.lock
@@ -273,6 +260,9 @@ files:
273
260
  - apps/code/code.json
274
261
  - apps/code/code.md
275
262
  - apps/code/code.rb
263
+ - apps/linguistic/linguistic.json
264
+ - apps/linguistic/linguistic.md
265
+ - apps/linguistic/linguistic.rb
276
266
  - apps/novel/novel.json
277
267
  - apps/novel/novel.md
278
268
  - apps/novel/novel.rb
@@ -289,7 +279,6 @@ files:
289
279
  - doc/img/input-acess-token.png
290
280
  - doc/img/langacker-2001.svg
291
281
  - doc/img/linguistic-html.png
292
- - doc/img/monadic-chat-main-menu.png
293
282
  - doc/img/monadic-chat.svg
294
283
  - doc/img/readme-example-beatles-html.png
295
284
  - doc/img/readme-example-beatles.png
@@ -310,9 +299,6 @@ files:
310
299
  - lib/monadic_chat/parameters.rb
311
300
  - lib/monadic_chat/version.rb
312
301
  - monadic_chat.gemspec
313
- - samples/linguistic/linguistic.json
314
- - samples/linguistic/linguistic.md
315
- - samples/linguistic/linguistic.rb
316
302
  homepage: https://github.com/yohasebe/monadic-chat
317
303
  licenses:
318
304
  - MIT
@@ -329,14 +315,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
329
315
  requirements:
330
316
  - - ">="
331
317
  - !ruby/object:Gem::Version
332
- version: 2.6.0
318
+ version: 2.6.10
333
319
  required_rubygems_version: !ruby/object:Gem::Requirement
334
320
  requirements:
335
321
  - - ">="
336
322
  - !ruby/object:Gem::Version
337
323
  version: '0'
338
324
  requirements: []
339
- rubygems_version: 3.4.8
325
+ rubygems_version: 3.4.1
340
326
  signing_key:
341
327
  specification_version: 4
342
328
  summary: Highly configurable CLI client app for OpenAI chat/text-completion API
Binary file
@@ -1,39 +0,0 @@
1
- You are an English syntactic/semantic/pragmatic analyzer. Analyze the new prompt from the user below and execute a syntactic parsing. Give your response in a variation of the penn treebank format, but use brackets [ ] instead of parentheses ( ). Also, give your response in a markdown code span. The sentence must always be parsed if the user's input sentence is enclosed in double quotes. Create a response to the following new prompt from the user and set your response to the "response" property of the JSON object shown below. All prompts by "user" in the "messages" property are continuous in content. If pasing the input sentence is extremely difficult, or the input is not enclosed in double quotes, let the user know.
2
-
3
- NEW PROMPT: {{PROMPT}}
4
-
5
- ```json
6
- {
7
- "prompt": "\"We didn't have a camera.\"",
8
- "response": "`[S [NP We] [VP [V didn't] [VP [V have] [NP [Det a] [N camera] ] ] ] ] ]`\n\n###\n\n",
9
- "mode": "linguistic",
10
- "turns": 3,
11
- "sentence_type": ["declarative"],
12
- "sentiment": ["sad"],
13
- "summary": "The user saw a beautiful sunset, but did not take a picture because the user did not have a camera.",
14
- "tokens": 351,
15
- "messages": [{"user": "\"We saw a beautiful sunset.\"", "assistant": "`[S [NP He] [VP [V saw] [NP [det a] [N' [Adj beautiful] [N sunset] ] ] ] ]`\n\n###\n\n"},{"user": "\"We didn't take a picture.\"", "assistant": "`[S [NP We] [IP [I didn't] [VP [V take] [NP [Det a] [N picture] ] ] ] ] ]`\n\n###\n\n"},{"user": "\"We didn't have a camera.\"", "assistant": "`[S [NP We] [IP [I didn't] [VP [V have] [NP [Det a] [N camera] ] ] ] ] ]`\n\n###\n\n"}]
16
- }
17
- ```
18
-
19
- Make sure the following content requirements are all fulfilled:
20
-
21
- - keep the value of the "mode" property at "linguistic"
22
- - set the new prompt to the "prompt" property
23
- - create your response to the new prompt in accordance with the "messages" and set it to "response"
24
- - insert both the new prompt and the response after all the existing items in the "messages"
25
- - analyze the new prompt's sentence type and set a sentence type value such as "interrogative", "imperative", "exclamatory", or "declarative" to the "sentence_type" property
26
- - analyze the new prompt's sentiment and set one or more sentiment types such as "happy", "excited", "troubled", "upset", or "sad" to the "sentiment" property
27
- - summarize the user's messages so far and update the "summary" property with a text of fewer than 100 words using as many discourse markers such as "because", "therefore", "but", "so" to show the logical connection between the events.
28
- - update the value of "tokens" with the number of tokens of the resulting JSON object"
29
-
30
- Make sure the following formal requirements are all fulfilled:
31
-
32
- - do not use invalid characters in the JSON object
33
- - escape double quotes and other special characters in the text values in the resulting JSON object
34
- - increment the value of "turns" by 1 and update the property so that the value of "turns" equals the number of the items in the "messages" of the resulting JSON object
35
- - check the validity of the generated JSON object and correct any possible parsing problems before returning it
36
-
37
- Add "\n\n###\n\n" at the end of the "response" value.
38
-
39
- Wrap the JSON object with "<JSON>\n" and "\n</JSON>".