...
This commit is contained in:
@@ -114,7 +114,7 @@ fn (mut f OpenAI) create_audio_request(args AudioArgs, endpoint string) !AudioRe
|
||||
@[params]
|
||||
pub struct CreateSpeechArgs {
|
||||
pub:
|
||||
model ModelType = .tts_1
|
||||
model string = "tts_1"
|
||||
input string @[required]
|
||||
voice Voice = .alloy
|
||||
response_format AudioFormat = .mp3
|
||||
@@ -135,7 +135,7 @@ pub fn (mut f OpenAI) create_speech(args CreateSpeechArgs) ! {
|
||||
mut output_file := os.open_file(args.output_path, 'w+')!
|
||||
|
||||
req := CreateSpeechRequest{
|
||||
model: modelname_str(args.model)
|
||||
model: args.model
|
||||
input: args.input
|
||||
voice: voice_str(args.voice)
|
||||
response_format: audio_format_str(args.response_format)
|
||||
|
||||
@@ -3,14 +3,15 @@ module openai
|
||||
import os
|
||||
|
||||
fn test_chat_completion() {
|
||||
key := os.getenv('OPENAI_API_KEY')
|
||||
heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
play(heroscript: heroscript)!
|
||||
|
||||
mut client := get()!
|
||||
|
||||
res := client.chat_completion(.gpt_4o_2024_08_06.str(), Messages{
|
||||
client.model_default = 'llama-3.3-70b-versatile'
|
||||
|
||||
println(client.list_models()!)
|
||||
|
||||
raise("sss")
|
||||
|
||||
res := client.chat_completion( Messages{
|
||||
messages: [
|
||||
Message{
|
||||
role: .user
|
||||
@@ -24,82 +25,82 @@ 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}"'
|
||||
// fn test_embeddings() {
|
||||
// key := os.getenv('OPENAI_API_KEY')
|
||||
// heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
play(heroscript: heroscript)!
|
||||
// play(heroscript: heroscript)!
|
||||
|
||||
mut client := get()!
|
||||
// mut client := get()!
|
||||
|
||||
res := client.create_embeddings(
|
||||
input: ['The food was delicious and the waiter..']
|
||||
model: .text_embedding_ada
|
||||
)!
|
||||
// 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
|
||||
}
|
||||
// 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}"'
|
||||
// fn test_files() {
|
||||
// key := os.getenv('OPENAI_API_KEY')
|
||||
// heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
play(heroscript: heroscript)!
|
||||
// play(heroscript: heroscript)!
|
||||
|
||||
mut client := get()!
|
||||
uploaded_file := client.upload_file(
|
||||
filepath: '${os.dir(@FILE) + '/testdata/testfile.txt'}'
|
||||
purpose: .assistants
|
||||
)!
|
||||
// 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'
|
||||
// assert uploaded_file.filename == 'testfile.txt'
|
||||
// assert uploaded_file.purpose == 'assistants'
|
||||
|
||||
got_file := client.get_file(uploaded_file.id)!
|
||||
assert got_file == uploaded_file
|
||||
// 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
|
||||
)!
|
||||
// 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'
|
||||
// assert uploaded_file2.filename == 'testfile2.txt'
|
||||
// assert uploaded_file2.purpose == 'assistants'
|
||||
|
||||
mut got_list := client.list_files()!
|
||||
// mut got_list := client.list_files()!
|
||||
|
||||
assert got_list.data.len >= 2 // there could be other older 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
|
||||
}
|
||||
// mut ids := []string{}
|
||||
// for file in got_list.data {
|
||||
// ids << file.id
|
||||
// }
|
||||
|
||||
assert uploaded_file.id in ids
|
||||
assert uploaded_file2.id in ids
|
||||
// assert uploaded_file.id in ids
|
||||
// assert uploaded_file2.id in ids
|
||||
|
||||
for file in got_list.data {
|
||||
client.delete_file(file.id)!
|
||||
}
|
||||
// for file in got_list.data {
|
||||
// client.delete_file(file.id)!
|
||||
// }
|
||||
|
||||
got_list = client.list_files()!
|
||||
assert got_list.data.len == 0
|
||||
}
|
||||
// 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}"'
|
||||
// fn test_audio() {
|
||||
// key := os.getenv('OPENAI_API_KEY')
|
||||
// heroscript := '!!openai.configure api_key: "${key}"'
|
||||
|
||||
play(heroscript: heroscript)!
|
||||
// play(heroscript: heroscript)!
|
||||
|
||||
mut client := get()!
|
||||
// mut client := get()!
|
||||
|
||||
// create speech
|
||||
client.create_speech(
|
||||
input: 'the quick brown fox jumps over the lazy dog'
|
||||
output_path: '/tmp/output.mp3'
|
||||
)!
|
||||
// // 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')
|
||||
}
|
||||
// assert os.exists('/tmp/output.mp3')
|
||||
// }
|
||||
|
||||
@@ -48,13 +48,25 @@ mut:
|
||||
messages []MessageRaw
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CompletionArgs{
|
||||
pub mut:
|
||||
model string
|
||||
msgs Messages
|
||||
|
||||
}
|
||||
|
||||
// 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(model_type string, msgs Messages) !ChatCompletion {
|
||||
mut m := ChatMessagesRaw{
|
||||
model: model_type
|
||||
pub fn (mut f OpenAI) chat_completion(args_ CompletionArgs) !ChatCompletion {
|
||||
mut args:=args_
|
||||
if args.model==""{
|
||||
args.model = f.model_default
|
||||
}
|
||||
for msg in msgs.messages {
|
||||
mut m := ChatMessagesRaw{
|
||||
model: args.model
|
||||
}
|
||||
for msg in args.msgs.messages {
|
||||
mr := MessageRaw{
|
||||
role: roletype_str(msg.role)
|
||||
content: msg.content
|
||||
@@ -62,10 +74,10 @@ pub fn (mut f OpenAI) chat_completion(model_type string, msgs Messages) !ChatCom
|
||||
m.messages << mr
|
||||
}
|
||||
data := json.encode(m)
|
||||
println('data: ${data}')
|
||||
// println('data: ${data}')
|
||||
mut conn := f.connection()!
|
||||
r := conn.post_json_str(prefix: 'chat/completions', data: data)!
|
||||
println('res: ${r}')
|
||||
// println('res: ${r}')
|
||||
|
||||
res := json.decode(ChatCompletion, r)!
|
||||
return res
|
||||
|
||||
@@ -1,57 +1,5 @@
|
||||
module openai
|
||||
|
||||
pub enum ModelType {
|
||||
gpt_4o_2024_08_06
|
||||
gpt_3_5_turbo
|
||||
gpt_4
|
||||
gpt_4_0613
|
||||
gpt_4_32k
|
||||
gpt_4_32k_0613
|
||||
gpt_3_5_turbo_0613
|
||||
gpt_3_5_turbo_16k
|
||||
gpt_3_5_turbo_16k_0613
|
||||
whisper_1
|
||||
tts_1
|
||||
}
|
||||
|
||||
fn modelname_str(e ModelType) string {
|
||||
return match e {
|
||||
.tts_1 {
|
||||
'tts-1'
|
||||
}
|
||||
.gpt_4o_2024_08_06 {
|
||||
'gpt-4o-2024-08-06'
|
||||
}
|
||||
.gpt_4 {
|
||||
'gpt-4'
|
||||
}
|
||||
.gpt_3_5_turbo {
|
||||
'gpt-3.5-turbo'
|
||||
}
|
||||
.gpt_4_0613 {
|
||||
'gpt-4-0613'
|
||||
}
|
||||
.gpt_4_32k {
|
||||
'gpt-4-32k'
|
||||
}
|
||||
.gpt_4_32k_0613 {
|
||||
'gpt-4-32k-0613'
|
||||
}
|
||||
.gpt_3_5_turbo_0613 {
|
||||
'gpt-3.5-turbo-0613'
|
||||
}
|
||||
.gpt_3_5_turbo_16k {
|
||||
'gpt-3.5-turbo-16k'
|
||||
}
|
||||
.gpt_3_5_turbo_16k_0613 {
|
||||
'gpt-3.5-turbo-16k-0613'
|
||||
}
|
||||
.whisper_1 {
|
||||
'whisper-1'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RoleType {
|
||||
system
|
||||
user
|
||||
|
||||
112
lib/clients/openai/openai_factory_.v
Normal file
112
lib/clients/openai/openai_factory_.v
Normal file
@@ -0,0 +1,112 @@
|
||||
module openai
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
__global (
|
||||
openai_global map[string]&OpenAI
|
||||
openai_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut args := args_
|
||||
if args.name == '' {
|
||||
args.name = 'default'
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&OpenAI {
|
||||
mut context := base.context()!
|
||||
mut args := args_get(args_)
|
||||
mut obj := OpenAI{name:args.name}
|
||||
if args.name !in openai_global {
|
||||
if !exists(args)! {
|
||||
set(obj)!
|
||||
} else {
|
||||
heroscript := context.hero_config_get('openai', args.name)!
|
||||
mut obj_ := heroscript_loads(heroscript)!
|
||||
set_in_mem(obj_)!
|
||||
}
|
||||
}
|
||||
return openai_global[args.name] or {
|
||||
println(openai_global)
|
||||
// bug if we get here because should be in globals
|
||||
panic('could not get config for openai with name, is bug, was for: ${args.name}')
|
||||
}
|
||||
}
|
||||
|
||||
// register the config for the future
|
||||
pub fn set(o OpenAI) ! {
|
||||
set_in_mem(o)!
|
||||
mut context := base.context()!
|
||||
heroscript := heroscript_dumps(o)!
|
||||
context.hero_config_set('openai', o.name, heroscript)!
|
||||
}
|
||||
|
||||
// does the config exists?
|
||||
pub fn exists(args_ ArgsGet) !bool {
|
||||
mut context := base.context()!
|
||||
mut args := args_get(args_)
|
||||
return context.hero_config_exists('openai', args.name)
|
||||
}
|
||||
|
||||
pub fn delete(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
context.hero_config_delete('openai', args.name)!
|
||||
if args.name in openai_global {
|
||||
// del openai_global[args.name]
|
||||
}
|
||||
}
|
||||
|
||||
// only sets in mem, does not set as config
|
||||
fn set_in_mem(o OpenAI) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
openai_global[o.name] = &o2
|
||||
openai_default = o.name
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut install_actions := plbook.find(filter: 'openai.configure')!
|
||||
if install_actions.len > 0 {
|
||||
for install_action in install_actions {
|
||||
heroscript := install_action.heroscript()
|
||||
mut obj2 := heroscript_loads(heroscript)!
|
||||
set(obj2)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// switch instance to be used for openai
|
||||
pub fn switch(name string) {
|
||||
openai_default = name
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
@[params]
|
||||
pub struct DefaultConfigArgs {
|
||||
instance string = 'default'
|
||||
}
|
||||
93
lib/clients/openai/openai_model.v
Normal file
93
lib/clients/openai/openai_model.v
Normal file
@@ -0,0 +1,93 @@
|
||||
module openai
|
||||
|
||||
import freeflowuniverse.herolib.data.encoderhero
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
import os
|
||||
|
||||
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
|
||||
conn ?&httpconnection.HTTPConnection @[skip; str: skip]
|
||||
}
|
||||
|
||||
// your checking & initialization code if needed
|
||||
fn obj_init(mycfg_ OpenAI) !OpenAI {
|
||||
mut mycfg := mycfg_
|
||||
if mycfg.api_key==""{
|
||||
|
||||
mut 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
|
||||
}
|
||||
}
|
||||
return mycfg
|
||||
}
|
||||
|
||||
pub fn (mut client OpenAI) connection() !&httpconnection.HTTPConnection {
|
||||
mut c := client.conn or {
|
||||
mut c2 := httpconnection.new(
|
||||
name: 'openaiconnection_${client.name}'
|
||||
url: client.url
|
||||
cache: false
|
||||
retry: 20
|
||||
)!
|
||||
c2
|
||||
}
|
||||
c.default_header.set(.authorization, 'Bearer ${client.api_key}')
|
||||
client.conn = c
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
/////////////NORMALLY NO NEED TO TOUCH
|
||||
|
||||
pub fn heroscript_dumps(obj OpenAI) !string {
|
||||
return encoderhero.encode[OpenAI](obj)!
|
||||
}
|
||||
|
||||
pub fn heroscript_loads(heroscript string) !OpenAI {
|
||||
mut obj := encoderhero.decode[OpenAI](heroscript)!
|
||||
return obj
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
module openai
|
||||
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
import os
|
||||
|
||||
pub const version = '1.14.3'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// TODO: THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE TO STRUCT BELOW, IS STRUCTURED AS HEROSCRIPT
|
||||
pub fn heroscript_default() !string {
|
||||
heroscript := "
|
||||
!!openai.configure
|
||||
name:'openai'
|
||||
api_key: ${os.getenv('OPENAI_API_KEY')}
|
||||
"
|
||||
|
||||
return heroscript
|
||||
}
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
|
||||
pub struct OpenAI {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
api_key string @[secret]
|
||||
server_url string
|
||||
conn ?&httpconnection.HTTPConnection
|
||||
}
|
||||
|
||||
// fn cfg_play(p paramsparser.Params) ! {
|
||||
// // THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
|
||||
// mut mycfg := OpenAI{
|
||||
// name: p.get_default('name', 'default')!
|
||||
// api_key: p.get('api_key')!
|
||||
// }
|
||||
// set(mycfg)!
|
||||
// }
|
||||
|
||||
fn obj_init(obj_ OpenAI) !OpenAI {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
return obj
|
||||
}
|
||||
|
||||
pub fn (mut client OpenAI) connection() !&httpconnection.HTTPConnection {
|
||||
server_url := if client.server_url != '' {
|
||||
client.server_url
|
||||
} else {
|
||||
'https://api.openai.com/v1'
|
||||
}
|
||||
mut c := client.conn or {
|
||||
mut c2 := httpconnection.new(
|
||||
name: 'openaiconnection_${client.name}'
|
||||
url: server_url
|
||||
cache: false
|
||||
retry: 20
|
||||
)!
|
||||
c2
|
||||
}
|
||||
|
||||
c.default_header.set(.authorization, 'Bearer ${client.api_key}')
|
||||
|
||||
client.conn = c
|
||||
return c
|
||||
}
|
||||
@@ -6,7 +6,7 @@ To get started
|
||||
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.clients. openai
|
||||
import freeflowuniverse.herolib.clients.openai
|
||||
|
||||
mut client:= openai.get()!
|
||||
|
||||
@@ -20,8 +20,5 @@ client...
|
||||
## example heroscript
|
||||
|
||||
```hero
|
||||
!!openai.configure
|
||||
secret: '...'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
!!openai.configure key
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user