mokkku 0.0.1 → 0.0.3
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 +4 -4
- data/bin/mokkku +41 -0
- data/lib/mokkku/cli/prompt.rb +27 -0
- data/lib/mokkku/cli/runner.rb +35 -0
- data/lib/mokkku/cli/validator.rb +15 -0
- data/lib/mokkku/generators/builder.rb +21 -0
- data/lib/mokkku/generators/claude.rb +24 -0
- data/lib/mokkku/generators/gpt.rb +23 -0
- data/lib/mokkku/version.rb +1 -1
- data/lib/mokkku/yaml_sanitizer.rb +13 -0
- data/lib/mokkku.rb +1 -0
- metadata +39 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04c69427e72610fa1be06c75060a255eb0ab45c64b3e1a65a5649aa2420552f7
|
4
|
+
data.tar.gz: efc88cd532cd54f28ae0dc4fb2c8cfba8fb0d3e674183494fdc47ef8adcfef15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afc7eb5280d025becdd44e0bd65412645a15bea68812ccc3c09a9179f79b2327faed3937c326c5da56f484a29cafc65e2d1f7bdf98550fff3d8a40995698f864
|
7
|
+
data.tar.gz: e07d24c250a66e1550da05e37a4961c3d4ad0e389e905aa662ca514ac9b96af48c263d3c24fab1e5281884f267381c5fbe588d8c67cd1540981388e81d707e81
|
data/bin/mokkku
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'mokkku'
|
5
|
+
require 'optionparser'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.banner = 'Usage: mokkku [options]'
|
11
|
+
|
12
|
+
opts.on('-m', '--model Model', 'Provide model name to generate mocks for') do |opt|
|
13
|
+
options[:models] = [opt]
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on('--models Model1,Model2', 'Provide model names to generate mocks for') do |opt|
|
17
|
+
options[:models] = opt.split(',')
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('-a', '--api-key value', 'API key for LLM') do |opt|
|
21
|
+
options[:llm_api_key] = opt
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on('-llm', '--llm-model value', 'Type of LLM: GPT, Gemini, or Claude') do |opt|
|
25
|
+
options[:llm_model] = opt
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on('-p', '--mocks-path value', 'Location where files will be created, default to ./spec/mocks') do |opt|
|
29
|
+
options[:mocks_path] = opt
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on('-c', '--count value', 'Number of entries to generate in mock file, 10 by default') do |opt|
|
33
|
+
options[:mocks_count] = opt
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on('-l', '--language value', 'The language of mocks, english by default') do |opt|
|
37
|
+
options[:language] = opt
|
38
|
+
end
|
39
|
+
end.parse!
|
40
|
+
|
41
|
+
Mokkku::Cli::Runner.start(options)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mokkku
|
2
|
+
module Cli
|
3
|
+
class Prompt
|
4
|
+
IGNORED_COLUMNS = %w[id created_at updated_at].freeze
|
5
|
+
|
6
|
+
def self.generate(model_name, columns, mocks_count, language)
|
7
|
+
columns_for_prompt = columns.reject { |col| IGNORED_COLUMNS.include?(col.name) || col.name.match?(/.*\_id$/) }
|
8
|
+
.inject({}) { |hash, col| hash[col.name] = col.sql_type_metadata.type; hash }
|
9
|
+
|
10
|
+
prompt_start = "Act like a virtual assistant that generates YAML file with the test data for a given Ruby on Rails model. Generate #{mocks_count.to_i} entries for the following model named #{model_name}:"
|
11
|
+
|
12
|
+
yaml_attributes = columns_for_prompt.map do |name, type|
|
13
|
+
" #{name}: #{type}\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
prompt_yaml_part = "- #{yaml_attributes.join}"
|
17
|
+
prompt_summary = 'Reply only with the content of the YAML file.'
|
18
|
+
|
19
|
+
if language != 'english'
|
20
|
+
prompt_summary += " Translate test data to #{language} language."
|
21
|
+
end
|
22
|
+
|
23
|
+
"#{prompt_start}\n\n#{prompt_yaml_part}\n\n#{prompt_summary}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'validator'
|
2
|
+
require_relative 'prompt'
|
3
|
+
require_relative '../generators/builder'
|
4
|
+
require_relative '../yaml_sanitizer'
|
5
|
+
|
6
|
+
module Mokkku
|
7
|
+
module Cli
|
8
|
+
class Runner
|
9
|
+
def self.start(options = {})
|
10
|
+
::Mokkku::Cli::Validator.validate_options!(options)
|
11
|
+
|
12
|
+
options[:models].each do |model_name|
|
13
|
+
columns = Object.const_get(model_name).columns
|
14
|
+
prompt = ::Mokkku::Cli::Prompt.generate(model_name, columns, options.fetch(:mocks_count, 10), options.fetch(:language, 'english'))
|
15
|
+
generator = ::Mokkku::Generators::Builder.call(
|
16
|
+
generator: options[:llm_model],
|
17
|
+
api_key: options[:llm_api_key],
|
18
|
+
prompt: prompt
|
19
|
+
)
|
20
|
+
|
21
|
+
yaml_mock = generator.call(api_key: options[:llm_api_key], prompt: prompt)
|
22
|
+
mock_file_name = model_name.to_s.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
|
23
|
+
|
24
|
+
puts "Write mocks for #{model_name} model in #{mock_file_name}.yml"
|
25
|
+
File.write(
|
26
|
+
File.join(options.fetch(:mocks_path, './spec/mocks'), "#{mock_file_name}.yml"),
|
27
|
+
::Mokkku::YamlSanitizer.sanitize(yaml_mock)
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
puts 'Done!'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Mokkku
|
2
|
+
module Cli
|
3
|
+
module Validator
|
4
|
+
ModelsNotProvided = Class.new(StandardError)
|
5
|
+
InvalidLlmModel = Class.new(StandardError)
|
6
|
+
LlmApiKeyNotProvided = Class.new(StandardError)
|
7
|
+
|
8
|
+
def self.validate_options!(options)
|
9
|
+
raise ModelsNotProvided if options.fetch(:models, []).empty?
|
10
|
+
raise InvalidLlmModel unless %w[gpt gemini claude].include?(options[:llm_model].to_s.downcase)
|
11
|
+
raise LlmApiKeyNotProvided if options[:llm_api_key].to_s == ''
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'gpt'
|
2
|
+
require_relative 'claude'
|
3
|
+
|
4
|
+
module Mokkku
|
5
|
+
module Generators
|
6
|
+
class Builder
|
7
|
+
UnsupportedGenerator = Class.new(StandardError)
|
8
|
+
|
9
|
+
def self.call(generator:, api_key:, prompt:)
|
10
|
+
case generator
|
11
|
+
when 'gpt'
|
12
|
+
Mokkku::Generators::Gpt
|
13
|
+
when 'claude'
|
14
|
+
Mokkku::Generators::Claude
|
15
|
+
else
|
16
|
+
raise UnsupportedGenerator
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'anthropic'
|
2
|
+
|
3
|
+
module Mokkku
|
4
|
+
module Generators
|
5
|
+
class Claude
|
6
|
+
def self.call(api_key:, prompt:)
|
7
|
+
client = Anthropic::Client.new(access_token: api_key)
|
8
|
+
|
9
|
+
response = client.messages(
|
10
|
+
parameters: {
|
11
|
+
model: 'claude-3-5-sonnet-20240620',
|
12
|
+
system: 'Respond only with code.',
|
13
|
+
messages: [
|
14
|
+
{ 'role': 'user', 'content': prompt },
|
15
|
+
],
|
16
|
+
max_tokens: 1_000
|
17
|
+
}
|
18
|
+
)
|
19
|
+
|
20
|
+
response['content'].first['text']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'openai'
|
2
|
+
|
3
|
+
module Mokkku
|
4
|
+
module Generators
|
5
|
+
class Gpt
|
6
|
+
def self.call(api_key:, prompt:)
|
7
|
+
client = OpenAI::Client.new(access_token: api_key)
|
8
|
+
|
9
|
+
response = client.completions(parameters: {
|
10
|
+
prompt: prompt,
|
11
|
+
model: 'gpt-3.5-turbo-instruct',
|
12
|
+
temperature: 0,
|
13
|
+
max_tokens: 1_000,
|
14
|
+
top_p: 1.0,
|
15
|
+
frequency_penalty: 0.0,
|
16
|
+
presence_penalty: 0.0
|
17
|
+
})
|
18
|
+
|
19
|
+
response['choices'].first['text']
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/mokkku/version.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Mokkku
|
2
|
+
class YamlSanitizer
|
3
|
+
def self.sanitize(yaml_content)
|
4
|
+
# Some LLMs ignore the instructions and return YAML with additions
|
5
|
+
yaml_lines = yaml_content.split("\n")
|
6
|
+
yaml_lines.shift if yaml_lines.first.start_with?("`")
|
7
|
+
yaml_lines.pop if yaml_lines.last.start_with?("`")
|
8
|
+
yaml_lines.shift unless yaml_lines.first.strip.start_with?('-')
|
9
|
+
|
10
|
+
yaml_lines.join("\n")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/mokkku.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mokkku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paweł Dąbrowski
|
@@ -44,16 +44,53 @@ dependencies:
|
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: ruby-openai
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 7.1.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 7.1.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: anthropic
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.3.0
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.3.0
|
47
75
|
description: Generate mock data that is unique for your application
|
48
76
|
email: contact@paweldabrowski.com
|
49
|
-
executables:
|
77
|
+
executables:
|
78
|
+
- mokkku
|
50
79
|
extensions: []
|
51
80
|
extra_rdoc_files: []
|
52
81
|
files:
|
82
|
+
- bin/mokkku
|
53
83
|
- lib/mokkku.rb
|
84
|
+
- lib/mokkku/cli/prompt.rb
|
85
|
+
- lib/mokkku/cli/runner.rb
|
86
|
+
- lib/mokkku/cli/validator.rb
|
87
|
+
- lib/mokkku/generators/builder.rb
|
88
|
+
- lib/mokkku/generators/claude.rb
|
89
|
+
- lib/mokkku/generators/gpt.rb
|
54
90
|
- lib/mokkku/mocked_object.rb
|
55
91
|
- lib/mokkku/utils.rb
|
56
92
|
- lib/mokkku/version.rb
|
93
|
+
- lib/mokkku/yaml_sanitizer.rb
|
57
94
|
homepage:
|
58
95
|
licenses: []
|
59
96
|
metadata: {}
|