lex-openai 0.1.1
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/.github/workflows/ci.yml +16 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +57 -0
- data/CHANGELOG.md +11 -0
- data/CLAUDE.md +61 -0
- data/Dockerfile +6 -0
- data/Gemfile +12 -0
- data/LICENSE +21 -0
- data/README.md +109 -0
- data/lex-openai.gemspec +32 -0
- data/lib/legion/extensions/openai/helpers/client.rb +26 -0
- data/lib/legion/extensions/openai/runners/audio.rb +51 -0
- data/lib/legion/extensions/openai/runners/chat.rb +32 -0
- data/lib/legion/extensions/openai/runners/embeddings.rb +27 -0
- data/lib/legion/extensions/openai/runners/files.rb +51 -0
- data/lib/legion/extensions/openai/runners/images.rb +55 -0
- data/lib/legion/extensions/openai/runners/models.rb +33 -0
- data/lib/legion/extensions/openai/runners/moderations.rb +26 -0
- data/lib/legion/extensions/openai/version.rb +9 -0
- data/lib/legion/extensions/openai.rb +19 -0
- metadata +109 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4e2104cbfd21361391e61c7f62492fa66a7e81693158b7fec6f6c187eb4b0696
|
|
4
|
+
data.tar.gz: 1bc10fcfd315c59547e2139fa27462d8142a221bc5c133de01b3f06806f4807f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 004ed985a19682f10c58e1a5067f4345483a5e3bad4d7aa182a62f00a14d1a0fa831af3f1269c02af7a75961fb506ac0172c74f6a752dfd9ac8780e4b2a966f2
|
|
7
|
+
data.tar.gz: dd23c73e298d53594a9ebded51bd99423ad13cd0da21a2c233acfbcef03d8c956e38be1fbbd6c89f5c41bc8dd5e2c4591e55b9f4f231b8eea6c599f1bc7f3c22
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.4
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Layout/LineLength:
|
|
7
|
+
Max: 160
|
|
8
|
+
|
|
9
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
+
EnforcedStyle: space
|
|
11
|
+
|
|
12
|
+
Layout/HashAlignment:
|
|
13
|
+
EnforcedHashRocketStyle: table
|
|
14
|
+
EnforcedColonStyle: table
|
|
15
|
+
|
|
16
|
+
Metrics/MethodLength:
|
|
17
|
+
Max: 50
|
|
18
|
+
|
|
19
|
+
Metrics/ClassLength:
|
|
20
|
+
Max: 1500
|
|
21
|
+
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Max: 1500
|
|
24
|
+
|
|
25
|
+
Metrics/BlockLength:
|
|
26
|
+
Max: 40
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'spec/**/*'
|
|
29
|
+
|
|
30
|
+
Metrics/AbcSize:
|
|
31
|
+
Max: 60
|
|
32
|
+
|
|
33
|
+
Metrics/CyclomaticComplexity:
|
|
34
|
+
Max: 15
|
|
35
|
+
|
|
36
|
+
Metrics/PerceivedComplexity:
|
|
37
|
+
Max: 17
|
|
38
|
+
|
|
39
|
+
Style/Documentation:
|
|
40
|
+
Enabled: false
|
|
41
|
+
|
|
42
|
+
Style/SymbolArray:
|
|
43
|
+
Enabled: true
|
|
44
|
+
|
|
45
|
+
Style/FrozenStringLiteralComment:
|
|
46
|
+
Enabled: true
|
|
47
|
+
EnforcedStyle: always
|
|
48
|
+
|
|
49
|
+
Metrics/ParameterLists:
|
|
50
|
+
Max: 12
|
|
51
|
+
|
|
52
|
+
Naming/FileName:
|
|
53
|
+
Enabled: false
|
|
54
|
+
|
|
55
|
+
Naming/MethodParameterName:
|
|
56
|
+
AllowedNames:
|
|
57
|
+
- n
|
data/CHANGELOG.md
ADDED
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# lex-openai: OpenAI Integration for LegionIO
|
|
2
|
+
|
|
3
|
+
**Repository Level 3 Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-ai/CLAUDE.md`
|
|
5
|
+
- **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Legion Extension that connects LegionIO to OpenAI. Provides runners for chat completions, image generation, audio processing, embeddings, file management, and content moderation.
|
|
10
|
+
|
|
11
|
+
**GitHub**: https://github.com/LegionIO/lex-openai
|
|
12
|
+
**License**: MIT
|
|
13
|
+
**Version**: 0.1.0
|
|
14
|
+
**Specs**: 17 examples
|
|
15
|
+
|
|
16
|
+
## Architecture
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Legion::Extensions::Openai
|
|
20
|
+
├── Runners/
|
|
21
|
+
│ ├── Chat # create(model:, messages:, api_key:, ...)
|
|
22
|
+
│ ├── Models # list(api_key:, ...), retrieve(api_key:, model_id:, ...), delete(api_key:, model_id:, ...)
|
|
23
|
+
│ ├── Images # generate(prompt:, api_key:, model: 'dall-e-3', ...), edit(...), variation(...)
|
|
24
|
+
│ ├── Audio # speech(input:, api_key:, model: 'tts-1', voice: 'alloy', ...), transcribe(...), translate(...)
|
|
25
|
+
│ ├── Embeddings # create(input:, model:, api_key:, ...)
|
|
26
|
+
│ ├── Files # list, upload, retrieve, delete, content (download)
|
|
27
|
+
│ └── Moderations # create(input:, api_key:, ...)
|
|
28
|
+
└── Helpers/
|
|
29
|
+
└── Client # OpenAI API client (module, Faraday factory, Bearer auth)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`Helpers::Client` is a **module** (not a class). It does not use `module_function` — instead, runner modules `extend` it so `client(...)` is available as a module-level method. `DEFAULT_BASE_URL` is `'https://api.openai.com'`.
|
|
33
|
+
|
|
34
|
+
## Key Design Decisions
|
|
35
|
+
|
|
36
|
+
- `faraday/multipart` is required unconditionally in `Helpers::Client` — the `:multipart` middleware is always loaded. This is a hard dependency (listed in gemspec), unlike lex-gemini where it is optional.
|
|
37
|
+
- Images (edit, variation) and Audio (transcribe, translate) runners use `Faraday::Multipart::FilePart` directly.
|
|
38
|
+
- `Images#generate` uses DALL-E 3 by default; `Images#edit` and `Images#variation` use DALL-E 2 by default.
|
|
39
|
+
- Audio defaults: `model: 'tts-1'`, `voice: 'alloy'`, `response_format: 'mp3'` for speech; `model: 'whisper-1'` for transcription/translation.
|
|
40
|
+
- Chat runner returns `{ result: response.body }` (no `:status` key) — differs slightly from claude/gemini runner return shapes.
|
|
41
|
+
- `include Legion::Extensions::Helpers::Lex` is guarded with `Legion::Extensions.const_defined?(:Helpers)` pattern.
|
|
42
|
+
|
|
43
|
+
## Dependencies
|
|
44
|
+
|
|
45
|
+
| Gem | Purpose |
|
|
46
|
+
|-----|---------|
|
|
47
|
+
| `faraday` >= 2.0 | HTTP client |
|
|
48
|
+
| `faraday-multipart` >= 1.0 | Multipart file uploads (images, audio, files) |
|
|
49
|
+
| `multi_json` | JSON parser abstraction |
|
|
50
|
+
|
|
51
|
+
## Testing
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
bundle install
|
|
55
|
+
bundle exec rspec # 17 examples
|
|
56
|
+
bundle exec rubocop
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Dockerfile
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Esity
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# lex-openai
|
|
2
|
+
|
|
3
|
+
OpenAI integration for [LegionIO](https://github.com/LegionIO/LegionIO). Provides runners for chat completions, image generation, audio processing, embeddings, file management, and content moderation via the OpenAI API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
gem install lex-openai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or add to your Gemfile:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem 'lex-openai'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Functions
|
|
18
|
+
|
|
19
|
+
### Chat
|
|
20
|
+
- `create` - Create a chat completion
|
|
21
|
+
|
|
22
|
+
### Models
|
|
23
|
+
- `list` - List available models
|
|
24
|
+
- `retrieve` - Get model details
|
|
25
|
+
- `delete` - Delete a fine-tuned model
|
|
26
|
+
|
|
27
|
+
### Images
|
|
28
|
+
- `generate` - Generate images from text prompts (DALL-E 3 default)
|
|
29
|
+
- `edit` - Edit images with text prompts and masks (DALL-E 2)
|
|
30
|
+
- `variation` - Create variations of an image (DALL-E 2)
|
|
31
|
+
|
|
32
|
+
### Audio
|
|
33
|
+
- `speech` - Generate speech from text (TTS, default model: tts-1)
|
|
34
|
+
- `transcribe` - Transcribe audio to text (Whisper)
|
|
35
|
+
- `translate` - Translate audio to English text (Whisper)
|
|
36
|
+
|
|
37
|
+
### Embeddings
|
|
38
|
+
- `create` - Generate vector embeddings
|
|
39
|
+
|
|
40
|
+
### Files
|
|
41
|
+
- `list` - List uploaded files
|
|
42
|
+
- `upload` - Upload a file
|
|
43
|
+
- `retrieve` - Get file metadata
|
|
44
|
+
- `delete` - Delete a file
|
|
45
|
+
- `content` - Download file content
|
|
46
|
+
|
|
47
|
+
### Moderations
|
|
48
|
+
- `create` - Classify content for policy compliance
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
Set your API key in your LegionIO settings:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"openai": {
|
|
57
|
+
"api_key": "sk-..."
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Standalone Usage
|
|
63
|
+
|
|
64
|
+
Runner modules can be extended directly onto any module or object. Each runner method requires `api_key:` as a keyword argument.
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
require 'legion/extensions/openai/runners/chat'
|
|
68
|
+
require 'legion/extensions/openai/runners/images'
|
|
69
|
+
|
|
70
|
+
# Chat completion
|
|
71
|
+
module ChatClient
|
|
72
|
+
extend Legion::Extensions::Openai::Runners::Chat
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
result = ChatClient.create(
|
|
76
|
+
model: 'gpt-4o',
|
|
77
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
78
|
+
api_key: ENV['OPENAI_API_KEY']
|
|
79
|
+
)
|
|
80
|
+
puts result[:result]['choices'].first['message']['content']
|
|
81
|
+
|
|
82
|
+
# Image generation
|
|
83
|
+
module ImageClient
|
|
84
|
+
extend Legion::Extensions::Openai::Runners::Images
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
image = ImageClient.generate(
|
|
88
|
+
prompt: 'A futuristic city at sunset',
|
|
89
|
+
model: 'dall-e-3',
|
|
90
|
+
api_key: ENV['OPENAI_API_KEY']
|
|
91
|
+
)
|
|
92
|
+
puts image[:result]['data'].first['url']
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Dependencies
|
|
96
|
+
|
|
97
|
+
- `faraday` >= 2.0 - HTTP client
|
|
98
|
+
- `faraday-multipart` >= 1.0 - Multipart file uploads (images, audio, files)
|
|
99
|
+
- `multi_json` - JSON parser abstraction
|
|
100
|
+
|
|
101
|
+
## Requirements
|
|
102
|
+
|
|
103
|
+
- Ruby >= 3.4
|
|
104
|
+
- [LegionIO](https://github.com/LegionIO/LegionIO) framework (optional for standalone runner usage)
|
|
105
|
+
- OpenAI API key
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
data/lex-openai.gemspec
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/openai/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-openai'
|
|
7
|
+
spec.version = Legion::Extensions::Openai::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'LEX Openai'
|
|
12
|
+
spec.description = 'Connects LegionIO to OpenAI'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-openai'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-openai'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-openai'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-openai'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-openai/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
end
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
|
|
29
|
+
spec.add_dependency 'faraday', '>= 2.0'
|
|
30
|
+
spec.add_dependency 'faraday-multipart', '>= 1.0'
|
|
31
|
+
spec.add_dependency 'multi_json'
|
|
32
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'faraday/multipart'
|
|
5
|
+
require 'multi_json'
|
|
6
|
+
|
|
7
|
+
module Legion
|
|
8
|
+
module Extensions
|
|
9
|
+
module Openai
|
|
10
|
+
module Helpers
|
|
11
|
+
module Client
|
|
12
|
+
DEFAULT_BASE_URL = 'https://api.openai.com'
|
|
13
|
+
|
|
14
|
+
def client(api_key:, base_url: DEFAULT_BASE_URL, **)
|
|
15
|
+
Faraday.new(url: base_url) do |conn|
|
|
16
|
+
conn.request :json
|
|
17
|
+
conn.request :multipart
|
|
18
|
+
conn.response :json, content_type: /\bjson$/
|
|
19
|
+
conn.headers['Authorization'] = "Bearer #{api_key}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Audio
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def speech(input:, api_key:, model: 'tts-1', voice: 'alloy', response_format: 'mp3', speed: nil, **)
|
|
13
|
+
body = { model: model, input: input, voice: voice, response_format: response_format }
|
|
14
|
+
body[:speed] = speed if speed
|
|
15
|
+
|
|
16
|
+
response = client(api_key: api_key, **).post('/v1/audio/speech', body)
|
|
17
|
+
{ result: response.body }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def transcribe(file:, api_key:, model: 'whisper-1', language: nil, prompt: nil, response_format: nil, **)
|
|
21
|
+
payload = {
|
|
22
|
+
file: Faraday::Multipart::FilePart.new(file, 'audio/mpeg'),
|
|
23
|
+
model: model
|
|
24
|
+
}
|
|
25
|
+
payload[:language] = language if language
|
|
26
|
+
payload[:prompt] = prompt if prompt
|
|
27
|
+
payload[:response_format] = response_format if response_format
|
|
28
|
+
|
|
29
|
+
response = client(api_key: api_key, **).post('/v1/audio/transcriptions', payload)
|
|
30
|
+
{ result: response.body }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def translate(file:, api_key:, model: 'whisper-1', prompt: nil, response_format: nil, **)
|
|
34
|
+
payload = {
|
|
35
|
+
file: Faraday::Multipart::FilePart.new(file, 'audio/mpeg'),
|
|
36
|
+
model: model
|
|
37
|
+
}
|
|
38
|
+
payload[:prompt] = prompt if prompt
|
|
39
|
+
payload[:response_format] = response_format if response_format
|
|
40
|
+
|
|
41
|
+
response = client(api_key: api_key, **).post('/v1/audio/translations', payload)
|
|
42
|
+
{ result: response.body }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
46
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Chat
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def create(model:, messages:, api_key:, temperature: nil, max_tokens: nil, top_p: nil,
|
|
13
|
+
frequency_penalty: nil, presence_penalty: nil, stop: nil, stream: false, **)
|
|
14
|
+
body = { model: model, messages: messages, stream: stream }
|
|
15
|
+
body[:temperature] = temperature if temperature
|
|
16
|
+
body[:max_tokens] = max_tokens if max_tokens
|
|
17
|
+
body[:top_p] = top_p if top_p
|
|
18
|
+
body[:frequency_penalty] = frequency_penalty if frequency_penalty
|
|
19
|
+
body[:presence_penalty] = presence_penalty if presence_penalty
|
|
20
|
+
body[:stop] = stop if stop
|
|
21
|
+
|
|
22
|
+
response = client(api_key: api_key, **).post('/v1/chat/completions', body)
|
|
23
|
+
{ result: response.body }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
27
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Embeddings
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def create(input:, api_key:, model: 'text-embedding-3-small', encoding_format: nil, dimensions: nil, **)
|
|
13
|
+
body = { input: input, model: model }
|
|
14
|
+
body[:encoding_format] = encoding_format if encoding_format
|
|
15
|
+
body[:dimensions] = dimensions if dimensions
|
|
16
|
+
|
|
17
|
+
response = client(api_key: api_key, **).post('/v1/embeddings', body)
|
|
18
|
+
{ result: response.body }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
22
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Files
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def list(api_key:, purpose: nil, **)
|
|
13
|
+
path = '/v1/files'
|
|
14
|
+
path += "?purpose=#{purpose}" if purpose
|
|
15
|
+
|
|
16
|
+
response = client(api_key: api_key, **).get(path)
|
|
17
|
+
{ result: response.body }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def upload(file:, purpose:, api_key:, **)
|
|
21
|
+
payload = {
|
|
22
|
+
file: Faraday::Multipart::FilePart.new(file, 'application/octet-stream'),
|
|
23
|
+
purpose: purpose
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
response = client(api_key: api_key, **).post('/v1/files', payload)
|
|
27
|
+
{ result: response.body }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def retrieve(file_id:, api_key:, **)
|
|
31
|
+
response = client(api_key: api_key, **).get("/v1/files/#{file_id}")
|
|
32
|
+
{ result: response.body }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete(file_id:, api_key:, **)
|
|
36
|
+
response = client(api_key: api_key, **).delete("/v1/files/#{file_id}")
|
|
37
|
+
{ result: response.body }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def content(file_id:, api_key:, **)
|
|
41
|
+
response = client(api_key: api_key, **).get("/v1/files/#{file_id}/content")
|
|
42
|
+
{ result: response.body }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
46
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Images
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def generate(prompt:, api_key:, model: 'dall-e-3', n: 1, size: '1024x1024',
|
|
13
|
+
quality: nil, style: nil, response_format: nil, **)
|
|
14
|
+
body = { prompt: prompt, model: model, n: n, size: size }
|
|
15
|
+
body[:quality] = quality if quality
|
|
16
|
+
body[:style] = style if style
|
|
17
|
+
body[:response_format] = response_format if response_format
|
|
18
|
+
|
|
19
|
+
response = client(api_key: api_key, **).post('/v1/images/generations', body)
|
|
20
|
+
{ result: response.body }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def edit(image:, prompt:, api_key:, model: 'dall-e-2', mask: nil, n: 1, size: '1024x1024', **)
|
|
24
|
+
payload = {
|
|
25
|
+
image: Faraday::Multipart::FilePart.new(image, 'image/png'),
|
|
26
|
+
prompt: prompt,
|
|
27
|
+
model: model,
|
|
28
|
+
n: n.to_s,
|
|
29
|
+
size: size
|
|
30
|
+
}
|
|
31
|
+
payload[:mask] = Faraday::Multipart::FilePart.new(mask, 'image/png') if mask
|
|
32
|
+
|
|
33
|
+
response = client(api_key: api_key, **).post('/v1/images/edits', payload)
|
|
34
|
+
{ result: response.body }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def variation(image:, api_key:, model: 'dall-e-2', n: 1, size: '1024x1024', **)
|
|
38
|
+
payload = {
|
|
39
|
+
image: Faraday::Multipart::FilePart.new(image, 'image/png'),
|
|
40
|
+
model: model,
|
|
41
|
+
n: n.to_s,
|
|
42
|
+
size: size
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
response = client(api_key: api_key, **).post('/v1/images/variations', payload)
|
|
46
|
+
{ result: response.body }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
50
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Models
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def list(api_key:, **)
|
|
13
|
+
response = client(api_key: api_key, **).get('/v1/models')
|
|
14
|
+
{ result: response.body }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve(model:, api_key:, **)
|
|
18
|
+
response = client(api_key: api_key, **).get("/v1/models/#{model}")
|
|
19
|
+
{ result: response.body }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def delete(model:, api_key:, **)
|
|
23
|
+
response = client(api_key: api_key, **).delete("/v1/models/#{model}")
|
|
24
|
+
{ result: response.body }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
28
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/helpers/client'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Openai
|
|
8
|
+
module Runners
|
|
9
|
+
module Moderations
|
|
10
|
+
extend Legion::Extensions::Openai::Helpers::Client
|
|
11
|
+
|
|
12
|
+
def create(input:, api_key:, model: nil, **)
|
|
13
|
+
body = { input: input }
|
|
14
|
+
body[:model] = model if model
|
|
15
|
+
|
|
16
|
+
response = client(api_key: api_key, **).post('/v1/moderations', body)
|
|
17
|
+
{ result: response.body }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
21
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/openai/version'
|
|
4
|
+
require 'legion/extensions/openai/helpers/client'
|
|
5
|
+
require 'legion/extensions/openai/runners/chat'
|
|
6
|
+
require 'legion/extensions/openai/runners/models'
|
|
7
|
+
require 'legion/extensions/openai/runners/images'
|
|
8
|
+
require 'legion/extensions/openai/runners/audio'
|
|
9
|
+
require 'legion/extensions/openai/runners/embeddings'
|
|
10
|
+
require 'legion/extensions/openai/runners/files'
|
|
11
|
+
require 'legion/extensions/openai/runners/moderations'
|
|
12
|
+
|
|
13
|
+
module Legion
|
|
14
|
+
module Extensions
|
|
15
|
+
module Openai
|
|
16
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-openai
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: faraday
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: faraday-multipart
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: multi_json
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
description: Connects LegionIO to OpenAI
|
|
55
|
+
email:
|
|
56
|
+
- matthewdiverson@gmail.com
|
|
57
|
+
executables: []
|
|
58
|
+
extensions: []
|
|
59
|
+
extra_rdoc_files: []
|
|
60
|
+
files:
|
|
61
|
+
- ".github/workflows/ci.yml"
|
|
62
|
+
- ".gitignore"
|
|
63
|
+
- ".rspec"
|
|
64
|
+
- ".rubocop.yml"
|
|
65
|
+
- CHANGELOG.md
|
|
66
|
+
- CLAUDE.md
|
|
67
|
+
- Dockerfile
|
|
68
|
+
- Gemfile
|
|
69
|
+
- LICENSE
|
|
70
|
+
- README.md
|
|
71
|
+
- lex-openai.gemspec
|
|
72
|
+
- lib/legion/extensions/openai.rb
|
|
73
|
+
- lib/legion/extensions/openai/helpers/client.rb
|
|
74
|
+
- lib/legion/extensions/openai/runners/audio.rb
|
|
75
|
+
- lib/legion/extensions/openai/runners/chat.rb
|
|
76
|
+
- lib/legion/extensions/openai/runners/embeddings.rb
|
|
77
|
+
- lib/legion/extensions/openai/runners/files.rb
|
|
78
|
+
- lib/legion/extensions/openai/runners/images.rb
|
|
79
|
+
- lib/legion/extensions/openai/runners/models.rb
|
|
80
|
+
- lib/legion/extensions/openai/runners/moderations.rb
|
|
81
|
+
- lib/legion/extensions/openai/version.rb
|
|
82
|
+
homepage: https://github.com/LegionIO/lex-openai
|
|
83
|
+
licenses:
|
|
84
|
+
- MIT
|
|
85
|
+
metadata:
|
|
86
|
+
homepage_uri: https://github.com/LegionIO/lex-openai
|
|
87
|
+
source_code_uri: https://github.com/LegionIO/lex-openai
|
|
88
|
+
documentation_uri: https://github.com/LegionIO/lex-openai
|
|
89
|
+
changelog_uri: https://github.com/LegionIO/lex-openai
|
|
90
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-openai/issues
|
|
91
|
+
rubygems_mfa_required: 'true'
|
|
92
|
+
rdoc_options: []
|
|
93
|
+
require_paths:
|
|
94
|
+
- lib
|
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '3.4'
|
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
requirements: []
|
|
106
|
+
rubygems_version: 3.6.9
|
|
107
|
+
specification_version: 4
|
|
108
|
+
summary: LEX Openai
|
|
109
|
+
test_files: []
|