Browse Source

Add support for multiple AI drivers via puter.js

Nariman Jelveh 9 tháng trước cách đây
mục cha
commit
43c18377eb

+ 7 - 4
src/puter-js/src/lib/utils.js

@@ -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
src/puter-js/src/modules/AI.js

@@ -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
src/puter-js/src/modules/Apps.js

@@ -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
src/puter-js/src/modules/Hosting.js

@@ -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
src/puter-js/src/modules/KV.js

@@ -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;