ai-chat 0.2.3 → 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/README.md +143 -76
- data/ai-chat.gemspec +8 -5
- data/lib/ai/amazing_print.rb +7 -1
- data/lib/ai/chat.rb +452 -81
- data/lib/ai/http.rb +45 -0
- data/lib/prompts/schema_generator.md +123 -0
- metadata +58 -12
data/lib/ai/http.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
module AI
|
|
3
|
+
module Http
|
|
4
|
+
def send_request(uri, content_type: nil, parameters: nil, method:)
|
|
5
|
+
Net::HTTP.start(uri.host, 443, use_ssl: true) do |http|
|
|
6
|
+
headers = {
|
|
7
|
+
"Authorization" => "Bearer #{@api_key}"
|
|
8
|
+
}
|
|
9
|
+
if content_type
|
|
10
|
+
headers.store("Content-Type", "application/json")
|
|
11
|
+
end
|
|
12
|
+
net_http_method = "Net::HTTP::#{method.downcase.capitalize}"
|
|
13
|
+
client = Kernel.const_get(net_http_method)
|
|
14
|
+
request = client.new(uri, headers)
|
|
15
|
+
|
|
16
|
+
if parameters
|
|
17
|
+
request.body = parameters.to_json
|
|
18
|
+
end
|
|
19
|
+
response = http.request(request)
|
|
20
|
+
|
|
21
|
+
# Handle proxy server 503 HTML response
|
|
22
|
+
begin
|
|
23
|
+
if content_type
|
|
24
|
+
return JSON.parse(response.body, symbolize_names: true)
|
|
25
|
+
else
|
|
26
|
+
return response.body
|
|
27
|
+
end
|
|
28
|
+
rescue JSON::ParserError, TypeError => e
|
|
29
|
+
raise JSON::ParserError, "Failed to parse response from proxy: #{e.message}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create_deep_struct(value)
|
|
35
|
+
case value
|
|
36
|
+
when Hash
|
|
37
|
+
OpenStruct.new(value.transform_values { |hash_value| send __method__, hash_value })
|
|
38
|
+
when Array
|
|
39
|
+
value.map { |element| send __method__, element }
|
|
40
|
+
else
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
You are an expert at creating JSON Schemas for OpenAI's Structured Outputs feature.
|
|
2
|
+
|
|
3
|
+
Generate a valid JSON Schema that follows these strict rules:
|
|
4
|
+
|
|
5
|
+
## OUTPUT FORMAT
|
|
6
|
+
Return a JSON object with this root structure:
|
|
7
|
+
- "name": a short snake_case identifier for the schema
|
|
8
|
+
- "strict": must be true
|
|
9
|
+
- "schema": the actual JSON Schema object
|
|
10
|
+
|
|
11
|
+
## SCHEMA REQUIREMENTS
|
|
12
|
+
|
|
13
|
+
### Critical Rules:
|
|
14
|
+
1. Root schema must be "type": "object" (not anyOf)
|
|
15
|
+
2. Set "additionalProperties": false on ALL objects (including nested ones)
|
|
16
|
+
3. ALL properties must be in "required" arrays (no optional fields unless using union types)
|
|
17
|
+
4. Always specify "items" for arrays
|
|
18
|
+
|
|
19
|
+
### Supported Types:
|
|
20
|
+
- string, number, boolean, integer, object, array, enum, anyOf
|
|
21
|
+
|
|
22
|
+
### Optional Fields:
|
|
23
|
+
To make a field optional, use union types:
|
|
24
|
+
- "type": ["string", "null"] for optional string
|
|
25
|
+
- "type": ["number", "null"] for optional number
|
|
26
|
+
- etc.
|
|
27
|
+
|
|
28
|
+
### String Properties (use when appropriate):
|
|
29
|
+
- "pattern": regex pattern (e.g., "^@[a-zA-Z0-9_]+$" for usernames)
|
|
30
|
+
- "format": predefined formats (date-time, time, date, duration, email, hostname, ipv4, ipv6, uuid)
|
|
31
|
+
- Example: {"type": "string", "format": "email", "description": "User's email address"}
|
|
32
|
+
|
|
33
|
+
### Number Properties (use when appropriate):
|
|
34
|
+
- "minimum": minimum value (inclusive)
|
|
35
|
+
- "maximum": maximum value (inclusive)
|
|
36
|
+
- "exclusiveMinimum": minimum value (exclusive)
|
|
37
|
+
- "exclusiveMaximum": maximum value (exclusive)
|
|
38
|
+
- "multipleOf": must be multiple of this value
|
|
39
|
+
- Example: {"type": "number", "minimum": -130, "maximum": 130, "description": "Temperature in degrees"}
|
|
40
|
+
|
|
41
|
+
### Array Properties (use when appropriate):
|
|
42
|
+
- "minItems": minimum number of items
|
|
43
|
+
- "maxItems": maximum number of items
|
|
44
|
+
- Example: {"type": "array", "items": {...}, "minItems": 1, "maxItems": 10}
|
|
45
|
+
|
|
46
|
+
### Enum Values:
|
|
47
|
+
Use enums for fixed sets of values:
|
|
48
|
+
- Example: {"type": "string", "enum": ["draft", "published", "archived"]}
|
|
49
|
+
|
|
50
|
+
### Nested Objects:
|
|
51
|
+
All nested objects MUST have:
|
|
52
|
+
- "additionalProperties": false
|
|
53
|
+
- Complete "required" arrays
|
|
54
|
+
- Clear "description" fields
|
|
55
|
+
|
|
56
|
+
### Recursive Schemas:
|
|
57
|
+
Support recursion using "$ref":
|
|
58
|
+
- Root recursion: {"$ref": "#"}
|
|
59
|
+
- Definition reference: {"$ref": "#/$defs/node_name"}
|
|
60
|
+
|
|
61
|
+
### Descriptions:
|
|
62
|
+
Add clear, helpful "description" fields for all properties to guide the model.
|
|
63
|
+
|
|
64
|
+
## CONSTRAINTS
|
|
65
|
+
- Max 5000 properties total, 10 levels of nesting
|
|
66
|
+
- Max 1000 enum values across all enums
|
|
67
|
+
- Total string length of all names/values cannot exceed 120,000 chars
|
|
68
|
+
|
|
69
|
+
## EXAMPLE OUTPUTS
|
|
70
|
+
|
|
71
|
+
Simple example:
|
|
72
|
+
{
|
|
73
|
+
"name": "user_profile",
|
|
74
|
+
"strict": true,
|
|
75
|
+
"schema": {
|
|
76
|
+
"type": "object",
|
|
77
|
+
"properties": {
|
|
78
|
+
"name": {"type": "string", "description": "User's full name"},
|
|
79
|
+
"age": {"type": "integer", "minimum": 0, "maximum": 150, "description": "User's age in years"},
|
|
80
|
+
"email": {"type": "string", "format": "email", "description": "User's email address"}
|
|
81
|
+
},
|
|
82
|
+
"required": ["name", "age", "email"],
|
|
83
|
+
"additionalProperties": false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Complex example with arrays and nesting:
|
|
88
|
+
{
|
|
89
|
+
"name": "recipe_collection",
|
|
90
|
+
"strict": true,
|
|
91
|
+
"schema": {
|
|
92
|
+
"type": "object",
|
|
93
|
+
"properties": {
|
|
94
|
+
"recipes": {
|
|
95
|
+
"type": "array",
|
|
96
|
+
"items": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {
|
|
99
|
+
"name": {"type": "string", "description": "Recipe name"},
|
|
100
|
+
"ingredients": {
|
|
101
|
+
"type": "array",
|
|
102
|
+
"items": {
|
|
103
|
+
"type": "object",
|
|
104
|
+
"properties": {
|
|
105
|
+
"name": {"type": "string"},
|
|
106
|
+
"quantity": {"type": "string"}
|
|
107
|
+
},
|
|
108
|
+
"required": ["name", "quantity"],
|
|
109
|
+
"additionalProperties": false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"required": ["name", "ingredients"],
|
|
114
|
+
"additionalProperties": false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"required": ["recipes"],
|
|
119
|
+
"additionalProperties": false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Return ONLY the JSON object, no additional text or explanation.
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ai-chat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Raghu Betina
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
10
|
+
date: 2025-11-13 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: openai
|
|
@@ -16,14 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
18
|
+
version: '0.34'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0.
|
|
25
|
+
version: '0.34'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: marcel
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -42,6 +41,9 @@ dependencies:
|
|
|
42
41
|
name: base64
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.1'
|
|
45
47
|
- - ">"
|
|
46
48
|
- !ruby/object:Gem::Version
|
|
47
49
|
version: 0.1.1
|
|
@@ -49,6 +51,9 @@ dependencies:
|
|
|
49
51
|
prerelease: false
|
|
50
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
53
|
requirements:
|
|
54
|
+
- - "~>"
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '0.1'
|
|
52
57
|
- - ">"
|
|
53
58
|
- !ruby/object:Gem::Version
|
|
54
59
|
version: 0.1.1
|
|
@@ -66,20 +71,62 @@ dependencies:
|
|
|
66
71
|
- - "~>"
|
|
67
72
|
- !ruby/object:Gem::Version
|
|
68
73
|
version: '2.0'
|
|
74
|
+
- !ruby/object:Gem::Dependency
|
|
75
|
+
name: ostruct
|
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - "~>"
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0.2'
|
|
81
|
+
type: :runtime
|
|
82
|
+
prerelease: false
|
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - "~>"
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '0.2'
|
|
88
|
+
- !ruby/object:Gem::Dependency
|
|
89
|
+
name: tty-spinner
|
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - "~>"
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: 0.9.3
|
|
95
|
+
type: :runtime
|
|
96
|
+
prerelease: false
|
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - "~>"
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: 0.9.3
|
|
102
|
+
- !ruby/object:Gem::Dependency
|
|
103
|
+
name: amazing_print
|
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - "~>"
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '1.8'
|
|
109
|
+
type: :runtime
|
|
110
|
+
prerelease: false
|
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - "~>"
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '1.8'
|
|
69
116
|
- !ruby/object:Gem::Dependency
|
|
70
117
|
name: dotenv
|
|
71
118
|
requirement: !ruby/object:Gem::Requirement
|
|
72
119
|
requirements:
|
|
73
120
|
- - ">="
|
|
74
121
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
122
|
+
version: 1.0.0
|
|
76
123
|
type: :development
|
|
77
124
|
prerelease: false
|
|
78
125
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
126
|
requirements:
|
|
80
127
|
- - ">="
|
|
81
128
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
129
|
+
version: 1.0.0
|
|
83
130
|
- !ruby/object:Gem::Dependency
|
|
84
131
|
name: refinements
|
|
85
132
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,7 +141,6 @@ dependencies:
|
|
|
94
141
|
- - "~>"
|
|
95
142
|
- !ruby/object:Gem::Version
|
|
96
143
|
version: '11.1'
|
|
97
|
-
description:
|
|
98
144
|
email:
|
|
99
145
|
- raghu@firstdraft.com
|
|
100
146
|
executables: []
|
|
@@ -109,17 +155,18 @@ files:
|
|
|
109
155
|
- lib/ai-chat.rb
|
|
110
156
|
- lib/ai/amazing_print.rb
|
|
111
157
|
- lib/ai/chat.rb
|
|
158
|
+
- lib/ai/http.rb
|
|
159
|
+
- lib/prompts/schema_generator.md
|
|
112
160
|
homepage: https://github.com/firstdraft/ai-chat
|
|
113
161
|
licenses:
|
|
114
162
|
- MIT
|
|
115
163
|
metadata:
|
|
116
164
|
bug_tracker_uri: https://github.com/firstdraft/ai-chat/issues
|
|
117
165
|
changelog_uri: https://github.com/firstdraft/ai-chat/blob/main/CHANGELOG.md
|
|
118
|
-
homepage_uri: https://
|
|
166
|
+
homepage_uri: https://rubygems.org/gems/ai-chat
|
|
119
167
|
label: AI Chat
|
|
120
168
|
rubygems_mfa_required: 'true'
|
|
121
169
|
source_code_uri: https://github.com/firstdraft/ai-chat
|
|
122
|
-
post_install_message:
|
|
123
170
|
rdoc_options: []
|
|
124
171
|
require_paths:
|
|
125
172
|
- lib
|
|
@@ -134,8 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
181
|
- !ruby/object:Gem::Version
|
|
135
182
|
version: '0'
|
|
136
183
|
requirements: []
|
|
137
|
-
rubygems_version: 3.
|
|
138
|
-
signing_key:
|
|
184
|
+
rubygems_version: 3.6.2
|
|
139
185
|
specification_version: 4
|
|
140
186
|
summary: A beginner-friendly Ruby interface for OpenAI's API
|
|
141
187
|
test_files: []
|