jekyll-chatgpt-translate 0.0.24 → 0.0.26

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: 496c59378248bd1973071e0ed6d01d0e55253cf0c47dce9f72b2704ba315e9e3
4
- data.tar.gz: 13905a9d5f52ed1558f1e0679af7ec236936b4d77eb97d0c8e63ce3e0cb72ac7
3
+ metadata.gz: 9f480f74d9f096d1b24d516f05c1c24a27cefe7e87cc9db917d2fffe727646fe
4
+ data.tar.gz: 0dd088c831b8a3d9685bf4363ea7821d83d8602767fb933740b938552475d98e
5
5
  SHA512:
6
- metadata.gz: 63e2c67379437c2f6aa20cff512452fcb2d2237b1e5d8a1d8bb0155c67a4ee044bfb4957765bff3daab4d24fdb875779ec9bffd8419e1331f0efd3667ee19d38
7
- data.tar.gz: 84ab3c8daa5173849cbcaeeb067ddf7470fa04b099c1793582c99f44f4a64e0fbf65b842817e0c489996cd742d8335de3f4fc62576aaede50212aeb4ff7d7c22
6
+ metadata.gz: c286215fa7b40fab206be74d7f03d02963f307009ba6d91c0f1ff7ce06795eb29be1588c022a994696755677e6640fb595aca7246474d8a1bc9072f38f5458a1
7
+ data.tar.gz: af831575ce9749aada2c42ad5c4d8798890490e5e0795cd87f70cce9a2d8b7bbaa3d7dfba9b95e9b5f81eaef2e9f9513ca1542341e1393bc4878c6ee257911af
data/.rubocop.yml CHANGED
@@ -3,7 +3,7 @@ AllCops:
3
3
  - 'bin/**/*'
4
4
  - 'assets/**/*'
5
5
  DisplayCopNames: true
6
- TargetRubyVersion: 2.3
6
+ TargetRubyVersion: 2.7
7
7
  SuggestExtensions: false
8
8
  NewCops: enable
9
9
 
@@ -35,3 +35,5 @@ Layout/EndAlignment:
35
35
  Enabled: false
36
36
  Metrics/ClassLength:
37
37
  Max: 200
38
+ Style/ClassVars:
39
+ Enabled: false
data/README.md CHANGED
@@ -60,9 +60,14 @@ Full list of options available to specify in `_config.yml`:
60
60
  * `api_key_file` (optional) — the file with OpenAI API key. If this option is not specified,
61
61
  it is expected to have the key in the `OPENAI_API_KEY` environment variable.
62
62
 
63
- * `model` (optional) — specifies the model to use by ChatGPT.
63
+ * `api_key` (optional) — the OpenAI API key itself. This is a very bad idea to
64
+ specify it right in the `_config.yml` file, but it's still possible.
64
65
 
65
- * `source` (optional) — is the ISO-839-1 code of the source language.
66
+ * `model` (optional) — specifies the model to use by ChatGPT,
67
+ [examples are here](https://github.com/alexrudall/ruby-openai#models).
68
+
69
+ * `source` (optional) — is the [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
70
+ code of the source language.
66
71
 
67
72
  * `no_download` (optional) — if this attribute is present, the plugin won't try
68
73
  to find HTML versions of translated pages in the Internet and won't try to
@@ -79,7 +84,7 @@ This layout will be specified for the pages generated by this plugin.
79
84
 
80
85
  * `targets` (mandatory) — an array of target languages, each of which has the following attributes
81
86
 
82
- * `language` (mandatory) — ISO-839-1 code of the target language
87
+ * `language` (mandatory) — [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code of the target language
83
88
 
84
89
  * `permalink` (mandatory) — template to use for newly generated pages
85
90
 
@@ -93,7 +98,7 @@ This layout will be specified for the pages generated by this plugin.
93
98
  * `version` (optional) — the version that will be attached to each generated page,
94
99
  in order to avoid repetitive translations on one hand and enable re-translations
95
100
  when the `version` is changed on another hand. By default, the version of
96
- the plugin will be used here, unless you set your own value.
101
+ this plugin will be used, unless you set your own value.
97
102
 
98
103
  ## How to Contribute
99
104
 
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
29
29
  s.required_ruby_version = '>= 2.6'
30
30
  s.name = 'jekyll-chatgpt-translate'
31
- s.version = '0.0.24'
31
+ s.version = '0.0.26'
32
32
  s.license = 'MIT'
33
33
  s.summary = 'Translate Jekyll Pages Through ChatGPT'
34
34
  s.description = [
@@ -35,6 +35,9 @@ module GptTranslate; end
35
35
  # Copyright:: Copyright (c) 2023 Yegor Bugayenko
36
36
  # License:: MIT
37
37
  class GptTranslate::ChatGPT
38
+ # Is TRUE if we already shown to the user the available models.
39
+ @@models_printed = false
40
+
38
41
  # Ctor.
39
42
  # +key+ OpenAI API Key, which can't be nil, but can be empty string, which means dry mode (no calls to OpenAI)
40
43
  # +source+ The language to translate from
@@ -64,6 +67,10 @@ class GptTranslate::ChatGPT
64
67
  par
65
68
  elsif @key.empty?
66
69
  par
70
+ elsif par.start_with?('* ')
71
+ "* #{translate_par(par[2..])}"
72
+ elsif par =~ /^[0-9]+\. /
73
+ "1. #{translate_par(par.split('.', 2)[1])}"
67
74
  else
68
75
  translate_par(par)
69
76
  end
@@ -73,12 +80,17 @@ class GptTranslate::ChatGPT
73
80
  private
74
81
 
75
82
  def translate_par(par)
83
+ client = OpenAI::Client.new(access_token: @key)
84
+ if @@models_printed
85
+ Jekyll.logger.info("Available ChatGPT models: #{client.models.list['data'].map { |m| m['id'] }.join(', ')}")
86
+ @@models_printed = true
87
+ end
88
+ prompt = GptTranslate::Prompt.new(par, @source, @target).to_s
76
89
  start = Time.now
77
90
  answer = nil
78
91
  attempt = 0
79
92
  begin
80
- prompt = GptTranslate::Prompt.new(par, @source, @target).to_s
81
- response = OpenAI::Client.new(access_token: @key).chat(
93
+ response = client.chat(
82
94
  parameters: {
83
95
  model: @model,
84
96
  messages: [{ role: 'user', content: prompt }],
@@ -86,7 +98,10 @@ class GptTranslate::ChatGPT
86
98
  }
87
99
  )
88
100
  answer = response.dig('choices', 0, 'message', 'content')
89
- raise 'No content returned by ChatGPT' if answer.nil?
101
+ if answer.nil?
102
+ Jekyll.logger.error("No content returned by ChatGPT: #{response}")
103
+ raise 'No content returned by ChatGPT'
104
+ end
90
105
  Jekyll.logger.debug("ChatGPT prompt: #{prompt.inspect}, ChatGPT answer: #{answer.inspect}")
91
106
  rescue StandardError => e
92
107
  attempt += 1
@@ -106,8 +106,8 @@ class GptTranslate::Plain
106
106
  content
107
107
  end
108
108
 
109
- def list_item(content, _type)
110
- "#{content.strip}\n\n"
109
+ def list_item(content, type)
110
+ "#{type == :ordered ? '1.' : '*'} #{content.strip}\n\n"
111
111
  end
112
112
 
113
113
  def paragraph(text)
@@ -23,5 +23,5 @@
23
23
  # SOFTWARE.
24
24
 
25
25
  module GptTranslate
26
- VERSION = '0.0.24'
26
+ VERSION = '0.0.26'
27
27
  end
data/test/test_chatgpt.rb CHANGED
@@ -44,6 +44,20 @@ class GptTranslate::ChatGPTTest < Minitest::Test
44
44
  assert_equal('done!', chat.translate('[OpenAI](https://openai.com) is the creator of ChatGPT', min: 10))
45
45
  end
46
46
 
47
+ def test_unordered_list_item
48
+ stub_request(:any, 'https://api.openai.com/v1/chat/completions')
49
+ .to_return(body: '{"choices":[{"message":{"content": "done!"}}]}')
50
+ chat = GptTranslate::ChatGPT.new('fake-key', 'gpt-3.5-turbo', 'en', 'ru')
51
+ assert_equal("* done!\n\n* done!", chat.translate("* First\n\n* Second", min: 1))
52
+ end
53
+
54
+ def test_ordered_list_item
55
+ stub_request(:any, 'https://api.openai.com/v1/chat/completions')
56
+ .to_return(body: '{"choices":[{"message":{"content": "done!"}}]}')
57
+ chat = GptTranslate::ChatGPT.new('fake-key', 'gpt-3.5-turbo', 'en', 'ru')
58
+ assert_equal("1. done!\n\n1. done!", chat.translate("1. First\n\n2. Second", min: 1))
59
+ end
60
+
47
61
  def test_dry_mode
48
62
  chat = GptTranslate::ChatGPT.new('', 'foo', 'xx', 'xx')
49
63
  assert_equal(38, chat.translate('This text should not be sent to OpenAI', min: 100).length)
data/test/test_plain.rb CHANGED
@@ -42,25 +42,25 @@ class GptTranslate::PlainTest < Minitest::Test
42
42
 
43
43
  def test_lists
44
44
  assert_equal(
45
- "first\n\nsecond\n\nthird",
45
+ "* first\n\n* second\n\n* third",
46
46
  GptTranslate::Plain.new("* first\n\n* second\n\n* third").to_s
47
47
  )
48
48
  assert_equal(
49
- 'first',
49
+ '* first',
50
50
  GptTranslate::Plain.new("* first\n\n\n\n").to_s
51
51
  )
52
52
  end
53
53
 
54
54
  def test_ordered_list
55
55
  assert_equal(
56
- "first\n\nsecond\n\nthird",
56
+ "1. first\n\n1. second\n\n1. third",
57
57
  GptTranslate::Plain.new("1. first\n\n2. second\n\n3. third").to_s
58
58
  )
59
59
  end
60
60
 
61
61
  def test_compact_list
62
62
  assert_equal(
63
- "first\n\nsecond\n\nthird",
63
+ "* first\n\n* second\n\n* third",
64
64
  GptTranslate::Plain.new("* first\n* second\n* third").to_s
65
65
  )
66
66
  end
@@ -151,11 +151,11 @@ class GptTranslate::PlainTest < Minitest::Test
151
151
 
152
152
  In this *lovely* letter I will explain how objects work in C++:
153
153
 
154
- Declare a class
154
+ * Declare a class
155
155
 
156
- Make an instance of it
156
+ * Make an instance of it
157
157
 
158
- Delete the instance
158
+ * Delete the instance
159
159
 
160
160
  ## More details
161
161
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-chatgpt-translate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.24
4
+ version: 0.0.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko