Add support for multiple AI drivers via puter.js

This commit is contained in:
Nariman Jelveh
2024-08-21 20:19:26 -07:00
parent bdfdf2331b
commit 43c18377eb
5 changed files with 59 additions and 25 deletions
+7 -4
View File
@@ -181,9 +181,10 @@ class Valid {
* Makes the hybrid promise/callback function for a particular driver method
* @param {string[]} arg_defs - argument names (for now; definitions eventually)
* @param {string} driverInterface - name of the interface
* @param {string} driverName - name of the driver
* @param {string} driverMethod - name of the method
*/
function make_driver_method(arg_defs, driverInterface, driverMethod, settings = {}) {
function make_driver_method(arg_defs, driverInterface, driverName, driverMethod, settings = {}) {
return async function (...args) {
let driverArgs = {};
let options = {};
@@ -214,11 +215,11 @@ function make_driver_method(arg_defs, driverInterface, driverMethod, settings =
driverArgs = settings.preprocess(driverArgs);
}
return await driverCall(options, driverInterface, driverMethod, driverArgs, settings);
return await driverCall(options, driverInterface, driverName, driverMethod, driverArgs, settings);
};
}
async function driverCall (options, driverInterface, driverMethod, driverArgs, settings) {
async function driverCall (options, driverInterface, driverName, driverMethod, driverArgs, settings) {
const tp = new TeePromise();
driverCall_(
@@ -226,6 +227,7 @@ async function driverCall (options, driverInterface, driverMethod, driverArgs, s
tp.resolve.bind(tp),
tp.reject.bind(tp),
driverInterface,
driverName,
driverMethod,
driverArgs,
undefined,
@@ -240,7 +242,7 @@ async function driverCall (options, driverInterface, driverMethod, driverArgs, s
async function driverCall_(
options = {},
resolve_func, reject_func,
driverInterface, driverMethod, driverArgs,
driverInterface, driverName, driverMethod, driverArgs,
method,
contentType = 'application/json;charset=UTF-8',
settings = {},
@@ -342,6 +344,7 @@ async function driverCall_(
// send request
xhr.send(JSON.stringify({
interface: driverInterface,
driver: driverName,
test_mode: settings?.test_mode,
method: driverMethod,
args: driverArgs,
+35 -4
View File
@@ -69,7 +69,7 @@ class AI{
testMode = true;
}
return await utils.make_driver_method(['source'], 'puter-ocr', 'recognize', {
return await utils.make_driver_method(['source'], 'puter-ocr', 'aws-textract', 'recognize', {
test_mode: testMode ?? false,
transform: async (result) => {
let str = '';
@@ -113,7 +113,7 @@ class AI{
testMode = true;
}
return await utils.make_driver_method(['source'], 'puter-tts', 'synthesize', {
return await utils.make_driver_method(['source'], 'puter-tts', 'aws-polly', 'synthesize', {
responseType: 'blob',
test_mode: testMode ?? false,
transform: async (result) => {
@@ -132,8 +132,12 @@ class AI{
// if object, it's treated as the full argument object that the API expects
chat = async (...args) => {
let options = {};
let settings = {};
let testMode = false;
// default driver is openai-completion
let driver = 'openai-completion';
// Check that the argument is not undefined or null
if(!args){
throw({message: 'Arguments are required', code: 'arguments_required'});
@@ -199,8 +203,35 @@ class AI{
testMode = true;
}
// if any of the args is an object, assume it's the settings object
for (let i = 0; i < args.length; i++) {
if (typeof args[i] === 'object') {
settings = args[i];
break;
}
}
// does settings contain `model`? add it to options
if (settings.model) {
options.model = settings.model;
}
// convert to the correct model name if necessary
if( options.model === 'claude-3-5-sonnet' || options.model === 'claude'){
options.model = 'claude-3-5-sonnet-20240620';
}
// map model to the appropriate driver
if (!options.model || options.model === 'gpt-4o' || options.model === 'gpt-4o-mini') {
driver = 'openai-completion';
}else if(options.model === 'claude-3-haiku-20240307' || options.model === 'claude-3-5-sonnet-20240620'){
driver = 'claude';
}else if(options.model === 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo' || options.model === 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo' || options.model === 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo' || options.model === `google/gemma-2-27b-it`){
driver = 'together-ai';
}
// Call the original chat.complete method
return await utils.make_driver_method(['messages'], 'puter-chat-completion', 'complete', {
return await utils.make_driver_method(['messages'], 'puter-chat-completion', driver, 'complete', {
test_mode: testMode ?? false,
transform: async (result) => {
result.toString = () => {
@@ -235,7 +266,7 @@ class AI{
}
// Call the original chat.complete method
return await utils.make_driver_method(['prompt'], 'puter-image-generation', 'generate', {
return await utils.make_driver_method(['prompt'], 'puter-image-generation', undefined, 'generate', {
responseType: 'blob',
test_mode: testMode ?? false,
transform: async blob => {
+5 -5
View File
@@ -42,7 +42,7 @@ class Apps{
options = { "predicate": ['user-can-edit'] };
return utils.make_driver_method(['uid'], 'puter-apps', 'select').call(this, options);
return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'select').call(this, options);
}
create = async (...args) => {
@@ -70,7 +70,7 @@ class Apps{
};
}
// Call the original chat.complete method
return await utils.make_driver_method(['object'], 'puter-apps', 'create').call(this, options);
return await utils.make_driver_method(['object'], 'puter-apps', undefined, 'create').call(this, options);
}
update = async(...args) => {
@@ -96,7 +96,7 @@ class Apps{
}
// Call the original chat.complete method
return await utils.make_driver_method(['object'], 'puter-apps', 'update').call(this, options);
return await utils.make_driver_method(['object'], 'puter-apps', undefined, 'update').call(this, options);
}
get = async(...args) => {
@@ -106,7 +106,7 @@ class Apps{
if (Array.isArray(args) && typeof args[0] === 'string') {
options = { id: {name: args[0]}};
}
return utils.make_driver_method(['uid'], 'puter-apps', 'read').call(this, options);
return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'read').call(this, options);
}
delete = async(...args) => {
@@ -116,7 +116,7 @@ class Apps{
if (Array.isArray(args) && typeof args[0] === 'string') {
options = { id: {name: args[0]}};
}
return utils.make_driver_method(['uid'], 'puter-apps', 'delete').call(this, options);
return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'delete').call(this, options);
}
getDeveloperProfile = function(...args){
+5 -5
View File
@@ -39,7 +39,7 @@ class Hosting{
}
// todo document the `Subdomain` object.
list = utils.make_driver_method([], 'puter-subdomains', 'select');
list = utils.make_driver_method([], 'puter-subdomains', undefined, 'select');
create = async (...args) => {
let options = {};
@@ -74,7 +74,7 @@ class Hosting{
options = { object: args[0] };
}
// Call the original chat.complete method
return await utils.make_driver_method(['object'], 'puter-subdomains', 'create').call(this, options);
return await utils.make_driver_method(['object'], 'puter-subdomains', undefined, 'create').call(this, options);
}
update = async(...args) => {
@@ -97,7 +97,7 @@ class Hosting{
}
// Call the original chat.complete method
return await utils.make_driver_method(['object'], 'puter-subdomains', 'update').call(this, options);
return await utils.make_driver_method(['object'], 'puter-subdomains', undefined, 'update').call(this, options);
}
get = async(...args) => {
@@ -113,7 +113,7 @@ class Hosting{
options = { id: {subdomain: args[0]}};
}
return utils.make_driver_method(['uid'], 'puter-subdomains', 'read').call(this, options);
return utils.make_driver_method(['uid'], 'puter-subdomains', undefined, 'read').call(this, options);
}
delete = async(...args) => {
@@ -129,7 +129,7 @@ class Hosting{
options = { id: {subdomain: args[0]}};
}
return utils.make_driver_method(['uid'], 'puter-subdomains', 'delete').call(this, options);
return utils.make_driver_method(['uid'], 'puter-subdomains', undefined, 'delete').call(this, options);
}
}
+7 -7
View File
@@ -47,7 +47,7 @@ class KV{
* `key` size cannot be larger than 1mb.
* `value` size cannot be larger than 10mb.
*/
set = utils.make_driver_method(['key', 'value'], 'puter-kvstore', 'set',{
set = utils.make_driver_method(['key', 'value'], 'puter-kvstore', undefined, 'set',{
preprocess: (args)=>{
// key cannot be undefined or null
if(args.key === undefined || args.key === null){
@@ -68,7 +68,7 @@ class KV{
/**
* Resolves to the value if the key exists, or `undefined` if the key does not exist. Rejects with an error on failure.
*/
get = utils.make_driver_method(['key'], 'puter-kvstore', 'get', {
get = utils.make_driver_method(['key'], 'puter-kvstore', undefined, 'get', {
preprocess: (args)=>{
// key size cannot be larger than MAX_KEY_SIZE
if(args.key.length > this.MAX_KEY_SIZE){
@@ -98,7 +98,7 @@ class KV{
throw ({message: 'Key size cannot be larger than ' + this.MAX_KEY_SIZE, code: 'key_too_large'});
}
return utils.make_driver_method(['key'], 'puter-kvstore', 'incr').call(this, options);
return utils.make_driver_method(['key'], 'puter-kvstore', undefined, 'incr').call(this, options);
}
decr = async(...args) => {
@@ -117,12 +117,12 @@ class KV{
throw ({message: 'Key size cannot be larger than ' + this.MAX_KEY_SIZE, code: 'key_too_large'});
}
return utils.make_driver_method(['key'], 'puter-kvstore', 'decr').call(this, options);
return utils.make_driver_method(['key'], 'puter-kvstore', undefined, 'decr').call(this, options);
}
// resolves to 'true' on success, or rejects with an error on failure
// will still resolve to 'true' if the key does not exist
del = utils.make_driver_method(['key'], 'puter-kvstore', 'del', {
del = utils.make_driver_method(['key'], 'puter-kvstore', undefined, 'del', {
preprocess: (args)=>{
// key size cannot be larger than this.MAX_KEY_SIZE
if(args.key.length > this.MAX_KEY_SIZE){
@@ -154,7 +154,7 @@ class KV{
pattern = args[0];
}
return utils.make_driver_method([], 'puter-kvstore', 'list', {
return utils.make_driver_method([], 'puter-kvstore', undefined, 'list', {
transform: (res)=>{
// glob pattern was provided
if(pattern){
@@ -179,7 +179,7 @@ class KV{
// resolve to 'true' on success, or rejects with an error on failure
// will still resolve to 'true' if there are no keys
flush = utils.make_driver_method([], 'puter-kvstore', 'flush')
flush = utils.make_driver_method([], 'puter-kvstore', undefined, 'flush')
// clear is an alias for flush
clear = this.flush;