jekyll-chatgpt-translate 0.0.24 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
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