artificial 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 20d89e77f87e37c150c0e2b3ebc0677f0a65e77c6a674aba37a9834d3986ba3b
4
+ data.tar.gz: baf31ac8198a8626ecac93a2719390c89155c49736321614b1375ca2889b46ea
5
+ SHA512:
6
+ metadata.gz: 36291dba209504dbdcca673c6dcc4e6393807fef54e5184b0576b7f5137cb6873d69d23e3cf5926c414c6a9756ed809798dd03b4b70806c320de968f78b0b6b3
7
+ data.tar.gz: 53432117f9d4ba5465bc8b9a35f6c7c0a56e0e050d42a112751fc51dcfc47ddd94e9655998c02b140e4031466a9450a58c46dbd01e686f8e82f801160cc32427
data/README.md ADDED
@@ -0,0 +1,303 @@
1
+ # Artificial
2
+
3
+ A comprehensive Ruby gem for prompt engineering and management. Build, optimize, and maintain AI prompts with advanced features like role-based prompting, data separation, multi-format input support, and structured XML output.
4
+
5
+ ## Features
6
+
7
+ - **Multi-format Input Support**: String, XML, YAML, JSON, and message arrays
8
+ - **Role-based Prompting**: Expert role assignment for optimal AI performance
9
+ - **Data Separation**: Clear separation between instructions and data
10
+ - **XML Structure**: Structured prompts with proper organization
11
+ - **Method Chaining**: Fluent API for building complex prompts
12
+ - **Validation**: Built-in validation for messages and roles
13
+ - **Hallucination Prevention**: Grounding requirements and source attribution
14
+ - **Tool Integration**: Support for function calling and external tools
15
+ - **Long Context Optimization**: Efficient handling of large documents
16
+ - **Example Management**: Structured examples with input/output pairs
17
+
18
+ ## Installation
19
+
20
+ Install the gem and add to the application's Gemfile by executing:
21
+
22
+ $ bundle add artificial
23
+
24
+ If bundler is not being used to manage dependencies, install the gem by executing:
25
+
26
+ $ gem install artificial
27
+
28
+ ## Usage
29
+
30
+ ### Basic Usage
31
+
32
+ ```ruby
33
+ require 'artificial'
34
+
35
+ # Simple prompt creation
36
+ prompt = Artificial::Prompt.new("What is Ruby?")
37
+ puts prompt.to_s
38
+ ```
39
+
40
+ ### Role-based Prompting
41
+
42
+ ```ruby
43
+ # Expert role assignment
44
+ prompt = Artificial::Prompt.new(
45
+ text: "Explain object-oriented programming",
46
+ system: "You are a Ruby programming expert with 10 years of experience"
47
+ )
48
+ puts prompt.to_s
49
+ ```
50
+
51
+ ### Method Chaining
52
+
53
+ ```ruby
54
+ # Fluent API for building complex prompts
55
+ prompt = Artificial::Prompt.new("Analyze this code")
56
+ .with_system("You are a senior Ruby developer")
57
+ .with_context(audience: "junior developers", goal: "code review")
58
+ .with_examples({ input: "class MyClass; end", output: "Simple class definition" })
59
+ .with_thinking(enabled: true)
60
+ .with_grounding(require_quotes: true, require_sources: true)
61
+
62
+ puts prompt.to_s
63
+ ```
64
+
65
+ ### Data Separation
66
+
67
+ ```ruby
68
+ # Clear separation between instructions and data
69
+ prompt = Artificial::Prompt.new(
70
+ instructions: "Analyze the sales data and identify trends",
71
+ data: {
72
+ q1_sales: "100000",
73
+ q2_sales: "120000",
74
+ q3_sales: "110000",
75
+ q4_sales: "130000"
76
+ }
77
+ )
78
+ puts prompt.to_s
79
+ ```
80
+
81
+ ### Tool Integration
82
+
83
+ ```ruby
84
+ # Function calling support
85
+ prompt = Artificial::Prompt.new("Calculate financial metrics")
86
+ .with_tools(
87
+ { name: "calculate_ratios", parameters: { data: "quarterly_reports" } },
88
+ { name: "generate_chart", parameters: { chart_type: "trend" } }
89
+ )
90
+ puts prompt.to_s
91
+ ```
92
+
93
+ ### Message Arrays (Conversation Format)
94
+
95
+ ```ruby
96
+ # Multi-turn conversations
97
+ messages = [
98
+ { role: "system", content: "You are a helpful Ruby programming assistant" },
99
+ { role: "user", content: "How do I create a class in Ruby?" },
100
+ { role: "assistant", content: "You can create a class using the 'class' keyword" },
101
+ { role: "user", content: "Can you show me an example?" }
102
+ ]
103
+
104
+ prompt = Artificial::Prompt.new(messages)
105
+ puts prompt.to_s
106
+ ```
107
+
108
+ ### Multi-format Input Parsing
109
+
110
+ ```ruby
111
+ # YAML format
112
+ yaml_input = <<~YAML
113
+ text: "Explain Ruby blocks"
114
+ system: "You are a Ruby expert"
115
+ context:
116
+ audience: "beginners"
117
+ goal: "education"
118
+ YAML
119
+
120
+ parsed = Artificial.parse(yaml_input)
121
+ puts parsed.to_hash[:text] # "Explain Ruby blocks"
122
+
123
+ # JSON format
124
+ json_input = '{"text": "What are Ruby gems?", "system": "You are a Ruby expert"}'
125
+ parsed = Artificial.parse(json_input)
126
+ puts parsed.to_hash[:text] # "What are Ruby gems?"
127
+
128
+ # Auto-detection
129
+ parsed = Artificial.parse("Simple text prompt")
130
+ puts parsed.to_hash[:format] # "string"
131
+ ```
132
+
133
+ ### Validation
134
+
135
+ ```ruby
136
+ # Message validation
137
+ messages = [
138
+ { role: "system", content: "You are helpful" },
139
+ { role: "user", content: "Hello" }
140
+ ]
141
+
142
+ validator = Artificial.validate_messages(messages)
143
+ puts validator.valid? # true
144
+
145
+ # Role validation with optimization suggestions
146
+ validator = Artificial.validate_role("You are a Ruby programming expert")
147
+ puts validator.valid? # true
148
+ puts validator.effective? # true
149
+ puts validator.optimization_suggestions.join("; ")
150
+ ```
151
+
152
+ ### Long Context Documents
153
+
154
+ ```ruby
155
+ # Efficient handling of large documents
156
+ prompt = Artificial::Prompt.new("Summarize the key findings")
157
+ .with_documents(
158
+ {
159
+ content: "Long research document content...",
160
+ source: "research_report.pdf",
161
+ metadata: { author: "Dr. Smith", date: "2024-01-15" }
162
+ }
163
+ )
164
+ puts prompt.to_s
165
+ ```
166
+
167
+ ### Advanced Features
168
+
169
+ ```ruby
170
+ # Comprehensive prompt with all features
171
+ prompt = Artificial::Prompt.new(
172
+ text: "Analyze this code",
173
+ system: "You are a senior Ruby developer",
174
+ context: {
175
+ audience: "junior developers",
176
+ goal: "identify improvements",
177
+ workflow: "code_review"
178
+ },
179
+ examples: [
180
+ { input: "bad_code.rb", output: "improvement_suggestions" }
181
+ ],
182
+ thinking: { enabled: true, style: "step_by_step" },
183
+ grounding: {
184
+ require_quotes: true,
185
+ require_sources: true,
186
+ allow_uncertainty: true
187
+ },
188
+ constraints: [
189
+ "Quote specific code sections",
190
+ "Provide actionable suggestions",
191
+ "Consider performance implications"
192
+ ]
193
+ )
194
+
195
+ puts prompt.to_s
196
+ ```
197
+
198
+ ## API Reference
199
+
200
+ ### Artificial::Prompt
201
+
202
+ Main class for creating and managing prompts.
203
+
204
+ #### Methods
205
+
206
+ - `new(input = nil, **options)` - Create a new prompt
207
+ - `to_s` - Generate the final prompt string
208
+ - `with_system(system_prompt)` - Set system prompt with role validation
209
+ - `with_context(**context_options)` - Add contextual information
210
+ - `with_examples(*examples)` - Add structured examples
211
+ - `with_thinking(enabled: true, style: 'step_by_step')` - Enable step-by-step reasoning
212
+ - `with_grounding(**options)` - Add hallucination prevention
213
+ - `with_constraints(*constraints)` - Add explicit constraints
214
+ - `with_tools(*tools)` - Add function calling tools
215
+ - `with_documents(*documents)` - Add long context documents
216
+ - `with_data(data_hash)` - Add data separate from instructions
217
+ - `with_prefill(text)` - Set assistant response prefill
218
+
219
+ ### Artificial Module Methods
220
+
221
+ - `Artificial.create_prompt(input, **options)` - Factory method for creating prompts
222
+ - `Artificial.parse(input, format: :auto)` - Parse input in various formats
223
+ - `Artificial.validate_messages(messages)` - Validate message array structure
224
+ - `Artificial.validate_role(system_prompt)` - Validate and optimize role prompts
225
+
226
+ ## Advanced Usage
227
+
228
+ ### Custom Parsers
229
+
230
+ The gem supports multiple input formats with automatic detection:
231
+
232
+ ```ruby
233
+ # Explicit format specification
234
+ xml_parsed = Artificial.parse(xml_string, format: :xml)
235
+ yaml_parsed = Artificial.parse(yaml_string, format: :yaml)
236
+ json_parsed = Artificial.parse(json_string, format: :json)
237
+
238
+ # Auto-detection (recommended)
239
+ auto_parsed = Artificial.parse(input_string) # Automatically detects format
240
+ ```
241
+
242
+ ### Validation and Optimization
243
+
244
+ ```ruby
245
+ # Role optimization suggestions
246
+ validator = Artificial.validate_role("You are helpful")
247
+ puts validator.effective? # false - generic role
248
+ puts validator.optimization_suggestions
249
+ # => ["Generic roles may reduce AI performance. Consider specifying domain expertise"]
250
+
251
+ # Effective role
252
+ validator = Artificial.validate_role("You are a Ruby programming expert with 10 years of experience")
253
+ puts validator.effective? # true
254
+ puts validator.optimization_suggestions
255
+ # => ["Excellent! Domain expert roles typically improve response quality by 20-30%"]
256
+ ```
257
+
258
+ ### Error Handling
259
+
260
+ ```ruby
261
+ begin
262
+ # Invalid message structure
263
+ messages = [{ role: "invalid", content: "test" }]
264
+ Artificial::Prompt.new(messages)
265
+ rescue ArgumentError => e
266
+ puts e.message # "Message at index 0 has invalid role 'invalid'"
267
+ end
268
+ ```
269
+
270
+ ## Examples
271
+
272
+ See the `examples/demo.rb` file for a comprehensive demonstration of all features.
273
+
274
+ ## Development
275
+
276
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
277
+
278
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
279
+
280
+ ## Contributing
281
+
282
+ Bug reports and pull requests are welcome on GitHub at https://github.com/roboruby/artificial.
283
+
284
+ ## License
285
+
286
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
287
+
288
+ ## Performance Benefits
289
+
290
+ Based on industry best practices from Anthropic's research, this gem provides:
291
+
292
+ - **Reduced hallucinations** through grounding requirements and source attribution
293
+ - **Better context handling** for long documents (20K+ tokens)
294
+ - **Structured output** that's easier to parse and validate
295
+ - **Optimized prompts** that follow proven patterns for maximum effectiveness
296
+
297
+ ## Alignment with Industry Standards
298
+
299
+ This gem implements prompt engineering techniques aligned with:
300
+
301
+ - Anthropic's Interactive Prompt Engineering Tutorial
302
+ - OpenAI's best practices for function calling
303
+ - Production-ready hallucination prevention strategies
data/Rakefile ADDED
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ # Default task runs tests
7
+ task default: [:test]
8
+
9
+ # Main test task - runs all tests
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'test'
12
+ t.libs << 'lib'
13
+ t.test_files = FileList['test/**/test_*.rb']
14
+ t.verbose = true
15
+ end
16
+
17
+ # Individual test tasks for specific test files
18
+ namespace :test do
19
+ desc 'Run all tests'
20
+ Rake::TestTask.new(:all) do |t|
21
+ t.libs << 'test'
22
+ t.libs << 'lib'
23
+ t.test_files = FileList['test/**/test_*.rb']
24
+ t.verbose = true
25
+ end
26
+
27
+ desc 'Run core prompt tests'
28
+ Rake::TestTask.new(:prompt) do |t|
29
+ t.libs << 'test'
30
+ t.libs << 'lib'
31
+ t.test_files = FileList['test/test_artificial.rb']
32
+ t.verbose = true
33
+ end
34
+
35
+ desc 'Run parser and validator tests'
36
+ Rake::TestTask.new(:parsers) do |t|
37
+ t.libs << 'test'
38
+ t.libs << 'lib'
39
+ t.test_files = FileList['test/test_parsers.rb']
40
+ t.verbose = true
41
+ end
42
+
43
+ desc 'Run tests with verbose output'
44
+ Rake::TestTask.new(:verbose) do |t|
45
+ t.libs << 'test'
46
+ t.libs << 'lib'
47
+ t.test_files = FileList['test/**/test_*.rb']
48
+ t.verbose = true
49
+ t.options = '--verbose'
50
+ end
51
+ end
52
+
53
+ # Demo task to run the examples
54
+ desc 'Run the demo script'
55
+ task :demo do
56
+ ruby 'examples/demo.rb'
57
+ end
58
+
59
+ # Code quality tasks
60
+ desc 'Run RuboCop'
61
+ task :rubocop do
62
+ sh 'rubocop'
63
+ end
64
+
65
+ desc 'Run all quality checks'
66
+ task quality: %i[test rubocop]
67
+
68
+ # Help task
69
+ desc 'Show available tasks'
70
+ task :help do
71
+ puts <<~HELP
72
+ Available Rake tasks:
73
+
74
+ Main tasks:
75
+ rake # Run all tests (default)
76
+ rake test # Run all tests
77
+ rake demo # Run the demo script
78
+
79
+ Test tasks:
80
+ rake test:all # Run all tests
81
+ rake test:prompt # Run core prompt tests only
82
+ rake test:parsers # Run parser and validator tests only
83
+ rake test:verbose # Run tests with verbose output
84
+
85
+ Quality tasks:
86
+ rake rubocop # Run RuboCop code analysis
87
+ rake quality # Run tests and RuboCop
88
+
89
+ Other tasks:
90
+ rake build # Build gem
91
+ rake install # Install gem locally
92
+ rake release # Release gem (maintainers only)
93
+ rake help # Show this help message
94
+
95
+ Examples:
96
+ rake # Quick test run
97
+ rake test:prompt # Test just the core functionality
98
+ rake demo # See the gem in action
99
+ rake quality # Full quality check before committing
100
+ HELP
101
+ end
data/examples/demo.rb ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Add lib to the load path
5
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
6
+
7
+ require 'artificial'
8
+
9
+ puts '=== Artificial Ruby Gem Demo ==='
10
+ puts "Version: #{Artificial::VERSION}"
11
+ puts
12
+
13
+ # Example 1: Basic prompt creation
14
+ puts '1. Basic Prompt Creation:'
15
+ prompt = Artificial::Prompt.new('What is Ruby?')
16
+ puts prompt
17
+ puts
18
+
19
+ # Example 2: Role-based prompting
20
+ puts '2. Role-Based Prompting:'
21
+ prompt = Artificial::Prompt.new(
22
+ text: 'Explain object-oriented programming',
23
+ system: 'You are a Ruby programming expert with 10 years of experience'
24
+ )
25
+ puts prompt
26
+ puts
27
+
28
+ # Example 3: Method chaining
29
+ puts '3. Method Chaining:'
30
+ prompt = Artificial::Prompt.new('Analyze this code')
31
+ .with_system('You are a senior Ruby developer')
32
+ .with_context(audience: 'junior developers', goal: 'code review')
33
+ .with_examples({ input: 'class MyClass; end', output: 'Simple class definition' })
34
+ .with_thinking(enabled: true)
35
+ .with_grounding(require_quotes: true, require_sources: true)
36
+
37
+ puts prompt
38
+ puts
39
+
40
+ # Example 4: Data separation
41
+ puts '4. Data Separation:'
42
+ prompt = Artificial::Prompt.new(
43
+ instructions: 'Analyze the sales data and identify trends',
44
+ data: {
45
+ q1_sales: '100000',
46
+ q2_sales: '120000',
47
+ q3_sales: '110000',
48
+ q4_sales: '130000'
49
+ }
50
+ )
51
+ puts prompt
52
+ puts
53
+
54
+ # Example 5: Tool integration
55
+ puts '5. Tool Integration:'
56
+ prompt = Artificial::Prompt.new('Calculate financial metrics')
57
+ .with_tools(
58
+ { name: 'calculate_ratios', parameters: { data: 'quarterly_reports' } },
59
+ { name: 'generate_chart', parameters: { chart_type: 'trend' } }
60
+ )
61
+ puts prompt
62
+ puts
63
+
64
+ # Example 6: Long context documents
65
+ puts '6. Long Context Documents:'
66
+ prompt = Artificial::Prompt.new('Summarize the key findings')
67
+ .with_documents(
68
+ {
69
+ content: 'This is a sample research document with important findings...',
70
+ source: 'research_report.pdf',
71
+ metadata: { author: 'Dr. Smith', date: '2024-01-15' }
72
+ }
73
+ )
74
+ puts prompt
75
+ puts
76
+
77
+ # Example 7: Message array (conversation format)
78
+ puts '7. Message Array (Conversation Format):'
79
+ messages = [
80
+ { role: 'system', content: 'You are a helpful Ruby programming assistant' },
81
+ { role: 'user', content: 'How do I create a class in Ruby?' },
82
+ { role: 'assistant', content: "You can create a class using the 'class' keyword" },
83
+ { role: 'user', content: 'Can you show me an example?' }
84
+ ]
85
+ prompt = Artificial::Prompt.new(messages)
86
+ puts prompt
87
+ puts
88
+
89
+ # Example 8: Auto-parsing different formats
90
+ puts '8. Auto-Parsing Different Formats:'
91
+
92
+ # YAML format
93
+ yaml_input = <<~YAML
94
+ text: "Explain Ruby blocks"
95
+ system: "You are a Ruby expert"
96
+ context:
97
+ audience: "beginners"
98
+ goal: "education"
99
+ YAML
100
+
101
+ parsed_yaml = Artificial.parse(yaml_input)
102
+ puts "YAML parsed as: #{parsed_yaml.to_hash[:format]}"
103
+ puts "Text: #{parsed_yaml.to_hash[:text]}"
104
+ puts
105
+
106
+ # JSON format
107
+ json_input = '{"text": "What are Ruby gems?", "system": "You are a Ruby expert"}'
108
+ parsed_json = Artificial.parse(json_input)
109
+ puts "JSON parsed as: #{parsed_json.to_hash[:format]}"
110
+ puts "Text: #{parsed_json.to_hash[:text]}"
111
+ puts
112
+
113
+ # Example 9: Validation
114
+ puts '9. Validation:'
115
+
116
+ # Valid messages
117
+ valid_messages = [
118
+ { role: 'system', content: 'You are helpful' },
119
+ { role: 'user', content: 'Hello' }
120
+ ]
121
+ validator = Artificial.validate_messages(valid_messages)
122
+ puts "Messages valid: #{validator.valid?}"
123
+
124
+ # Role validation
125
+ role_validator = Artificial.validate_role('You are a Ruby programming expert')
126
+ puts "Role valid: #{role_validator.valid?}"
127
+ puts "Role effective: #{role_validator.effective?}"
128
+ puts "Suggestions: #{role_validator.optimization_suggestions.join('; ')}"
129
+ puts
130
+
131
+ # Example 10: Factory method
132
+ puts '10. Factory Method:'
133
+ prompt = Artificial.create_prompt('Hello world', system: 'You are helpful')
134
+ puts prompt
135
+ puts
136
+
137
+ puts '=== Demo Complete ==='
138
+ puts 'For more examples, check the documentation at https://rubydoc.info/gems/artificial'
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Artificial
6
+ module Parsers
7
+ class JSONParser
8
+ attr_reader :input, :parsed_data, :errors
9
+
10
+ def initialize(input)
11
+ @input = input
12
+ @parsed_data = {}
13
+ @errors = []
14
+ end
15
+
16
+ def parse
17
+ return self unless valid?
18
+
19
+ begin
20
+ json_data = JSON.parse(@input)
21
+ @parsed_data = normalize_json_data(json_data)
22
+ @parsed_data[:format] = 'json'
23
+ @parsed_data[:type] = 'structured_json'
24
+ rescue JSON::ParserError => e
25
+ @errors << "JSON parsing error: #{e.message}"
26
+ rescue StandardError => e
27
+ @errors << "JSON processing error: #{e.message}"
28
+ end
29
+
30
+ self
31
+ end
32
+
33
+ def valid?
34
+ return false unless @input.is_a?(String)
35
+ return false if @input.strip.empty?
36
+
37
+ begin
38
+ JSON.parse(@input)
39
+ true
40
+ rescue JSON::ParserError => e
41
+ @errors << "Invalid JSON: #{e.message}"
42
+ false
43
+ rescue StandardError => e
44
+ @errors << "JSON validation error: #{e.message}"
45
+ false
46
+ end
47
+ end
48
+
49
+ def to_hash
50
+ @parsed_data
51
+ end
52
+
53
+ private
54
+
55
+ def normalize_json_data(json_data)
56
+ return {} unless json_data.is_a?(Hash)
57
+
58
+ # Convert string keys to symbols for consistency
59
+ normalized = {}
60
+ json_data.each do |key, value|
61
+ symbol_key = key.to_s.to_sym
62
+ normalized[symbol_key] = normalize_value(value)
63
+ end
64
+
65
+ # Ensure common fields are present
66
+ normalized[:text] ||= normalized[:instructions]
67
+ normalized[:examples] ||= []
68
+ normalized[:context] ||= {}
69
+ normalized[:grounding] ||= {}
70
+ normalized[:tools] ||= []
71
+
72
+ # Handle special JSON structures
73
+ normalized[:messages] = normalize_messages(normalized[:messages]) if normalized[:messages].is_a?(Array)
74
+
75
+ normalized
76
+ end
77
+
78
+ def normalize_value(value)
79
+ case value
80
+ when Hash
81
+ value.transform_keys { |k| k.to_s.to_sym }
82
+ when Array
83
+ value.map { |v| normalize_value(v) }
84
+ else
85
+ value
86
+ end
87
+ end
88
+
89
+ def normalize_messages(messages)
90
+ messages.map do |message|
91
+ if message.is_a?(Hash)
92
+ {
93
+ role: message['role']&.to_s || message[:role]&.to_s,
94
+ content: message['content'] || message[:content]
95
+ }
96
+ else
97
+ message
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Artificial
4
+ module Parsers
5
+ class StringParser
6
+ attr_reader :input, :parsed_data
7
+
8
+ def initialize(input)
9
+ @input = input
10
+ @parsed_data = {}
11
+ end
12
+
13
+ def parse
14
+ @parsed_data = {
15
+ text: @input,
16
+ format: 'string',
17
+ type: 'simple_text'
18
+ }
19
+ self
20
+ end
21
+
22
+ def valid?
23
+ @input.is_a?(String) && !@input.empty?
24
+ end
25
+
26
+ def to_hash
27
+ @parsed_data
28
+ end
29
+ end
30
+ end
31
+ end