structify 0.1.0 → 0.3.0
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/CHANGELOG.md +22 -0
- data/CLAUDE.md +27 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +26 -25
- data/README.md +301 -139
- data/lib/structify/model.rb +304 -60
- data/lib/structify/schema_serializer.rb +165 -0
- data/lib/structify/version.rb +1 -1
- data/lib/structify.rb +90 -4
- data/structify.gemspec +2 -2
- metadata +7 -4
data/lib/structify.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "structify/version"
|
4
|
+
require_relative "structify/schema_serializer"
|
4
5
|
require_relative "structify/model"
|
5
6
|
|
6
7
|
# Structify is a DSL for defining extraction schemas for LLM-powered models.
|
7
8
|
# It provides a simple way to integrate with Rails models for LLM extraction,
|
8
|
-
#
|
9
|
+
# allowing for schema versioning and evolution.
|
9
10
|
#
|
10
11
|
# @example
|
11
12
|
# class Article < ApplicationRecord
|
@@ -15,8 +16,6 @@ require_relative "structify/model"
|
|
15
16
|
# title "Article Extraction"
|
16
17
|
# description "Extract article metadata"
|
17
18
|
# version 1
|
18
|
-
# assistant_prompt "Extract the following fields from the article"
|
19
|
-
# llm_model "gpt-4"
|
20
19
|
#
|
21
20
|
# field :title, :string, required: true
|
22
21
|
# field :summary, :text, description: "A brief summary of the article"
|
@@ -24,6 +23,93 @@ require_relative "structify/model"
|
|
24
23
|
# end
|
25
24
|
# end
|
26
25
|
module Structify
|
26
|
+
# Configuration class for Structify
|
27
|
+
class Configuration
|
28
|
+
# @return [Symbol] The default container attribute for JSON fields
|
29
|
+
attr_accessor :default_container_attribute
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@default_container_attribute = :json_attributes
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Structify::Configuration] The current configuration
|
37
|
+
def self.configuration
|
38
|
+
@configuration ||= Configuration.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# Configure Structify
|
42
|
+
# @yield [config] The configuration block
|
43
|
+
# @yieldparam config [Structify::Configuration] The configuration object
|
44
|
+
# @return [Structify::Configuration] The updated configuration
|
45
|
+
def self.configure
|
46
|
+
yield(configuration) if block_given?
|
47
|
+
configuration
|
48
|
+
end
|
49
|
+
# Base error class for Structify
|
27
50
|
class Error < StandardError; end
|
28
|
-
|
51
|
+
|
52
|
+
# Error raised when trying to access a field that doesn't exist in the record's version
|
53
|
+
class MissingFieldError < Error
|
54
|
+
attr_reader :field_name, :record_version, :schema_version
|
55
|
+
|
56
|
+
def initialize(field_name, record_version, schema_version)
|
57
|
+
@field_name = field_name
|
58
|
+
@record_version = record_version
|
59
|
+
@schema_version = schema_version
|
60
|
+
|
61
|
+
message = "Field '#{field_name}' does not exist in version #{record_version}. " \
|
62
|
+
"It was introduced in version #{schema_version}. " \
|
63
|
+
"To access this field, upgrade the record by setting new field values and saving."
|
64
|
+
|
65
|
+
super(message)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Error raised when trying to access a field that has been removed in the current schema version
|
70
|
+
class RemovedFieldError < Error
|
71
|
+
attr_reader :field_name, :removed_in_version
|
72
|
+
|
73
|
+
def initialize(field_name, removed_in_version)
|
74
|
+
@field_name = field_name
|
75
|
+
@removed_in_version = removed_in_version
|
76
|
+
|
77
|
+
message = "Field '#{field_name}' has been removed in version #{removed_in_version}. " \
|
78
|
+
"This field is no longer available in the current schema."
|
79
|
+
|
80
|
+
super(message)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Error raised when trying to access a field outside its specified version range
|
85
|
+
class VersionRangeError < Error
|
86
|
+
attr_reader :field_name, :record_version, :valid_versions
|
87
|
+
|
88
|
+
def initialize(field_name, record_version, valid_versions)
|
89
|
+
@field_name = field_name
|
90
|
+
@record_version = record_version
|
91
|
+
@valid_versions = valid_versions
|
92
|
+
|
93
|
+
message = "Field '#{field_name}' is not available in version #{record_version}. " \
|
94
|
+
"This field is only available in versions: #{format_versions(valid_versions)}."
|
95
|
+
|
96
|
+
super(message)
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def format_versions(versions)
|
102
|
+
if versions.is_a?(Range)
|
103
|
+
if versions.end.nil?
|
104
|
+
"#{versions.begin} and above"
|
105
|
+
else
|
106
|
+
"#{versions.begin} to #{versions.end}#{versions.exclude_end? ? ' (exclusive)' : ''}"
|
107
|
+
end
|
108
|
+
elsif versions.is_a?(Array)
|
109
|
+
versions.join(", ")
|
110
|
+
else
|
111
|
+
"#{versions} and above" # Single integer means this version and onwards
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
29
115
|
end
|
data/structify.gemspec
CHANGED
@@ -19,13 +19,13 @@ Gem::Specification.new do |spec|
|
|
19
19
|
# Specify which files should be added to the gem when it is released.
|
20
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
21
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
22
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) || f.end_with?('.gem') }
|
23
23
|
end
|
24
24
|
spec.bindir = "exe"
|
25
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
28
|
# Runtime dependencies
|
29
|
-
spec.add_dependency "activesupport", "~>
|
29
|
+
spec.add_dependency "activesupport", "~> 8"
|
30
30
|
spec.add_dependency "attr_json", "~> 2.1"
|
31
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: structify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kieran Klaassen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '8'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: attr_json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -49,6 +49,8 @@ files:
|
|
49
49
|
- ".gitignore"
|
50
50
|
- ".rspec"
|
51
51
|
- ".travis.yml"
|
52
|
+
- CHANGELOG.md
|
53
|
+
- CLAUDE.md
|
52
54
|
- CODE_OF_CONDUCT.md
|
53
55
|
- Gemfile
|
54
56
|
- Gemfile.lock
|
@@ -59,6 +61,7 @@ files:
|
|
59
61
|
- bin/setup
|
60
62
|
- lib/structify.rb
|
61
63
|
- lib/structify/model.rb
|
64
|
+
- lib/structify/schema_serializer.rb
|
62
65
|
- lib/structify/version.rb
|
63
66
|
- structify.gemspec
|
64
67
|
homepage: https://github.com/kieranklaassen/structify
|