vibe-sort 0.2.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +27 -0
- data/CHANGELOG.md +101 -0
- data/LICENSE.txt +21 -0
- data/README.md +281 -0
- data/Rakefile +12 -0
- data/docs/IMPLEMENTATION_PLAN.md +534 -0
- data/docs/README.md +211 -0
- data/docs/api_reference.md +440 -0
- data/docs/architecture.md +320 -0
- data/docs/development.md +566 -0
- data/docs/v0.2.0_UPDATE.md +377 -0
- data/lib/vibe/sort/version.rb +7 -0
- data/lib/vibe/sort.rb +10 -0
- data/lib/vibe_sort/client.rb +87 -0
- data/lib/vibe_sort/configuration.rb +21 -0
- data/lib/vibe_sort/error.rb +17 -0
- data/lib/vibe_sort/sorter.rb +125 -0
- data/lib/vibe_sort/version.rb +5 -0
- data/lib/vibe_sort.rb +14 -0
- data/sig/vibe/sort.rbs +6 -0
- metadata +83 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# Architecture Overview
|
|
2
|
+
|
|
3
|
+
## System Design
|
|
4
|
+
|
|
5
|
+
VibeSort follows a layered architecture with clear separation of concerns:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────┐
|
|
9
|
+
│ User Application │
|
|
10
|
+
└─────────────────┬───────────────────────┘
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
┌─────────────────────────────────────────┐
|
|
14
|
+
│ VibeSort::Client (Public API) │
|
|
15
|
+
│ - Input validation │
|
|
16
|
+
│ - Error handling │
|
|
17
|
+
│ - Response formatting │
|
|
18
|
+
└─────────────────┬───────────────────────┘
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
┌─────────────────────────────────────────┐
|
|
22
|
+
│ VibeSort::Configuration │
|
|
23
|
+
│ - API key management │
|
|
24
|
+
│ - Temperature settings │
|
|
25
|
+
└─────────────────┬───────────────────────┘
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
┌─────────────────────────────────────────┐
|
|
29
|
+
│ VibeSort::Sorter │
|
|
30
|
+
│ - HTTP client (Faraday) │
|
|
31
|
+
│ - Request building │
|
|
32
|
+
│ - Response parsing │
|
|
33
|
+
│ - Validation │
|
|
34
|
+
└─────────────────┬───────────────────────┘
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
┌─────────────────────────────────────────┐
|
|
38
|
+
│ OpenAI API │
|
|
39
|
+
│ https://api.openai.com/v1/chat/ │
|
|
40
|
+
│ completions │
|
|
41
|
+
└─────────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Component Details
|
|
45
|
+
|
|
46
|
+
### VibeSort::Client
|
|
47
|
+
|
|
48
|
+
**Purpose**: Public-facing interface that users interact with.
|
|
49
|
+
|
|
50
|
+
**Responsibilities**:
|
|
51
|
+
- Initialize configuration
|
|
52
|
+
- Validate input arrays (must be non-empty arrays of numbers)
|
|
53
|
+
- Delegate sorting to `Sorter`
|
|
54
|
+
- Catch and format exceptions
|
|
55
|
+
- Return standardized response hashes
|
|
56
|
+
|
|
57
|
+
**Key Methods**:
|
|
58
|
+
- `initialize(api_key:, temperature: 0.0)`: Creates client with configuration
|
|
59
|
+
- `sort(array)`: Sorts array and returns result hash
|
|
60
|
+
|
|
61
|
+
**Return Format**:
|
|
62
|
+
```ruby
|
|
63
|
+
{
|
|
64
|
+
success: Boolean,
|
|
65
|
+
sorted_array: Array<Numeric>,
|
|
66
|
+
error: String (only on failure)
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### VibeSort::Configuration
|
|
71
|
+
|
|
72
|
+
**Purpose**: Encapsulates configuration settings.
|
|
73
|
+
|
|
74
|
+
**Responsibilities**:
|
|
75
|
+
- Store API key securely
|
|
76
|
+
- Store temperature setting
|
|
77
|
+
- Validate API key presence
|
|
78
|
+
|
|
79
|
+
**Key Methods**:
|
|
80
|
+
- `initialize(api_key:, temperature:)`: Creates configuration
|
|
81
|
+
- Raises `ArgumentError` if API key is nil or empty
|
|
82
|
+
|
|
83
|
+
**Attributes**:
|
|
84
|
+
- `api_key`: OpenAI API key (String)
|
|
85
|
+
- `temperature`: Model temperature (Float, 0.0-2.0)
|
|
86
|
+
|
|
87
|
+
### VibeSort::Sorter
|
|
88
|
+
|
|
89
|
+
**Purpose**: Handles communication with OpenAI API.
|
|
90
|
+
|
|
91
|
+
**Responsibilities**:
|
|
92
|
+
- Build HTTP connection with Faraday
|
|
93
|
+
- Construct API request payload
|
|
94
|
+
- Send POST request to OpenAI
|
|
95
|
+
- Parse and validate JSON responses
|
|
96
|
+
- Extract sorted array from response
|
|
97
|
+
- Raise `ApiError` on failures
|
|
98
|
+
|
|
99
|
+
**Key Methods**:
|
|
100
|
+
- `initialize(config)`: Creates sorter with configuration
|
|
101
|
+
- `perform(array)`: Executes sort via API
|
|
102
|
+
- `build_payload(array)`: Private - constructs request
|
|
103
|
+
- `handle_response(response)`: Private - processes response
|
|
104
|
+
- `parse_sorted_array(response)`: Private - extracts result
|
|
105
|
+
- `validate_sorted_array!(array)`: Private - validates output
|
|
106
|
+
|
|
107
|
+
**Constants**:
|
|
108
|
+
- `OPENAI_API_URL`: API endpoint
|
|
109
|
+
- `DEFAULT_MODEL`: "gpt-3.5-turbo-1106" (supports JSON mode)
|
|
110
|
+
|
|
111
|
+
### VibeSort::ApiError
|
|
112
|
+
|
|
113
|
+
**Purpose**: Custom exception for API-related errors.
|
|
114
|
+
|
|
115
|
+
**Responsibilities**:
|
|
116
|
+
- Encapsulate error message
|
|
117
|
+
- Store HTTP response for debugging
|
|
118
|
+
- Provide clear error context
|
|
119
|
+
|
|
120
|
+
**Attributes**:
|
|
121
|
+
- `message`: Error description (String)
|
|
122
|
+
- `response`: Faraday::Response object (optional)
|
|
123
|
+
|
|
124
|
+
## Request Flow
|
|
125
|
+
|
|
126
|
+
1. **User calls `client.sort([34, 1, 99, 15, 8])`**
|
|
127
|
+
|
|
128
|
+
2. **Client validates input**
|
|
129
|
+
- Checks if input is an Array
|
|
130
|
+
- Checks if all elements are Numeric
|
|
131
|
+
- Returns error hash if invalid
|
|
132
|
+
|
|
133
|
+
3. **Client creates Sorter**
|
|
134
|
+
- Passes Configuration object
|
|
135
|
+
- Sorter initializes Faraday connection
|
|
136
|
+
|
|
137
|
+
4. **Sorter builds request payload**
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"model": "gpt-3.5-turbo-1106",
|
|
141
|
+
"temperature": 0.0,
|
|
142
|
+
"response_format": { "type": "json_object" },
|
|
143
|
+
"messages": [
|
|
144
|
+
{
|
|
145
|
+
"role": "system",
|
|
146
|
+
"content": "You are an assistant that only sorts..."
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"role": "user",
|
|
150
|
+
"content": "Please sort this array: [34,1,99,15,8]"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
5. **Sorter sends POST request**
|
|
157
|
+
- URL: `https://api.openai.com/v1/chat/completions`
|
|
158
|
+
- Headers: Authorization (Bearer token), Content-Type
|
|
159
|
+
- Body: JSON payload
|
|
160
|
+
|
|
161
|
+
6. **OpenAI processes request**
|
|
162
|
+
- Model analyzes the array
|
|
163
|
+
- Returns JSON with sorted array
|
|
164
|
+
|
|
165
|
+
7. **Sorter parses response**
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"choices": [{
|
|
169
|
+
"message": {
|
|
170
|
+
"content": "{\"sorted_array\": [1,8,15,34,99]}"
|
|
171
|
+
}
|
|
172
|
+
}]
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
8. **Sorter validates result**
|
|
177
|
+
- Checks if `sorted_array` key exists
|
|
178
|
+
- Validates all elements are Numeric
|
|
179
|
+
- Raises `ApiError` if invalid
|
|
180
|
+
|
|
181
|
+
9. **Client returns success hash**
|
|
182
|
+
```ruby
|
|
183
|
+
{
|
|
184
|
+
success: true,
|
|
185
|
+
sorted_array: [1, 8, 15, 34, 99]
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Error Handling
|
|
190
|
+
|
|
191
|
+
### Input Validation Errors
|
|
192
|
+
```ruby
|
|
193
|
+
# Empty array
|
|
194
|
+
{ success: false, sorted_array: [], error: "Input must be an array of numbers" }
|
|
195
|
+
|
|
196
|
+
# Non-array input
|
|
197
|
+
{ success: false, sorted_array: [], error: "Input must be an array of numbers" }
|
|
198
|
+
|
|
199
|
+
# Mixed types
|
|
200
|
+
{ success: false, sorted_array: [], error: "Input must be an array of numbers" }
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### API Errors
|
|
204
|
+
```ruby
|
|
205
|
+
# Invalid API key
|
|
206
|
+
{ success: false, sorted_array: [], error: "OpenAI API error: Invalid API key" }
|
|
207
|
+
|
|
208
|
+
# Rate limit
|
|
209
|
+
{ success: false, sorted_array: [], error: "OpenAI API error: Rate limit exceeded" }
|
|
210
|
+
|
|
211
|
+
# Network error
|
|
212
|
+
{ success: false, sorted_array: [], error: "Unexpected error: Connection failed" }
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Response Parsing Errors
|
|
216
|
+
```ruby
|
|
217
|
+
# Invalid JSON
|
|
218
|
+
{ success: false, sorted_array: [], error: "Failed to parse JSON response: ..." }
|
|
219
|
+
|
|
220
|
+
# Missing sorted_array key
|
|
221
|
+
{ success: false, sorted_array: [], error: "Response does not contain a valid 'sorted_array'" }
|
|
222
|
+
|
|
223
|
+
# Non-numeric values
|
|
224
|
+
{ success: false, sorted_array: [], error: "Sorted array contains non-numeric values" }
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Dependencies
|
|
228
|
+
|
|
229
|
+
### Runtime
|
|
230
|
+
- **faraday** (~> 2.0): HTTP client library
|
|
231
|
+
- **faraday-json** (~> 1.0): JSON middleware for Faraday
|
|
232
|
+
|
|
233
|
+
### Development
|
|
234
|
+
- **rspec** (~> 3.0): Testing framework
|
|
235
|
+
- **pry** (~> 0.14): Debugging console
|
|
236
|
+
|
|
237
|
+
## Design Decisions
|
|
238
|
+
|
|
239
|
+
### Why JSON Mode?
|
|
240
|
+
OpenAI's JSON mode (`response_format: { type: "json_object" }`) ensures the model always returns valid JSON, making parsing more reliable.
|
|
241
|
+
|
|
242
|
+
### Why Temperature 0.0 by Default?
|
|
243
|
+
Lower temperature (0.0) produces deterministic, consistent results. Sorting should be predictable, not creative!
|
|
244
|
+
|
|
245
|
+
### Why Faraday?
|
|
246
|
+
Faraday is a flexible, well-maintained HTTP client with middleware support, making it easy to add JSON encoding/decoding.
|
|
247
|
+
|
|
248
|
+
### Why Separate Client and Sorter?
|
|
249
|
+
Separation of concerns:
|
|
250
|
+
- **Client**: User-facing API, input validation, error formatting
|
|
251
|
+
- **Sorter**: HTTP communication, response parsing, API logic
|
|
252
|
+
|
|
253
|
+
This makes testing easier and keeps responsibilities clear.
|
|
254
|
+
|
|
255
|
+
## Testing Strategy
|
|
256
|
+
|
|
257
|
+
### Unit Tests
|
|
258
|
+
- Test each class in isolation
|
|
259
|
+
- Mock HTTP requests (use WebMock or VCR)
|
|
260
|
+
- Test error conditions
|
|
261
|
+
- Validate input/output formats
|
|
262
|
+
|
|
263
|
+
### Integration Tests
|
|
264
|
+
- Test full flow with real API (use test API key)
|
|
265
|
+
- Verify correct request format
|
|
266
|
+
- Verify response parsing
|
|
267
|
+
- Test various array sizes
|
|
268
|
+
|
|
269
|
+
### Edge Cases
|
|
270
|
+
- Empty arrays
|
|
271
|
+
- Single-element arrays
|
|
272
|
+
- Already sorted arrays
|
|
273
|
+
- Reverse-sorted arrays
|
|
274
|
+
- Duplicate values
|
|
275
|
+
- Negative numbers
|
|
276
|
+
- Floating-point numbers
|
|
277
|
+
- Very large numbers
|
|
278
|
+
|
|
279
|
+
## Security Considerations
|
|
280
|
+
|
|
281
|
+
1. **API Key Storage**: Never hardcode API keys. Use environment variables.
|
|
282
|
+
2. **Input Validation**: Always validate user input before sending to API.
|
|
283
|
+
3. **Output Validation**: Verify API responses before returning to user.
|
|
284
|
+
4. **Error Messages**: Don't expose sensitive information in error messages.
|
|
285
|
+
5. **HTTPS**: All API communication uses HTTPS (encrypted).
|
|
286
|
+
|
|
287
|
+
## Performance Considerations
|
|
288
|
+
|
|
289
|
+
### Latency
|
|
290
|
+
- Each sort requires an API round-trip (~1-3 seconds)
|
|
291
|
+
- Network latency varies by location
|
|
292
|
+
- OpenAI API processing time varies by load
|
|
293
|
+
|
|
294
|
+
### Cost
|
|
295
|
+
- OpenAI charges per token
|
|
296
|
+
- Each sort uses approximately 100-200 tokens
|
|
297
|
+
- Cost: ~$0.001-0.002 per sort (with gpt-3.5-turbo)
|
|
298
|
+
|
|
299
|
+
### Rate Limits
|
|
300
|
+
- OpenAI enforces rate limits (requests per minute)
|
|
301
|
+
- Free tier: 3 requests/minute
|
|
302
|
+
- Paid tier: 60+ requests/minute
|
|
303
|
+
|
|
304
|
+
### Scalability
|
|
305
|
+
- Not suitable for high-frequency sorting
|
|
306
|
+
- Consider batching if sorting multiple arrays
|
|
307
|
+
- Add caching if sorting same arrays repeatedly
|
|
308
|
+
|
|
309
|
+
## Future Enhancements
|
|
310
|
+
|
|
311
|
+
Potential improvements for future versions:
|
|
312
|
+
|
|
313
|
+
1. **Batch Sorting**: Sort multiple arrays in one API call
|
|
314
|
+
2. **Caching**: Cache results for identical inputs
|
|
315
|
+
3. **Custom Models**: Allow users to specify different GPT models
|
|
316
|
+
4. **Retry Logic**: Automatic retry on transient failures
|
|
317
|
+
5. **Async Support**: Non-blocking API calls with callbacks
|
|
318
|
+
6. **Metrics**: Track API usage, costs, and performance
|
|
319
|
+
7. **Different Sort Orders**: Support descending order
|
|
320
|
+
8. **Custom Sorting**: Allow custom comparison functions
|