Class: Inquirex::LLM::Schema
- Inherits:
-
Object
- Object
- Inquirex::LLM::Schema
- Defined in:
- lib/inquirex/llm/schema.rb
Overview
Immutable definition of expected LLM output structure. Each field maps a name to a spec: an Inquirex data type, plus — for :enum / :multi_enum fields — the exhaustive list of allowed values. Together they form the contract between the LLM prompt and the structured data it must return.
A field spec is given either as a bare type symbol or as a Hash with :type and optional :values:
Defined Under Namespace
Classes: Field
Constant Summary collapse
- VALID_TYPES =
%i[ string text integer decimal currency boolean enum multi_enum date email phone array hash ].freeze
Instance Attribute Summary collapse
-
#field_specs ⇒ Hash{Symbol => Field}
readonly
field_name => spec mapping.
-
#fields ⇒ Hash{Symbol => Symbol}
readonly
Field_name => type mapping.
Class Method Summary collapse
-
.from_h(hash) ⇒ Schema
Accepts both wire shapes: plain type strings and rich { "type" => ..., "values" => [...] } specs.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#field_names ⇒ Array<Symbol>
Ordered list of field names.
-
#initialize(**field_map) ⇒ Schema
constructor
A new instance of Schema.
- #inspect ⇒ Object
-
#missing_fields(output) ⇒ Array<Symbol>
Returns the list of fields missing from the given output.
-
#size ⇒ Integer
Number of fields.
-
#to_h ⇒ Hash
Wire format.
-
#to_json ⇒ String
JSON representation.
-
#valid_output?(output) ⇒ Boolean
Checks whether a Hash output conforms to the schema (all declared fields present).
-
#values_for(name) ⇒ Array<String>?
Allowed values for an enum/multi_enum field, or nil when unconstrained.
Constructor Details
#initialize(**field_map) ⇒ Schema
Returns a new instance of Schema.
41 42 43 44 45 46 47 |
# File 'lib/inquirex/llm/schema.rb', line 41 def initialize(**field_map) raise Errors::DefinitionError, "Schema must have at least one field" if field_map.empty? @field_specs = field_map.to_h { |name, spec| [name.to_sym, build_field(name, spec)] }.freeze @fields = @field_specs.transform_values(&:type).freeze freeze end |
Instance Attribute Details
#field_specs ⇒ Hash{Symbol => Field} (readonly)
field_name => spec mapping
25 26 27 |
# File 'lib/inquirex/llm/schema.rb', line 25 def field_specs @field_specs end |
#fields ⇒ Hash{Symbol => Symbol} (readonly)
Returns field_name => type mapping.
50 51 52 |
# File 'lib/inquirex/llm/schema.rb', line 50 def fields @fields end |
Class Method Details
.from_h(hash) ⇒ Schema
Accepts both wire shapes: plain type strings and rich { "type" => ..., "values" => [...] } specs.
114 115 116 117 118 119 |
# File 'lib/inquirex/llm/schema.rb', line 114 def self.from_h(hash) field_map = hash.each_with_object({}) do |(k, v), acc| acc[k.to_sym] = v end new(**field_map) end |
Instance Method Details
#==(other) ⇒ Object
121 122 123 |
# File 'lib/inquirex/llm/schema.rb', line 121 def ==(other) other.is_a?(Schema) && @field_specs == other.field_specs end |
#field_names ⇒ Array<Symbol>
Returns ordered list of field names.
53 |
# File 'lib/inquirex/llm/schema.rb', line 53 def field_names = @field_specs.keys |
#inspect ⇒ Object
125 126 127 128 129 130 |
# File 'lib/inquirex/llm/schema.rb', line 125 def inspect parts = @field_specs.map do |name, field| field.values ? "#{name}:#{field.type}(#{field.values.join("|")})" : "#{name}:#{field.type}" end "#<Inquirex::LLM::Schema #{parts.join(", ")}>" end |
#missing_fields(output) ⇒ Array<Symbol>
Returns the list of fields missing from the given output.
81 82 83 84 85 86 |
# File 'lib/inquirex/llm/schema.rb', line 81 def missing_fields(output) return field_names unless output.is_a?(Hash) symbolized = output.transform_keys(&:to_sym) @field_specs.keys.reject { |key| symbolized.key?(key) } end |
#size ⇒ Integer
Returns number of fields.
56 |
# File 'lib/inquirex/llm/schema.rb', line 56 def size = @field_specs.size |
#to_h ⇒ Hash
Wire format. Fields without value constraints serialize as a plain type string (the pre-0.6 shape); constrained fields serialize as { "type" => ..., "values" => [...] }.
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/inquirex/llm/schema.rb', line 93 def to_h @field_specs.each_with_object({}) do |(name, field), acc| acc[name.to_s] = if field.values { "type" => field.type.to_s, "values" => field.values } else field.type.to_s end end end |
#to_json ⇒ String
Returns JSON representation.
105 106 107 |
# File 'lib/inquirex/llm/schema.rb', line 105 def to_json(*) JSON.generate(to_h) end |
#valid_output?(output) ⇒ Boolean
Checks whether a Hash output conforms to the schema (all declared fields present).
70 71 72 73 74 75 |
# File 'lib/inquirex/llm/schema.rb', line 70 def valid_output?(output) return false unless output.is_a?(Hash) symbolized = output.transform_keys(&:to_sym) @field_specs.keys.all? { |key| symbolized.key?(key) } end |
#values_for(name) ⇒ Array<String>?
Allowed values for an enum/multi_enum field, or nil when unconstrained.
62 63 64 |
# File 'lib/inquirex/llm/schema.rb', line 62 def values_for(name) @field_specs[name.to_sym]&.values end |