...
This commit is contained in:
19
lib/clients/openai/audio/README.md
Normal file
19
lib/clients/openai/audio/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Quick Example: Transcribing Audio
|
||||
|
||||
```v
|
||||
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()! //will be the default client, key is in `AIKEY` on environment variable or `OPENROUTER_API_KEY`
|
||||
|
||||
// Assuming you have an audio file named 'audio.mp3' in the same directory
|
||||
// For a real application, handle file paths dynamically
|
||||
audio_file_path := 'audio.mp3'
|
||||
|
||||
resp := client.audio.create_transcription(
|
||||
file: audio_file_path,
|
||||
model: 'whisper-1'
|
||||
)!
|
||||
|
||||
```
|
||||
|
||||
@@ -1,9 +1,88 @@
|
||||
module openai
|
||||
module audio
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
import os
|
||||
import net.http
|
||||
import freeflowuniverse.herolib.clients.openai { OpenAI }
|
||||
|
||||
type OpenAIAlias = OpenAI
|
||||
|
||||
pub enum Voice {
|
||||
alloy
|
||||
ash
|
||||
coral
|
||||
echo
|
||||
fable
|
||||
onyx
|
||||
nova
|
||||
sage
|
||||
shimmer
|
||||
}
|
||||
|
||||
fn voice_str(x Voice) string {
|
||||
return match x {
|
||||
.alloy {
|
||||
'alloy'
|
||||
}
|
||||
.ash {
|
||||
'ash'
|
||||
}
|
||||
.coral {
|
||||
'coral'
|
||||
}
|
||||
.echo {
|
||||
'echo'
|
||||
}
|
||||
.fable {
|
||||
'fable'
|
||||
}
|
||||
.onyx {
|
||||
'onyx'
|
||||
}
|
||||
.nova {
|
||||
'nova'
|
||||
}
|
||||
.sage {
|
||||
'sage'
|
||||
}
|
||||
.shimmer {
|
||||
'shimmer'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AudioFormat {
|
||||
mp3
|
||||
opus
|
||||
aac
|
||||
flac
|
||||
wav
|
||||
pcm
|
||||
}
|
||||
|
||||
fn audio_format_str(x AudioFormat) string {
|
||||
return match x {
|
||||
.mp3 {
|
||||
'mp3'
|
||||
}
|
||||
.opus {
|
||||
'opus'
|
||||
}
|
||||
.aac {
|
||||
'aac'
|
||||
}
|
||||
.flac {
|
||||
'flac'
|
||||
}
|
||||
.wav {
|
||||
'wav'
|
||||
}
|
||||
.pcm {
|
||||
'pcm'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AudioRespType {
|
||||
json
|
||||
@@ -44,6 +123,7 @@ fn audio_resp_type_str(i AudioRespType) string {
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct AudioArgs {
|
||||
pub mut:
|
||||
filepath string
|
||||
@@ -60,17 +140,17 @@ pub mut:
|
||||
|
||||
// create transcription from an audio file
|
||||
// supported audio formats are mp3, mp4, mpeg, mpga, m4a, wav, or webm
|
||||
pub fn (mut f OpenAI) create_transcription(args AudioArgs) !AudioResponse {
|
||||
pub fn (mut f OpenAIAlias) create_transcription(args AudioArgs) !AudioResponse {
|
||||
return f.create_audio_request(args, 'audio/transcriptions')
|
||||
}
|
||||
|
||||
// create translation to english from an audio file
|
||||
// supported audio formats are mp3, mp4, mpeg, mpga, m4a, wav, or webm
|
||||
pub fn (mut f OpenAI) create_tranlation(args AudioArgs) !AudioResponse {
|
||||
pub fn (mut f OpenAIAlias) create_tranlation(args AudioArgs) !AudioResponse {
|
||||
return f.create_audio_request(args, 'audio/translations')
|
||||
}
|
||||
|
||||
fn (mut f OpenAI) create_audio_request(args AudioArgs, endpoint string) !AudioResponse {
|
||||
fn (mut f OpenAIAlias) create_audio_request(args AudioArgs, endpoint string) !AudioResponse {
|
||||
file_content := os.read_file(args.filepath)!
|
||||
ext := os.file_ext(args.filepath)
|
||||
mut file_mime_type := ''
|
||||
@@ -131,7 +211,7 @@ pub:
|
||||
speed f32
|
||||
}
|
||||
|
||||
pub fn (mut f OpenAI) create_speech(args CreateSpeechArgs) ! {
|
||||
pub fn (mut f OpenAIAlias) create_speech(args CreateSpeechArgs) ! {
|
||||
mut output_file := os.open_file(args.output_path, 'w+')!
|
||||
|
||||
req := CreateSpeechRequest{
|
||||
26
lib/clients/openai/audio/audio_test.v
Normal file
26
lib/clients/openai/audio/audio_test.v
Normal file
@@ -0,0 +1,26 @@
|
||||
module audio_test
|
||||
|
||||
import os
|
||||
import clients.openai
|
||||
import clients.openai.audio
|
||||
import clients.openai.openai_factory_ { get }
|
||||
import freeflowuniverse.crystallib.osal { play }
|
||||
|
||||
fn test_audio() {
|
||||
key := os.getenv('OPENAI_API_KEY')
|
||||
heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
play(heroscript: heroscript)!
|
||||
|
||||
mut client := get()!
|
||||
|
||||
// create speech
|
||||
client.create_speech(
|
||||
input: 'the quick brown fox jumps over the lazy dog'
|
||||
output_path: '/tmp/output.mp3'
|
||||
voice: audio.Voice.alloy
|
||||
response_format: audio.AudioFormat.mp3
|
||||
)!
|
||||
|
||||
assert os.exists('/tmp/output.mp3')
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
module openai
|
||||
|
||||
import os
|
||||
import openai.audio
|
||||
import openai.files
|
||||
import openai.finetune
|
||||
import openai.images
|
||||
|
||||
fn test_chat_completion() {
|
||||
mut client := get()!
|
||||
@@ -24,83 +28,3 @@ fn test_chat_completion() {
|
||||
|
||||
assert res.choices[0].message.content == 'AI is getting out of hand'
|
||||
}
|
||||
|
||||
// fn test_embeddings() {
|
||||
// key := os.getenv('OPENAI_API_KEY')
|
||||
// heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
// play(heroscript: heroscript)!
|
||||
|
||||
// mut client := get()!
|
||||
|
||||
// res := client.create_embeddings(
|
||||
// input: ['The food was delicious and the waiter..']
|
||||
// model: .text_embedding_ada
|
||||
// )!
|
||||
|
||||
// assert res.data.len == 1
|
||||
// assert res.data[0].embedding.len == 1536
|
||||
// }
|
||||
|
||||
// fn test_files() {
|
||||
// key := os.getenv('OPENAI_API_KEY')
|
||||
// heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
// play(heroscript: heroscript)!
|
||||
|
||||
// mut client := get()!
|
||||
// uploaded_file := client.upload_file(
|
||||
// filepath: '${os.dir(@FILE) + '/testdata/testfile.txt'}'
|
||||
// purpose: .assistants
|
||||
// )!
|
||||
|
||||
// assert uploaded_file.filename == 'testfile.txt'
|
||||
// assert uploaded_file.purpose == 'assistants'
|
||||
|
||||
// got_file := client.get_file(uploaded_file.id)!
|
||||
// assert got_file == uploaded_file
|
||||
|
||||
// uploaded_file2 := client.upload_file(
|
||||
// filepath: '${os.dir(@FILE) + '/testdata/testfile2.txt'}'
|
||||
// purpose: .assistants
|
||||
// )!
|
||||
|
||||
// assert uploaded_file2.filename == 'testfile2.txt'
|
||||
// assert uploaded_file2.purpose == 'assistants'
|
||||
|
||||
// mut got_list := client.list_files()!
|
||||
|
||||
// assert got_list.data.len >= 2 // there could be other older files
|
||||
|
||||
// mut ids := []string{}
|
||||
// for file in got_list.data {
|
||||
// ids << file.id
|
||||
// }
|
||||
|
||||
// assert uploaded_file.id in ids
|
||||
// assert uploaded_file2.id in ids
|
||||
|
||||
// for file in got_list.data {
|
||||
// client.delete_file(file.id)!
|
||||
// }
|
||||
|
||||
// got_list = client.list_files()!
|
||||
// assert got_list.data.len == 0
|
||||
// }
|
||||
|
||||
// fn test_audio() {
|
||||
// key := os.getenv('OPENAI_API_KEY')
|
||||
// heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
// play(heroscript: heroscript)!
|
||||
|
||||
// mut client := get()!
|
||||
|
||||
// // create speech
|
||||
// client.create_speech(
|
||||
// input: 'the quick brown fox jumps over the lazy dog'
|
||||
// output_path: '/tmp/output.mp3'
|
||||
// )!
|
||||
|
||||
// assert os.exists('/tmp/output.mp3')
|
||||
// }
|
||||
|
||||
@@ -2,63 +2,61 @@ module openai
|
||||
|
||||
import json
|
||||
|
||||
pub struct ChatCompletion {
|
||||
pub mut:
|
||||
id string
|
||||
object string
|
||||
created u32
|
||||
choices []Choice
|
||||
usage Usage
|
||||
}
|
||||
|
||||
pub struct Choice {
|
||||
pub mut:
|
||||
index int
|
||||
message MessageRaw
|
||||
finish_reason string
|
||||
}
|
||||
|
||||
pub struct Message {
|
||||
pub mut:
|
||||
role RoleType
|
||||
content string
|
||||
}
|
||||
|
||||
pub struct Usage {
|
||||
pub mut:
|
||||
prompt_tokens int
|
||||
completion_tokens int
|
||||
total_tokens int
|
||||
}
|
||||
|
||||
pub struct Messages {
|
||||
pub mut:
|
||||
messages []Message
|
||||
}
|
||||
|
||||
pub struct MessageRaw {
|
||||
pub mut:
|
||||
role string
|
||||
content string
|
||||
}
|
||||
|
||||
struct ChatMessagesRaw {
|
||||
mut:
|
||||
model string
|
||||
messages []MessageRaw
|
||||
temperature f64 = 0.5
|
||||
max_completion_tokens int = 32000
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CompletionArgs {
|
||||
pub mut:
|
||||
model string
|
||||
msgs Messages
|
||||
temperature f64 = 0.5
|
||||
messages []Message // optional because we can use message, which means we just pass a string
|
||||
message string
|
||||
temperature f64 = 0.2
|
||||
max_completion_tokens int = 32000
|
||||
}
|
||||
|
||||
struct Message {
|
||||
mut:
|
||||
role RoleType
|
||||
content string
|
||||
}
|
||||
|
||||
pub enum RoleType {
|
||||
system
|
||||
user
|
||||
assistant
|
||||
function
|
||||
}
|
||||
|
||||
fn roletype_str(x RoleType) string {
|
||||
return match x {
|
||||
.system {
|
||||
'system'
|
||||
}
|
||||
.user {
|
||||
'user'
|
||||
}
|
||||
.assistant {
|
||||
'assistant'
|
||||
}
|
||||
.function {
|
||||
'function'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Usage {
|
||||
mut:
|
||||
prompt_tokens int
|
||||
completion_tokens int
|
||||
total_tokens int
|
||||
}
|
||||
|
||||
struct ChatCompletion {
|
||||
mut:
|
||||
id string
|
||||
created u32
|
||||
result string
|
||||
usage Usage
|
||||
}
|
||||
|
||||
// creates a new chat completion given a list of messages
|
||||
// each message consists of message content and the role of the author
|
||||
pub fn (mut f OpenAI) chat_completion(args_ CompletionArgs) !ChatCompletion {
|
||||
@@ -71,19 +69,38 @@ pub fn (mut f OpenAI) chat_completion(args_ CompletionArgs) !ChatCompletion {
|
||||
temperature: args.temperature
|
||||
max_completion_tokens: args.max_completion_tokens
|
||||
}
|
||||
for msg in args.msgs.messages {
|
||||
for msg in args.messages {
|
||||
mr := MessageRaw{
|
||||
role: roletype_str(msg.role)
|
||||
content: msg.content
|
||||
}
|
||||
m.messages << mr
|
||||
}
|
||||
if args.message != '' {
|
||||
mr := MessageRaw{
|
||||
role: 'user'
|
||||
content: args.message
|
||||
}
|
||||
m.messages << mr
|
||||
}
|
||||
data := json.encode(m)
|
||||
// println('data: ${data}')
|
||||
mut conn := f.connection()!
|
||||
r := conn.post_json_str(prefix: 'chat/completions', data: data)!
|
||||
// println('res: ${r}')
|
||||
|
||||
res := json.decode(ChatCompletion, r)!
|
||||
return res
|
||||
res := json.decode(ChatCompletionRaw, r)!
|
||||
|
||||
mut result := ''
|
||||
for choice in res.choices {
|
||||
result += choice.message.content
|
||||
}
|
||||
|
||||
mut chat_completion_result := ChatCompletion{
|
||||
id: res.id
|
||||
created: res.created
|
||||
result: result
|
||||
usage: res.usage
|
||||
}
|
||||
return chat_completion_result
|
||||
}
|
||||
|
||||
17
lib/clients/openai/embeddings/README.md
Normal file
17
lib/clients/openai/embeddings/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
# Quick Example: Creating Embeddings
|
||||
|
||||
```v
|
||||
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()! //will be the default client, key is in `AIKEY` on environment variable or `OPENROUTER_API_KEY`
|
||||
|
||||
text_to_embed := 'The quick brown fox jumps over the lazy dog.'
|
||||
|
||||
resp := client.embeddings.create_embedding(
|
||||
input: text_to_embed,
|
||||
model: 'text-embedding-ada-002'
|
||||
)!
|
||||
|
||||
```
|
||||
@@ -1,6 +1,9 @@
|
||||
module openai
|
||||
module embeddings
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.clients.openai { OpenAI, Usage }
|
||||
|
||||
type OpenAIAlias = OpenAI
|
||||
|
||||
pub enum EmbeddingModel {
|
||||
text_embedding_ada
|
||||
@@ -42,7 +45,7 @@ pub mut:
|
||||
usage Usage
|
||||
}
|
||||
|
||||
pub fn (mut f OpenAI) create_embeddings(args EmbeddingCreateArgs) !EmbeddingResponse {
|
||||
pub fn (mut f OpenAIAlias) create_embeddings(args EmbeddingCreateArgs) !EmbeddingResponse {
|
||||
req := EmbeddingCreateRequest{
|
||||
input: args.input
|
||||
model: embedding_model_str(args.model)
|
||||
24
lib/clients/openai/embeddings/embeddings_test.v
Normal file
24
lib/clients/openai/embeddings/embeddings_test.v
Normal file
@@ -0,0 +1,24 @@
|
||||
module embeddings_test
|
||||
|
||||
import os
|
||||
import clients.openai
|
||||
import clients.openai.embeddings
|
||||
import clients.openai.openai_factory_ { get }
|
||||
import freeflowuniverse.crystallib.osal { play }
|
||||
|
||||
fn test_embeddings() {
|
||||
key := os.getenv('OPENAI_API_KEY')
|
||||
heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
play(heroscript: heroscript)!
|
||||
|
||||
mut client := get()!
|
||||
|
||||
res := client.create_embeddings(
|
||||
input: ['The food was delicious and the waiter..']
|
||||
model: embeddings.EmbeddingModel.text_embedding_ada
|
||||
)!
|
||||
|
||||
assert res.data.len == 1
|
||||
assert res.data[0].embedding.len == 1536
|
||||
}
|
||||
25
lib/clients/openai/files/README.md
Normal file
25
lib/clients/openai/files/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
# Example: Uploading a File
|
||||
|
||||
```v
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()! //will be the default client, key is in `AIKEY` on environment variable or `OPENROUTER_API_KEY`
|
||||
|
||||
// Assuming you have a file named 'mydata.jsonl' in the same directory
|
||||
// For a real application, handle file paths dynamically
|
||||
file_path := 'mydata.jsonl'
|
||||
|
||||
resp := client.files.upload_file(
|
||||
file: file_path,
|
||||
purpose: 'fine-tune' // or 'assistants', 'batch', 'vision'
|
||||
)
|
||||
|
||||
if resp.id.len > 0 {
|
||||
println('File uploaded successfully with ID: ${resp.id}')
|
||||
} else {
|
||||
eprintln('Failed to upload file.')
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
@@ -1,9 +1,12 @@
|
||||
module openai
|
||||
module files
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
import os
|
||||
import net.http
|
||||
import freeflowuniverse.herolib.clients.openai { OpenAI }
|
||||
|
||||
type OpenAIAlias = OpenAI
|
||||
|
||||
const jsonl_mime_type = 'text/jsonl'
|
||||
|
||||
@@ -44,7 +47,7 @@ pub mut:
|
||||
}
|
||||
|
||||
// upload file to client org, usually used for fine tuning
|
||||
pub fn (mut f OpenAI) upload_file(args FileUploadArgs) !File {
|
||||
pub fn (mut f OpenAIAlias) upload_file(args FileUploadArgs) !File {
|
||||
file_content := os.read_file(args.filepath)!
|
||||
|
||||
file_data := http.FileData{
|
||||
@@ -74,28 +77,28 @@ pub fn (mut f OpenAI) upload_file(args FileUploadArgs) !File {
|
||||
}
|
||||
|
||||
// list all files in client org
|
||||
pub fn (mut f OpenAI) list_files() !Files {
|
||||
pub fn (mut f OpenAIAlias) list_files() !Files {
|
||||
mut conn := f.connection()!
|
||||
r := conn.get(prefix: 'files')!
|
||||
return json.decode(Files, r)!
|
||||
}
|
||||
|
||||
// deletes a file
|
||||
pub fn (mut f OpenAI) delete_file(file_id string) !DeleteResp {
|
||||
pub fn (mut f OpenAIAlias) delete_file(file_id string) !DeleteResp {
|
||||
mut conn := f.connection()!
|
||||
r := conn.delete(prefix: 'files/' + file_id)!
|
||||
return json.decode(DeleteResp, r)!
|
||||
}
|
||||
|
||||
// returns a single file metadata
|
||||
pub fn (mut f OpenAI) get_file(file_id string) !File {
|
||||
pub fn (mut f OpenAIAlias) get_file(file_id string) !File {
|
||||
mut conn := f.connection()!
|
||||
r := conn.get(prefix: 'files/' + file_id)!
|
||||
return json.decode(File, r)!
|
||||
}
|
||||
|
||||
// returns the content of a specific file
|
||||
pub fn (mut f OpenAI) get_file_content(file_id string) !string {
|
||||
pub fn (mut f OpenAIAlias) get_file_content(file_id string) !string {
|
||||
mut conn := f.connection()!
|
||||
r := conn.get(prefix: 'files/' + file_id + '/content')!
|
||||
return r
|
||||
1
lib/clients/openai/files/files_test.v
Normal file
1
lib/clients/openai/files/files_test.v
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
22
lib/clients/openai/finetune/README.md
Normal file
22
lib/clients/openai/finetune/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# OpenAI Fine-tuning Client
|
||||
|
||||
|
||||
```v
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()! //will be the default client, key is in `AIKEY` on environment variable or `OPENROUTER_API_KEY`
|
||||
|
||||
// Assuming you have a training file ID from the Files API
|
||||
training_file_id := 'file-xxxxxxxxxxxxxxxxxxxxxxxxx'
|
||||
|
||||
resp := client.finetune.create_fine_tune(
|
||||
training_file: training_file_id,
|
||||
model: 'gpt-3.5-turbo'
|
||||
)
|
||||
|
||||
if resp.id.len > 0 {
|
||||
println('Fine-tuning job created with ID: ${resp.id}')
|
||||
} else {
|
||||
eprintln('Failed to create fine-tuning job.')
|
||||
}
|
||||
```
|
||||
@@ -1,7 +1,11 @@
|
||||
module openai
|
||||
module finetune
|
||||
|
||||
import freeflowuniverse.herolib.clients.openai { OpenAI }
|
||||
import freeflowuniverse.herolib.clients.openai.files { File }
|
||||
import json
|
||||
|
||||
type OpenAIAlias = OpenAI
|
||||
|
||||
pub struct FineTune {
|
||||
pub:
|
||||
id string
|
||||
@@ -61,7 +65,7 @@ pub mut:
|
||||
}
|
||||
|
||||
// creates a new fine-tune based on an already uploaded file
|
||||
pub fn (mut f OpenAI) create_fine_tune(args FineTuneCreateArgs) !FineTune {
|
||||
pub fn (mut f OpenAIAlias) create_fine_tune(args FineTuneCreateArgs) !FineTune {
|
||||
data := json.encode(args)
|
||||
mut conn := f.connection()!
|
||||
r := conn.post_json_str(prefix: 'fine-tunes', data: data)!
|
||||
@@ -70,28 +74,28 @@ pub fn (mut f OpenAI) create_fine_tune(args FineTuneCreateArgs) !FineTune {
|
||||
}
|
||||
|
||||
// returns all fine-tunes in this account
|
||||
pub fn (mut f OpenAI) list_fine_tunes() !FineTuneList {
|
||||
pub fn (mut f OpenAIAlias) list_fine_tunes() !FineTuneList {
|
||||
mut conn := f.connection()!
|
||||
r := conn.get(prefix: 'fine-tunes')!
|
||||
return json.decode(FineTuneList, r)!
|
||||
}
|
||||
|
||||
// get a single fine-tune information
|
||||
pub fn (mut f OpenAI) get_fine_tune(fine_tune string) !FineTune {
|
||||
pub fn (mut f OpenAIAlias) get_fine_tune(fine_tune string) !FineTune {
|
||||
mut conn := f.connection()!
|
||||
r := conn.get(prefix: 'fine-tunes/' + fine_tune)!
|
||||
return json.decode(FineTune, r)!
|
||||
}
|
||||
|
||||
// cancel a fine-tune that didn't finish yet
|
||||
pub fn (mut f OpenAI) cancel_fine_tune(fine_tune string) !FineTune {
|
||||
pub fn (mut f OpenAIAlias) cancel_fine_tune(fine_tune string) !FineTune {
|
||||
mut conn := f.connection()!
|
||||
r := conn.post_json_str(prefix: 'fine-tunes/' + fine_tune + '/cancel')!
|
||||
return json.decode(FineTune, r)!
|
||||
}
|
||||
|
||||
// returns all events for a fine tune in this account
|
||||
pub fn (mut f OpenAI) list_fine_tune_events(fine_tune string) !FineTuneEventList {
|
||||
pub fn (mut f OpenAIAlias) list_fine_tune_events(fine_tune string) !FineTuneEventList {
|
||||
mut conn := f.connection()!
|
||||
r := conn.get(prefix: 'fine-tunes/' + fine_tune + '/events')!
|
||||
return json.decode(FineTuneEventList, r)!
|
||||
21
lib/clients/openai/images/README.md
Normal file
21
lib/clients/openai/images/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
# Example: Creating an Image
|
||||
|
||||
```v
|
||||
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()! //will be the default client, key is in `AIKEY` on environment variable or `OPENROUTER_API_KEY`
|
||||
|
||||
resp := client.images.create_image(
|
||||
prompt: 'A futuristic city at sunset',
|
||||
n: 1,
|
||||
size: '1024x1024'
|
||||
)
|
||||
|
||||
if resp.data.len > 0 {
|
||||
println('Image created. URL: ${resp.data[0].url}')
|
||||
} else {
|
||||
eprintln('Failed to create image.')
|
||||
}
|
||||
```
|
||||
@@ -4,6 +4,9 @@ import json
|
||||
import net.http
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
import freeflowuniverse.herolib.clients.openai { OpenAI }
|
||||
|
||||
type OpenAIAlias = OpenAI
|
||||
|
||||
const image_mine_type = 'image/png'
|
||||
|
||||
@@ -43,6 +46,7 @@ fn image_resp_type_str(i ImageRespType) string {
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ImageCreateArgs {
|
||||
pub mut:
|
||||
prompt string
|
||||
@@ -95,7 +99,7 @@ pub mut:
|
||||
|
||||
// Create new images generation given a prompt
|
||||
// the amount of images returned is specified by `num_images`
|
||||
pub fn (mut f OpenAI) create_image(args ImageCreateArgs) !Images {
|
||||
pub fn (mut f OpenAIAlias) create_image(args ImageCreateArgs) !Images {
|
||||
image_size := image_size_str(args.size)
|
||||
response_format := image_resp_type_str(args.format)
|
||||
request := ImageRequest{
|
||||
@@ -115,7 +119,7 @@ pub fn (mut f OpenAI) create_image(args ImageCreateArgs) !Images {
|
||||
// image needs to be in PNG format and transparent or else a mask of the same size needs
|
||||
// to be specified to indicate where the image should be in the generated image
|
||||
// the amount of images returned is specified by `num_images`
|
||||
pub fn (mut f OpenAI) create_edit_image(args ImageEditArgs) !Images {
|
||||
pub fn (mut f OpenAIAlias) create_edit_image(args ImageEditArgs) !Images {
|
||||
image_content := os.read_file(args.image_path)!
|
||||
image_file := http.FileData{
|
||||
filename: os.base(args.image_path)
|
||||
@@ -160,7 +164,7 @@ pub fn (mut f OpenAI) create_edit_image(args ImageEditArgs) !Images {
|
||||
// create variations of the given image
|
||||
// image needs to be in PNG format
|
||||
// the amount of images returned is specified by `num_images`
|
||||
pub fn (mut f OpenAI) create_variation_image(args ImageVariationArgs) !Images {
|
||||
pub fn (mut f OpenAIAlias) create_variation_image(args ImageVariationArgs) !Images {
|
||||
image_content := os.read_file(args.image_path)!
|
||||
image_file := http.FileData{
|
||||
filename: os.base(args.image_path)
|
||||
@@ -1,101 +0,0 @@
|
||||
module openai
|
||||
|
||||
pub enum RoleType {
|
||||
system
|
||||
user
|
||||
assistant
|
||||
function
|
||||
}
|
||||
|
||||
fn roletype_str(x RoleType) string {
|
||||
return match x {
|
||||
.system {
|
||||
'system'
|
||||
}
|
||||
.user {
|
||||
'user'
|
||||
}
|
||||
.assistant {
|
||||
'assistant'
|
||||
}
|
||||
.function {
|
||||
'function'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Voice {
|
||||
alloy
|
||||
ash
|
||||
coral
|
||||
echo
|
||||
fable
|
||||
onyx
|
||||
nova
|
||||
sage
|
||||
shimmer
|
||||
}
|
||||
|
||||
fn voice_str(x Voice) string {
|
||||
return match x {
|
||||
.alloy {
|
||||
'alloy'
|
||||
}
|
||||
.ash {
|
||||
'ash'
|
||||
}
|
||||
.coral {
|
||||
'coral'
|
||||
}
|
||||
.echo {
|
||||
'echo'
|
||||
}
|
||||
.fable {
|
||||
'fable'
|
||||
}
|
||||
.onyx {
|
||||
'onyx'
|
||||
}
|
||||
.nova {
|
||||
'nova'
|
||||
}
|
||||
.sage {
|
||||
'sage'
|
||||
}
|
||||
.shimmer {
|
||||
'shimmer'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AudioFormat {
|
||||
mp3
|
||||
opus
|
||||
aac
|
||||
flac
|
||||
wav
|
||||
pcm
|
||||
}
|
||||
|
||||
fn audio_format_str(x AudioFormat) string {
|
||||
return match x {
|
||||
.mp3 {
|
||||
'mp3'
|
||||
}
|
||||
.opus {
|
||||
'opus'
|
||||
}
|
||||
.aac {
|
||||
'aac'
|
||||
}
|
||||
.flac {
|
||||
'flac'
|
||||
}
|
||||
.wav {
|
||||
'wav'
|
||||
}
|
||||
.pcm {
|
||||
'pcm'
|
||||
}
|
||||
}
|
||||
}
|
||||
31
lib/clients/openai/model_models_completion.v
Normal file
31
lib/clients/openai/model_models_completion.v
Normal file
@@ -0,0 +1,31 @@
|
||||
module openai
|
||||
|
||||
struct ChatCompletionRaw {
|
||||
mut:
|
||||
id string
|
||||
object string
|
||||
created u32
|
||||
choices []ChoiceRaw
|
||||
usage Usage
|
||||
}
|
||||
|
||||
struct ChoiceRaw {
|
||||
mut:
|
||||
index int
|
||||
message MessageRaw
|
||||
finish_reason string
|
||||
}
|
||||
|
||||
struct MessageRaw {
|
||||
mut:
|
||||
role string
|
||||
content string
|
||||
}
|
||||
|
||||
struct ChatMessagesRaw {
|
||||
mut:
|
||||
model string
|
||||
messages []MessageRaw
|
||||
temperature f64 = 0.5
|
||||
max_completion_tokens int = 32000
|
||||
}
|
||||
30
lib/clients/openai/moderation/README.md
Normal file
30
lib/clients/openai/moderation/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# OpenAI Moderation Client
|
||||
|
||||
This directory contains the V client for OpenAI's Moderation API.
|
||||
|
||||
|
||||
```v
|
||||
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()! //will be the default client, key is in `AIKEY` on environment variable or `OPENROUTER_API_KEY`
|
||||
|
||||
text_to_moderate := 'I want to kill them all.'
|
||||
|
||||
resp := client.moderation.create_moderation(
|
||||
input: text_to_moderate
|
||||
)
|
||||
|
||||
if resp.results.len > 0 {
|
||||
if resp.results[0].flagged {
|
||||
println('Text was flagged for moderation.')
|
||||
println('Categories: ${resp.results[0].categories}')
|
||||
} else {
|
||||
println('Text passed moderation.')
|
||||
}
|
||||
} else {
|
||||
eprintln('Failed to get moderation result.')
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
module openai
|
||||
module moderation
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.clients.openai { OpenAI }
|
||||
|
||||
type OpenAIAlias = OpenAI
|
||||
|
||||
pub enum ModerationModel {
|
||||
text_moderation_latest
|
||||
@@ -69,7 +72,7 @@ pub mut:
|
||||
results []ModerationResult
|
||||
}
|
||||
|
||||
pub fn (mut f OpenAI) create_moderation(input string, model ModerationModel) !ModerationResponse {
|
||||
pub fn (mut f OpenAIAlias) create_moderation(input string, model ModerationModel) !ModerationResponse {
|
||||
req := ModerationRequest{
|
||||
input: input
|
||||
model: moderation_model_str(model)
|
||||
@@ -8,57 +8,42 @@ pub const version = '0.0.0'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
|
||||
// @[heap]
|
||||
// pub struct OpenAIBase {
|
||||
// pub mut:
|
||||
// name string = 'default'
|
||||
// api_key string
|
||||
// url string
|
||||
// model_default string
|
||||
// }
|
||||
|
||||
@[heap]
|
||||
pub struct OpenAI {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
api_key string
|
||||
url string
|
||||
model_default string
|
||||
url string = 'https://openrouter.ai/api/v1'
|
||||
model_default string = 'gpt-oss-120b'
|
||||
conn ?&httpconnection.HTTPConnection @[skip; str: skip]
|
||||
}
|
||||
|
||||
// your checking & initialization code if needed
|
||||
fn obj_init(mycfg_ OpenAI) !OpenAI {
|
||||
mut mycfg := mycfg_
|
||||
if mycfg.model_default == '' {
|
||||
k := os.getenv('AIMODEL')
|
||||
if k != '' {
|
||||
mycfg.model_default = k
|
||||
}
|
||||
}
|
||||
|
||||
if mycfg.url == '' {
|
||||
k := os.getenv('AIURL')
|
||||
if k != '' {
|
||||
mycfg.url = k
|
||||
}
|
||||
}
|
||||
if mycfg.api_key == '' {
|
||||
mut k := os.getenv('AIKEY')
|
||||
k := os.getenv('AIKEY')
|
||||
if k != '' {
|
||||
mycfg.api_key = k
|
||||
k = os.getenv('AIURL')
|
||||
if k != '' {
|
||||
mycfg.url = k
|
||||
} else {
|
||||
return error('found AIKEY in env, but not AIURL')
|
||||
}
|
||||
k = os.getenv('AIMODEL')
|
||||
if k != '' {
|
||||
mycfg.model_default = k
|
||||
}
|
||||
return mycfg
|
||||
}
|
||||
mycfg.url = 'https://api.openai.com/v1/models'
|
||||
k = os.getenv('OPENAI_API_KEY')
|
||||
if k != '' {
|
||||
mycfg.api_key = k
|
||||
return mycfg
|
||||
}
|
||||
k = os.getenv('OPENROUTER_API_KEY')
|
||||
if k != '' {
|
||||
mycfg.api_key = k
|
||||
mycfg.url = 'https://openrouter.ai/api/v1'
|
||||
return mycfg
|
||||
if k == '' {
|
||||
k2 := os.getenv('OPENROUTER_API_KEY')
|
||||
if k2 != '' {
|
||||
mycfg.api_key = k2
|
||||
}
|
||||
}
|
||||
}
|
||||
return mycfg
|
||||
|
||||
@@ -4,21 +4,27 @@ To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
|
||||
playcmds.run(
|
||||
heroscript:'
|
||||
!!openai.configure name: "default" key: "" url: "https://openrouter.ai/api/v1" model_default: "gpt-oss-120b"
|
||||
'
|
||||
heroscript_path:''
|
||||
reset: false
|
||||
)!
|
||||
|
||||
//name:'default' is the default, you can change it to whatever you want
|
||||
mut client:= openai.get()!
|
||||
|
||||
client...
|
||||
|
||||
|
||||
|
||||
mut r:=client.chat_completion(
|
||||
model: "gpt-3.5-turbo",
|
||||
message: 'Hello, world!'
|
||||
temperature: 0.5
|
||||
max_completion_tokens: 1024
|
||||
)!
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
```hero
|
||||
!!openai.configure key
|
||||
```
|
||||
if key empty then will try to get it from environment variable `AIKEY` or `OPENROUTER_API_KEY`
|
||||
|
||||
1
lib/clients/openai/testdata/testfile.txt
vendored
1
lib/clients/openai/testdata/testfile.txt
vendored
@@ -1 +0,0 @@
|
||||
hello world
|
||||
1
lib/clients/openai/testdata/testfile2.txt
vendored
1
lib/clients/openai/testdata/testfile2.txt
vendored
@@ -1 +0,0 @@
|
||||
testfile2 content
|
||||
Reference in New Issue
Block a user