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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dea0bbaeb26c51558aa530f63a7a57ea1118d5d858c46b284b0aa0eefa43fe1c
4
- data.tar.gz: 63c3ff3581a61bae6f77c9f20a11a56cd7bca662c4722f7284c8ac1523b0b4fb
3
+ metadata.gz: 04c69427e72610fa1be06c75060a255eb0ab45c64b3e1a65a5649aa2420552f7
4
+ data.tar.gz: efc88cd532cd54f28ae0dc4fb2c8cfba8fb0d3e674183494fdc47ef8adcfef15
5
5
  SHA512:
6
- metadata.gz: dc4da5ff3401d84a7c6340da54caa95a334fb548b7d33eb7194487492276c202c61bf17dc9eea471d982ea134076d5f821de7d4d23f248929cdbf67fb7a67369
7
- data.tar.gz: a8a65b0ce61a7317d43261ec44e83a47344524c4226fa8f6d78d69f27544d703b0f8b501fbb6001765ff555aec60b27f1b34d637de1960cdc8fe697ce2902f76
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
@@ -3,7 +3,7 @@ module Mokkku
3
3
  module_function
4
4
 
5
5
  def to_s
6
- '0.0.1'
6
+ '0.0.3'
7
7
  end
8
8
  end
9
9
  end
@@ -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
@@ -1,4 +1,5 @@
1
1
  require_relative 'mokkku/utils'
2
+ require_relative 'mokkku/cli/runner'
2
3
 
3
4
  module Mokkku
4
5
  extend Mokkku::Utils
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.1
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: {}