UNPKG

json-object-editor

Version:

JOE the Json Object Editor | Platform Edition

221 lines (209 loc) 11.8 kB
var schema = { title : 'Ai Response | ${name}', info:"An ai response from openai etc", summary:{ description:'Stored AI response objects generated from ai_prompt and the chatgpt plugin.', purpose:'Use ai_response to persist responses, token usage, and referenced objects from OpenAI calls for auditing, reuse, and comparison back to JOE objects.', labelField:'name', defaultSort:{ field:'created', dir:'desc' }, searchableFields:['name','prompt_method','model_used','response_type','response_id','tags','_id'], allowedSorts:['created','joeUpdated','name','model_used'], relationships:{ outbound:[ { field:'ai_prompt', targetSchema:'ai_prompt', cardinality:'one' }, { field:'referenced_objects', targetSchema:'<schemaName>', cardinality:'many' }, { field:'tags', targetSchema:'tag', cardinality:'many' } ], inbound:{ graphRef:'server/relationships.graph.json' } }, joeManagedFields:['created','joeUpdated'], fields:[ { name:'_id', type:'string', required:true }, { name:'itemtype', type:'string', required:true, const:'ai_response' }, { name:'name', type:'string', required:true }, { name:'ai_prompt', type:'string', isReference:true, targetSchema:'ai_prompt' }, { name:'referenced_objects', type:'string', isArray:true }, { name:'generated_thoughts', type:'string', isArray:true, isReference:true, targetSchema:'thought' }, { name:'user_prompt', type:'string' }, { name:'prompt_method', type:'string' }, { name:'model_used', type:'string' }, { name:'response_type', type:'string' }, { name:'response', type:'string' }, { name:'response_keys', type:'string', isArray:true }, { name:'response_id', type:'string' }, { name:'usage', type:'object' }, { name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' }, { name:'joeUpdated', type:'string', format:'date-time' }, { name:'created', type:'string', format:'date-time' } ] }, menuicon:` <svg xmlns="http://www.w3.org/2000/svg" viewBox="-150 -150 1324 1324"> <path d="M314.57 597.81h376.06v28.2H314.57zm0 75.21h376.06v28.2H314.57zm0 75.21h376.06v28.2H314.57zm239.99-498.47 151.31 31.3c12.23 2.53 12.23 20 0 22.53l-151.31 31.3-31.3 151.31c-2.53 12.23-20 12.23-22.53 0l-31.3-151.31-151.31-31.3c-12.23-2.53-12.23-20 0-22.53l151.31-31.3 31.3-151.31c2.53-12.23 20-12.23 22.53 0l31.3 151.31ZM388.55 102.88l65.55 13.56c5.3 1.1 5.3 8.66 0 9.76l-65.55 13.56-13.56 65.55c-1.1 5.3-8.66 5.3-9.76 0l-13.56-65.55-65.55-13.56c-5.3-1.1-5.3-8.66 0-9.76l65.55-13.56 13.56-65.55c1.1-5.3 8.66-5.3 9.76 0l13.56 65.55Zm20.9 365.17 63.07 13.04c5.1 1.05 5.1 8.33 0 9.39l-63.07 13.04-13.04 63.07c-1.05 5.1-8.33 5.1-9.39 0l-13.04-63.07-63.07-13.04c-5.1-1.05-5.1-8.33 0-9.39l63.07-13.04 13.04-63.07c1.05-5.1 8.33-5.1 9.39 0l13.04 63.07Z"/> <path d="M689 155.94v37.61h67.44v676.9H267.56v-676.9H319v-37.61h-89.04v752.12h564.08V155.94H689z"/> </svg>`, listView:{ title: function(air){ var html = `<joe-subtext class="fright">${_joe.Utils.prettyPrintDTS(air.created)}</joe-subtext> <joe-title>${air.name}</joe-title> <joe-subtitle>${(air.response_keys?.length && `returns <b>${air.response_keys}</b>`) ||''}</joe-subtitle> ${air.prompt_method?`<joe-subtext class="fright">method ${air.prompt_method}</joe-subtext>`:''} <div>${(air.referenced_objects||[]).map(function(ref){ var obj = $J.get(ref); if(obj){ return `<joe-subtext>${obj.itemtype}:<b>${obj.name}</b> - ${obj._id}</joe-subtext>`; }else{ return `<joe-subtext>${ref}</joe-subtext>`; } }).join('')}</div>`; air.tags?.length && (html+=_joe.schemas.tag.methods.renderTags(air.tags,'fright')); return html; }, listWindowTitle: 'Ai Responses' }, subsets: function(){ return _joe.Filter.Options.tags({group:true,collapsed:false}).concat(_joe.getDataset('ai_prompt').map(prompt => { var color = prompt.status && $J.get(prompt.status,'status').color; return { name: prompt.name, id: prompt._id, filter: { ai_prompt: prompt._id }, stripecolor: color || null // optional }; })) }, sorter:['!created','name'], checkChanges:false, fields:[ 'name', //'info', {name:'ai_prompt',type:'objectReference', values:'ai_prompt',display:'Ai Prompt',width:'50%',locked:true}, {name:'referenced_objects',type:'objectReference',width:'50%',values:function(air,orList){ return $J.search({_id:{$in:air.referenced_objects}}); },display:'Referenced Objects',locked:true}, {name:'generated_thoughts',type:'objectReference',width:'50%',values:function(air,orList){ return $J.search({_id:{$in:air.generated_thoughts||[]},itemtype:'thought'}); },display:'Generated Thoughts',locked:true}, {name:'user_prompt', display:'Sent User Prompt',comment:"The input sent by the user after all processing",locked:true,type:'rendering'}, {name:'prompt_method',locked:true,width:'50%'}, {name:'model_used',locked:true,width:'50%'}, // {name:'ai_prompt',type:'select', values:'ai_prompt',display:'Ai Prompt',width:'50%',template:function(resp,prompt){ // return prompt.name; // }}, //{name:'business',type:'objectReference', values:'business',display:'Business',locked:true}, //{name:'params', type:'rendering', locked:true}, {section_start:'response',collapsed:false}, {name:'response_type',type:'text',display:'Response Type', placeholder:'(a code for the responsetype)',locked:true,width:'50%',condition:function(v){ return v.length > 0; }}, {name:'response', type:'rendering', locked:true,height:'500px'}, {name:'response_keys', type:'text', locked:true,display:'Response Keys'}, {name:'response_id', type:'text', display:'openAI response ID',locked:true}, {section_end:'response'}, {sidebar_start:'right', collapsed:false}, {section_start:'workflow'}, 'tags', {section_end:'workflow'}, {section_start:'tokens'}, {name:'usage',type:'content',display:'Tokens Used',run:function(air){ if(!air.usage || !air.usage.total_tokens){return '';} var html=`<joe-text>input <b>${air.usage.input_tokens}</b></joe-text> <joe-text>output <b>${air.usage.output_tokens}</b></joe-text> <joe-text>total <b>${air.usage.total_tokens}</b></joe-text>` return html; }}, {section_end:'tokens'}, {sidebar_end:'right'}, //{name:'payload', type:'code', locked:true,height:'500px'}, //{name:'raw_response', type:'code', language:'json',locked:true}, {section_start:'system',collapsed:true}, '_id','created','itemtype', {section_end:'system'}, ], methods:{ compareResponseToObject:function(response_id,object_id,do_alert){ let response =$J.get(response_id); var object; let object_keys; if(_joe.current.object._id == object_id){ object = _jco(true); object_keys = _joe.current.fields.map(f=>f.name) } else{ object = $J.get(object_id); object_keys = Object.keys(object); } if(!response || !object){return false;} //evaluate the response to see if it is valid json try{ let parsed = JSON.parse(response.response); //find the keys in the response that are in the object let keys = Object.keys(parsed); let match = keys.filter(k=>object_keys.includes(k)); //if there are no keys that match, return false if(!match.length){ do_alert && alert('Response does not match any object keys: '+keys.join(',')); return false;} //return an array of matching keys do_alert && ( doit = confirm('Replace object values with responses for: '+match.join(','))); if(doit){ _joe.schemas.ai_response.methods.updateObjectFromResponse(response_id,object_id,match); } return match; }catch(e){ //if the response is not valid json, return false return false; } }, updateObjectFromResponse:function(response_id,object_id,fields){ let response =$J.get(response_id); let parsed = JSON.parse(response.response); var object; if(_joe.current.object._id == object_id){ object = _jco(true); } else{ object = $J.get(object_id); } //handle tags if(response.tags && response.tags.length){ let newTags = (object.tags||[]).concat(response.tags); //tags array to a set, then back to array newTags = [...new Set(newTags)]; _joe.Fields.set('tags',newTags); } fields.map(function(field){ let newVal = object[field]; //update the object with the response if(object[field].isArray()){ //append the response to the array newVal = object[field].concat(parsed[field]); }else if(typeof object[field] == 'string'){ //merge the response with the object newVal = parsed[field] } _joe.Fields.set(field,newVal); }); }, listResponses:function(obj){ let html =''; let responses = _joe.getDataset('ai_response').filter(r=>{ return r.referenced_objects && r.referenced_objects.includes(obj._id); }) $c.sortBy(responses,'!created'); responses.map(resp=>{ let temp = `<joe-subtitle>${resp.name}</joe-subtitle> <joe-subtext>${_joe.Utils.prettyPrintDTS(resp.created)}</joe-subtext> ${resp.tags && _joe.schemas.tag.methods.renderTags(resp.tags) || ''}`; resp.response_keys && (temp += `<joe-button-wrapper class="bottom"><joe-button class="joe-button joe-blue-button" onclick="_joe.Utils.stopPropagation(event);_joe.schemas.ai_response.methods.compareResponseToObject('${resp._id}','${obj._id}',true);">< merge ${resp.response_keys.length} fields</joe-button><joe-button-wrapper>`); html+=_joe.renderFieldListItem(resp,temp,'ai_response',{icon:'ai_assistant',link:function(item){ return location.href.replace(location.hash,`#/${item.itemtype}/${item._id}`); }}); }) return html; } }, idprop : "_id" }; module.exports = schema;