Module: Llm::ResponseParser
- Defined in:
- lib/llm/response_parser.rb
Overview
Extracts JSON from LLM responses, handling markdown wrapping and malformed output. Returns nil on parse failure — callers should fall back to non-AI path.
Class Method Summary collapse
- .extract_elements(response) ⇒ Object
- .extract_json(text) ⇒ Object
- .extract_scenarios(response) ⇒ Object
- .normalize_element(element) ⇒ Object
- .parse_json(response) ⇒ Object
Class Method Details
.extract_elements(response) ⇒ Object
21 22 23 24 25 26 |
# File 'lib/llm/response_parser.rb', line 21 def extract_elements(response) parsed = parse_json(response) return nil unless parsed && parsed[:elements].is_a?(Array) parsed[:elements].map { |el| normalize_element(el) }.compact end |
.extract_json(text) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/llm/response_parser.rb', line 51 def extract_json(text) # Try raw JSON first stripped = text.strip return stripped if stripped.start_with?('{') # Try markdown code block match = text.match(/```(?:json)?\s*\n?(.*?)\n?\s*```/m) return match[1].strip if match # Try finding first { ... } block brace_match = text.match(/(\{.*\})/m) return brace_match[1] if brace_match text end |
.extract_scenarios(response) ⇒ Object
28 29 30 31 32 33 |
# File 'lib/llm/response_parser.rb', line 28 def extract_scenarios(response) parsed = parse_json(response) return nil unless parsed && parsed[:scenarios].is_a?(Array) parsed[:scenarios] end |
.normalize_element(element) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/llm/response_parser.rb', line 35 def normalize_element(element) return nil unless element[:name] && element[:type] && element[:locator] locator = element[:locator] locator = { type: locator[:type]&.to_sym, value: locator[:value] } if locator.is_a?(Hash) { name: element[:name].to_s.gsub(/[^a-z0-9_]/i, '_').downcase, type: element[:type].to_sym, locator:, purpose: element[:purpose], input_type: element[:input_type], text: element[:text] }.compact end |
.parse_json(response) ⇒ Object
11 12 13 14 15 16 17 18 19 |
# File 'lib/llm/response_parser.rb', line 11 def parse_json(response) return nil if response.nil? || response.strip.empty? json_str = extract_json(response) result = JSON.parse(json_str, symbolize_names: true) result.is_a?(Hash) ? result : nil rescue JSON::ParserError nil end |