geekdict 0.1.1 → 0.2.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: f9a7876ba4eddfb0497523ab7f318588fc1ef1abf754b5f75771b0f2bbc29092
4
- data.tar.gz: 460d3c363a9622fec12bb463854239355293827327d7d7639338c306a36f99a3
3
+ metadata.gz: 8c60ec472c37345eac7c1b4be1f60c56ea5edca02c3c5af8eb19be3cd1173470
4
+ data.tar.gz: ada5e008be1245e52e1b70827b7ef517f067ce187a3a7c755d97e45c189cb14d
5
5
  SHA512:
6
- metadata.gz: a66b0934455eebc3bc5c511510abc261d7c8ddb59cc91f4ea66b4b30ee6b8d709f39451e62d4674731db803ec88f105c064c8722b56b9e073abd0c38597b8c1a
7
- data.tar.gz: 64d730010c52a0e5c7a98b169ff7fef55ed34eab4863b32781aefd18889ffa946cab96dbc5d33516668488d87ddb3be830a111a7b75092e552c3fc29f2d106f2
6
+ metadata.gz: 06ae16f269a32062b8d825debf6e4f76df6cf9e65394365c8275dd0846d163bcaa70203d39561695c6744ae9e137364d6cd2b2ce4d2ee9bb59df492bed357022
7
+ data.tar.gz: e29388ec6089b5172b6898f805942150c8862e0b909ba0dbc37ee4e2d3835b89d190128e6824b19bef7905174dcd8b1c7654f6b3debc176d9e72536fc1be100f
data/README.md CHANGED
@@ -12,38 +12,130 @@ You can install via rubygems:
12
12
 
13
13
  Configure
14
14
  --------
15
- This translate uses OpenAI's GPT-3.5. Ensure you have `OPENAI_API_KEY` configured as environment variable.
15
+ GeekDict requires API keys for certain providers, set as environment variables:
16
+
17
+ * **OpenRouter**: Set `OPENROUTER_API_KEY`.
18
+ * **OpenAI**: Set `OPENAI_API_KEY`.
19
+ * **Youdao**: Configuration for Youdao keys is typically handled within its specific module or a separate config file if needed (refer to Youdao provider specifics if used).
20
+
21
+ ### Configuration File (Optional)
22
+
23
+ You can customize the default provider and model by creating a configuration file at `~/.geekdict.config`. The file should be in YAML format.
24
+
25
+ **Example `~/.geekdict.config`:**
26
+
27
+ ```yaml
28
+ provider: openrouter # 'openai', 'openrouter', or 'youdao'
29
+ model: google/gemini-2.5-flash-preview # Specific model for the chosen provider
30
+ ```
31
+
32
+ **Defaults:**
33
+
34
+ * If the config file is not present or a setting is missing, the tool defaults to:
35
+ * `provider: openrouter`
36
+ * `model: google/gemini-2.5-flash-preview`
37
+
38
+ **Prioritization:**
39
+
40
+ Settings are applied in the following order (highest priority first):
41
+
42
+ 1. Command-line options (`--provider`, `--model`)
43
+ 2. Values in `~/.geekdict.config`
44
+ 3. Hardcoded defaults
16
45
 
17
46
 
18
47
  Commands
19
48
  --------
20
- ### Translate a word
49
+ ### Translate a word (`t`)
50
+
51
+ Translates a given word between English and Chinese.
52
+
53
+ **Usage:**
54
+
55
+ ```bash
56
+ geekdict t [options] <word>
57
+ ```
58
+
59
+ **Options:**
60
+
61
+ * `-p, --provider PROVIDER`: Specify the translation provider (`openai`, `openrouter`, `youdao`). Overrides config file setting.
62
+ * `-m, --model MODEL`: Specify the LLM model to use (e.g., `gpt-4`, `google/gemini-pro`). Overrides config file setting.
63
+ * `-d, --debug`: Enable debug output.
64
+ * `-o, --open`: (Functionality might vary - check specific provider usage)
65
+
66
+ **Examples:**
21
67
 
22
- $geekdict t test
23
- n. 试验;检验
24
- vt. 试验;测试
25
- vi. 试验;测试
26
- n. (Test)人名;(英)特斯特
68
+ ```bash
69
+ # Use defaults (provider/model from CLI -> config -> hardcoded defaults)
70
+ $ geekdict t hello
71
+
72
+ # Specify provider (uses default/config model for that provider)
73
+ $ geekdict t hello -p openai
74
+
75
+ # Specify model (uses default/config provider)
76
+ $ geekdict t hello -m gpt-4
77
+
78
+ # Specify both provider and model
79
+ $ geekdict t hello --provider openrouter --model anthropic/claude-3-haiku
80
+
81
+ # Use Youdao provider (model option typically ignored)
82
+ $ geekdict t hello -p youdao
83
+ ```
84
+
85
+ **Example Output (using an LLM provider):**
86
+
87
+ ```
88
+ Translation: 你好 (nǐ hǎo)
89
+
90
+ Explanation:
91
+ "你好" (nǐ hǎo) is the standard Mandarin Chinese greeting equivalent to "hello" in English. It's a polite and common way to greet someone.
92
+
93
+ Examples:
94
+ 1. 你好,请问有什么可以帮您的吗?
95
+ Hello, may I help you with anything?
96
+ 2. 他笑着对我说你好。
97
+ He smiled and said hello to me.
98
+ ```
27
99
 
28
100
  Command Help
29
101
  ------------
30
- Use *help* command to get detail information.
102
+ Use the `help` command to get detailed information about commands and options.
31
103
 
32
- $geekdict
33
- Commands:
34
- geekdict help [COMMAND] # Describe available commands or one specific command
35
- geekdict t # Translate a word
104
+ ```bash
105
+ $ geekdict help
106
+ Commands:
107
+ geekdict help [COMMAND] # Describe available commands or one specific command
108
+ geekdict t <word> # Translate a word
109
+ geekdict v # Show version
36
110
 
37
- $geekdict help t
38
- Usage:
39
- geekdict t
111
+ $ geekdict help t
112
+ Usage:
113
+ geekdict t [options] <word>
40
114
 
41
- Options:
115
+ Options:
42
116
  -d, [--debug], [--no-debug]
43
117
  -o, [--open], [--no-open]
118
+ -p, [--provider=PROVIDER] # Provider (overrides config: openai/openrouter/youdao)
119
+ -m, [--model=MODEL] # LLM model (overrides config)
120
+ # Default: false
121
+
122
+ Translate a word
123
+ ```
124
+
125
+ ### Shell Alias (Optional)
44
126
 
45
- Translate a word
127
+ For faster access, you can create a shell alias. Add the following line to your shell configuration file (e.g., `~/.bashrc`, `~/.zshrc`):
46
128
 
129
+ ```bash
130
+ alias t='geekdict t'
131
+ ```
132
+
133
+ After adding the alias and restarting your shell or sourcing the configuration file (e.g., `source ~/.zshrc`), you can simply use `t` instead of `geekdict t`:
134
+
135
+ ```bash
136
+ # Instead of: geekdict t hello
137
+ t hello
138
+ ```
47
139
 
48
140
  Development
49
141
  ----------
data/lib/geekdict/cli.rb CHANGED
@@ -1,21 +1,69 @@
1
1
  require "thor"
2
+ # Remove YAML require, handled in config.rb
2
3
  require_relative 'local_history'
3
4
  require_relative 'version'
5
+ require_relative 'config' # Add require for the new config module
4
6
  require_relative 'openai/gpt.rb'
7
+ require_relative 'openrouter/api.rb'
8
+ # Assuming youdao might be added later or is handled elsewhere
9
+ # require_relative 'youdao/api.rb'
10
+ require_relative 'youdao/api.rb' # Keep youdao require
5
11
 
6
12
  module GeekDict
13
+ class CLI < Thor
14
+ # Constants and load_config are now in GeekDict::Config
7
15
 
8
- class CLI < Thor
16
+ desc "t", "Translate a word"
17
+ option :debug, :aliases => '-d', :type => :boolean, :default => false
18
+ option :open, :aliases => '-o', :type => :boolean, :default => false
19
+ # Update enum and desc to use Config constants
20
+ option :provider, :aliases => '-p', :type => :string, :enum => GeekDict::Config::ALLOWED_PROVIDERS, :desc => "Provider (overrides config: #{GeekDict::Config::ALLOWED_PROVIDERS.join('/')})"
21
+ # Add model option
22
+ option :model, :aliases => '-m', :type => :string, :desc => "LLM model (overrides config)"
23
+ def t(word)
24
+ GeekDict.debugger options[:debug]
25
+ LocalHistory.save word
9
26
 
10
- desc "t", "Translate a word"
11
- option :debug, :aliases=>'-d', :type=>:boolean,:default=>false
12
- option :open, :aliases => '-o', :type => :boolean, :default=> false
13
- def t(word)
14
- GeekDict.debugger options[:debug]
15
- LocalHistory.save word
16
- result = GeekDict::OpenAI.translate word
17
- puts result
18
- end
27
+ # 1. Load config file using the Config module
28
+ config = GeekDict::Config.load_config
29
+
30
+ # 2. Determine provider: CLI option > Config file > Default (use Config constants)
31
+ provider = options[:provider]&.downcase || config[:provider] || GeekDict::Config::DEFAULT_PROVIDER
32
+
33
+ # 3. Determine model: CLI option > Config file > Default (use Config constants)
34
+ model = options[:model] || config[:model] || GeekDict::Config::DEFAULT_MODEL
35
+
36
+ # 4. Validate provider (use Config constants)
37
+ unless GeekDict::Config::ALLOWED_PROVIDERS.include?(provider)
38
+ warn "Warning: Invalid provider '#{provider}' specified. Using default '#{GeekDict::Config::DEFAULT_PROVIDER}'."
39
+ provider = GeekDict::Config::DEFAULT_PROVIDER
40
+ # Reset model if provider changed to default, unless model was explicitly set via CLI
41
+ model = options[:model] || GeekDict::Config::DEFAULT_MODEL # Use default model for the default provider
42
+ end
43
+
44
+ # Optional: Output effective settings for debugging/clarity
45
+ puts "Using provider: #{provider}, model: #{model}" if options[:debug]
46
+
47
+ # 5. Call the appropriate provider with the word and model
48
+ result = case provider
49
+ when 'openai'
50
+ # TODO: Update OpenAI class to accept model
51
+ GeekDict::OpenAI.translate(word, model: model)
52
+ when 'openrouter'
53
+ # TODO: Update OpenRouter class to accept model
54
+ GeekDict::OpenRouter.translate(word, model: model)
55
+ when 'youdao'
56
+ # Youdao might not use a 'model' in the same way.
57
+ # If it needs config, adjust here. For now, pass nothing extra.
58
+ GeekDict::Youdao.translate(word)
59
+ else
60
+ # This case should technically not be reached due to validation
61
+ warn "Internal Error: Unknown provider '#{provider}'. Aborting."
62
+ exit 1
63
+ end
64
+
65
+ puts result
66
+ end
19
67
 
20
68
  desc "v", "version"
21
69
  def v()
@@ -0,0 +1,33 @@
1
+ require "yaml"
2
+
3
+ module GeekDict
4
+ module Config
5
+ CONFIG_PATH = File.expand_path("~/.geekdict.config")
6
+ DEFAULT_PROVIDER = "openrouter"
7
+ DEFAULT_MODEL = "google/gemini-2.5-flash-preview"
8
+ ALLOWED_PROVIDERS = ['openai', 'openrouter', 'youdao'].freeze
9
+
10
+ module_function
11
+
12
+ # Method to load configuration from ~/.geekdict.config
13
+ def load_config
14
+ config = {}
15
+ if File.exist?(CONFIG_PATH)
16
+ begin
17
+ loaded_config = YAML.load_file(CONFIG_PATH)
18
+ config = loaded_config if loaded_config.is_a?(Hash)
19
+ rescue Psych::SyntaxError => e
20
+ warn "Warning: Error parsing config file #{CONFIG_PATH}: #{e.message}. Using defaults."
21
+ rescue => e
22
+ warn "Warning: Could not load config file #{CONFIG_PATH}: #{e.message}. Using defaults."
23
+ end
24
+ end
25
+ # Ensure keys are symbols for easier access, handle potential nil values
26
+ config = config.transform_keys { |k| k.to_s.downcase.to_sym rescue k } # Make keys symbols & lowercase
27
+ {
28
+ provider: config[:provider],
29
+ model: config[:model]
30
+ }
31
+ end
32
+ end
33
+ end
@@ -8,12 +8,16 @@ module GeekDict
8
8
 
9
9
  module_function
10
10
 
11
- def translate(word)
11
+ # Update translate method to accept model
12
+ def translate(word, model: nil) # Add model keyword argument
12
13
  @debugger = GeekDict.debugger
14
+ # Use the provided model, or fallback to a default if nil
15
+ effective_model = model || "gpt-3.5-turbo" # Fallback model for OpenAI
16
+
13
17
  client = ::OpenAI::Client.new(access_token: ENV.fetch('OPENAI_API_KEY'))
14
18
  response = client.chat(
15
19
  parameters: {
16
- model: "gpt-3.5-turbo",
20
+ model: effective_model, # Use the determined model
17
21
  messages: [
18
22
  { role: "system", content: system_prompt(word)},
19
23
  { role: "user", content: word}
@@ -25,7 +29,24 @@ module GeekDict
25
29
 
26
30
  def system_prompt(word)
27
31
  <<-EOS
28
- You are helpful and enthusiastic language translator. If the word or sentense is Chinese, translate it into English. If it is English, translate into Chinese. If the word is incorrectly spelled or it's not a correct word in English or Chinese, try your best to find the closest word. In addition to the translation, offer a comprehensive explanation of the word along with one or two examples to illustrate its usage. Do NOT add Pinyin in the example sentences for Chinese.
32
+ You are a precise language translator specializing in English-Chinese translation. Follow these guidelines:
33
+
34
+ 1. If the input is Chinese, translate to English. If English, translate to Chinese.
35
+ 2. For words with multiple meanings, prioritize the most common usage first.
36
+ 3. For misspelled or incorrect words, suggest the closest correct word.
37
+ 4. For idiomatic expressions, provide both literal and figurative translations.
38
+ 5. For technical terms, include the field/domain where appropriate.
39
+
40
+ Format your response as follows:
41
+ - Translation: [primary translation]
42
+ - Explanation: [concise explanation of meaning and usage]
43
+ - Examples:
44
+ 1. [example sentence in target language]
45
+ [translation in source language]
46
+ 2. [second example if helpful]
47
+ [translation in source language]
48
+
49
+ Keep explanations clear and concise. Do NOT include pinyin in Chinese text.
29
50
  EOS
30
51
  end
31
52
  end
@@ -0,0 +1,67 @@
1
+ require 'json'
2
+ require 'httpclient'
3
+
4
+ module GeekDict
5
+ module OpenRouter
6
+ module_function
7
+
8
+ # Update translate method to accept model
9
+ def translate(word, model: nil) # Add model keyword argument
10
+ @debugger = GeekDict.debugger
11
+
12
+ # Use the provided model, or fallback to a default if nil (though CLI should provide one)
13
+ effective_model = model || 'google/gemini-2.5-flash-preview' # Fallback, though CLI provides default
14
+
15
+ client = HTTPClient.new
16
+ headers = {
17
+ 'Content-Type' => 'application/json',
18
+ 'Authorization' => "Bearer #{ENV.fetch('OPENROUTER_API_KEY')}"
19
+ }
20
+
21
+ body = {
22
+ model: effective_model, # Use the determined model
23
+ messages: [
24
+ { role: "system", content: system_prompt(word) },
25
+ { role: "user", content: word }
26
+ ],
27
+ temperature: 0.2
28
+ }
29
+
30
+ response = client.post(
31
+ 'https://openrouter.ai/api/v1/chat/completions',
32
+ body.to_json,
33
+ headers
34
+ )
35
+
36
+ if response.status == 200
37
+ result = JSON.parse(response.body)
38
+ result.dig("choices", 0, "message", "content")
39
+ else
40
+ "Error: Failed to get translation (#{response.status})"
41
+ end
42
+ end
43
+
44
+ def system_prompt(word)
45
+ <<-EOS
46
+ You are a precise language translator specializing in English-Chinese translation. Follow these guidelines:
47
+
48
+ 1. If the input is Chinese, translate to English. If English, translate to Chinese.
49
+ 2. For words with multiple meanings, prioritize the most common usage first.
50
+ 3. For misspelled or incorrect words, suggest the closest correct word.
51
+ 4. For idiomatic expressions, provide both literal and figurative translations.
52
+ 5. For technical terms, include the field/domain where appropriate.
53
+
54
+ Format your response as follows:
55
+ - Translation: [primary translation]
56
+ - Explanation: [concise explanation of meaning and usage]
57
+ - Examples:
58
+ 1. [example sentence in target language]
59
+ [translation in source language]
60
+ 2. [second example if helpful]
61
+ [translation in source language]
62
+
63
+ Keep explanations clear and concise. Do NOT include pinyin in Chinese text.
64
+ EOS
65
+ end
66
+ end
67
+ end
@@ -1,3 +1,3 @@
1
1
  module GeekDict
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/geekdict.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'geekdict/cli'
2
2
  require 'geekdict/debugger'
3
3
  require 'geekdict/youdao/api'
4
+ require 'geekdict/openai/gpt'
5
+ require 'geekdict/openrouter/api'
4
6
 
5
7
  module GeekDict
6
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geekdict
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wenbing Li
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-01 00:00:00.000000000 Z
11
+ date: 2025-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -110,9 +110,11 @@ files:
110
110
  - geekdict.gemspec
111
111
  - lib/geekdict.rb
112
112
  - lib/geekdict/cli.rb
113
+ - lib/geekdict/config.rb
113
114
  - lib/geekdict/debugger.rb
114
115
  - lib/geekdict/local_history.rb
115
116
  - lib/geekdict/openai/gpt.rb
117
+ - lib/geekdict/openrouter/api.rb
116
118
  - lib/geekdict/version.rb
117
119
  - lib/geekdict/youdao/api.rb
118
120
  - lib/geekdict/youdao/config.rb
@@ -123,7 +125,7 @@ homepage: https://github.com/wbinglee/geekdict
123
125
  licenses:
124
126
  - MIT
125
127
  metadata: {}
126
- post_install_message:
128
+ post_install_message:
127
129
  rdoc_options: []
128
130
  require_paths:
129
131
  - lib
@@ -138,8 +140,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
140
  - !ruby/object:Gem::Version
139
141
  version: '0'
140
142
  requirements: []
141
- rubygems_version: 3.3.26
142
- signing_key:
143
+ rubygems_version: 3.5.22
144
+ signing_key:
143
145
  specification_version: 4
144
146
  summary: A command line tool for translation.
145
147
  test_files: