Skip to content

Commit

Permalink
20240926 @Mookse
Browse files Browse the repository at this point in the history
- Create Obscure Functionality #374
- Member version (complete [minus frontend])
- API version (wip, stable)
  • Loading branch information
Mookse committed Sep 26, 2024
1 parent b0b2fd5 commit b4a2429
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 16 deletions.
9 changes: 7 additions & 2 deletions inc/js/api-functions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,15 @@ async function memory(ctx){
/**
* Given an itemId, obscures aspects of contents of the data record.
* @param {Koa} ctx - Koa Context object
* @returns {Promise<object>} - Promise object representing obscured item
*/
async function obscure(ctx){
const { iid } = ctx.params
await mAPIKeyValidation(ctx)
ctx.body = await ctx.MyLife.obscure(iid, ctx.request?.body)
const { itemId: iid, } = ctx.request?.body
if(!ctx.Globals.isValidGuid(iid))
ctx.throw(400, 'Improper `itemId` provided in request')
const { mbr_id } = ctx.state
ctx.body = await ctx.MyLife.obscure(mbr_id, iid)
}
/**
* Validates api token.
Expand Down Expand Up @@ -318,6 +322,7 @@ async function mAPIKeyValidation(ctx){ // transforms ctx.state
if(ctx.params.mid === ':mid')
ctx.params.mid = undefined
const memberId = ctx.params?.mid
?? ctx.request.body?.mbr_id
?? ctx.request.body?.memberKey
?? ctx.session?.APIMemberKey
if(!memberId?.length)
Expand Down
10 changes: 10 additions & 0 deletions inc/js/core.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,16 @@ class MyLife extends Organization { // form=server
console.log('isMemberHosted:', isHosted, isValidated, memberId)
return isValidated
}
/**
* Obscures the summary for a given itemId belonging to member.
* @param {string} mbr_id - valid member id
* @param {string} itemId - valid item id belonging to member
* @returns {object} - returns the obscured item
*/
async obscure(mbr_id, itemId){
console.log('core::obscure()::from api-functions', mbr_id, itemId)
return { itemId, mbr_id, obscured: true }
}
/**
* Registers a new candidate to MyLife membership
* @public
Expand Down
11 changes: 11 additions & 0 deletions inc/js/functions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,16 @@ async function migrateChat(ctx){
const { avatar, } = ctx.state
ctx.body = await avatar.migrateChat(tid)
}
/**
* Given an itemId, obscures aspects of contents of the data record.
* @param {Koa} ctx - Koa Context object
* @returns {object} - The item obscured
*/
async function obscure(ctx){
const { iid, } = ctx.params
const { avatar, } = ctx.state
ctx.body = await avatar.obscure(iid)
}
/**
* Reset the passphrase for the member's avatar.
* @param {Koa} ctx - Koa Context object
Expand Down Expand Up @@ -416,6 +426,7 @@ export {
members,
migrateBot,
migrateChat,
obscure,
passphraseReset,
privacyPolicy,
retireBot,
Expand Down
69 changes: 57 additions & 12 deletions inc/js/mylife-agent-factory.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const mExcludeProperties = {
definitions: true,
name: true
}
const mGeneralBotId = 'asst_piDEJKYjqvAZbLstjd6u0ZMb'
const mLLMServices = new LLMServices()
const mMyLifeTeams = [
{
Expand Down Expand Up @@ -386,6 +387,14 @@ class BotFactory extends EventEmitter{
// @todo remove restriction (?) for all experiences to be stored under MyLife `mbr_id`
return await mDataservices.getItem(_experience_id, 'system')
}
/**
* Retrieves a collection item by Id.
* @param {Guid} id - The id of the collection item to retrieve.
* @returns {object} - The item.
*/
async item(id){
return await this.dataservices.getItem(id)
}
/**
* Proxy for modular mHelp() function.
* @public
Expand All @@ -398,6 +407,23 @@ class BotFactory extends EventEmitter{
async help(thread_id, bot_id, helpRequest, avatar){
return await mHelp(thread_id, bot_id, helpRequest, this, avatar)
}
/**
* Given an itemId, obscures aspects of contents of the data record. Consults modular LLM with isolated request and saves outcome to database.
* @param {Guid} itemId - Id of the item to obscure
* @returns {string} - The obscured content
*/
async obscure(itemId){
const { id, summary, relationships, } = await this.item(itemId)
?? {}
if(!id)
throw new Error('Item not found')
if(!summary?.length)
throw new Error('No summary found to obscure')
const obscuredSummary = await mObscure(this, summary)
if(obscuredSummary?.length) /* save response */
this.dataservices.patch(id, { summary: obscuredSummary }) // no need await
return obscuredSummary
}
/**
* Allows member to reset passphrase.
* @param {string} passphrase
Expand Down Expand Up @@ -614,14 +640,6 @@ class AgentFactory extends BotFactory {
async deleteItem(id){
return await this.dataservices.deleteItem(id)
}
/**
* Retrieves a collection item by Id.
* @param {Guid} id - The id of the collection item to retrieve.
* @returns {object} - The item.
*/
async item(id){
return await this.dataservices.getItem(id)
}
async entry(entry){
const defaultType = 'entry'
const {
Expand Down Expand Up @@ -835,12 +853,14 @@ class AgentFactory extends BotFactory {
}
/**
* Updates a collection item.
* @param {object} item - The item to update.
* @returns {Promise<object>} - The updated item.
* @param {object} item - The item to update
* @property {Guid} item.id - The item id
* @returns {Promise<object>} - The updated item
*/
async updateItem(item){
const { id, ..._item } = item
const response = await this.dataservices.patch(id, _item)
if(!this.globals.isValidGuid(item?.id))
throw new Error('item id required for update')
const response = await this.dataservices.patch(item.id, item)
return response
}
/* getters/setters */
Expand Down Expand Up @@ -1543,6 +1563,31 @@ async function mLoadSchemas(){
console.log(err)
}
}
/**
* Given an itemId, obscures aspects of contents of the data record.
* @param {AgentFactory} factory - The factory object
* @param {Guid} iid - The item id
* @returns {Object} - The obscured item object
*/
async function mObscure(factory, summary) {
const { mbr_id } = factory
let obscuredSummary
// @stub - if greater than limit, turn into text file and add
const prompt = `OBSCURE:\n${summary}`
const messageArray = await mLLMServices.getLLMResponse(null, mGeneralBotId, prompt)
const { content: contentArray=[], } = messageArray?.[0] ?? {}
const { value, } = contentArray
.filter(message=>message.type==='text')
?.[0]
?.text
?? {}
try {
let parsedSummary = JSON.parse(value)
if(typeof parsedSummary==='object' && parsedSummary!==null)
obscuredSummary = parsedSummary.obscuredSummary
} catch(e) {} // obscuredSummary is just a string; use as-is or null
return obscuredSummary
}
async function mPopulateBotInstructions(){
const instructionSets = await mDataservices.botInstructions()
instructionSets
Expand Down
29 changes: 29 additions & 0 deletions inc/js/mylife-avatar.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,27 @@ class Avatar extends EventEmitter {
console.log('migrateChat::BYPASS-SAVE', conversation.thread_id)
return conversation
}
/**
* Given an itemId, obscures aspects of contents of the data record. Obscure is a vanilla function for MyLife, so does not require intervening intelligence and relies on the factory's modular LLM.
* @param {Guid} iid - The item id
* @returns {Object} - The obscured item object
*/
async obscure(iid){
const updatedSummary = await this.#factory.obscure(iid)
this.frontendInstruction = {
command: 'updateItemSummary',
itemId: iid,
summary: updatedSummary,
}
return {
instruction: this.frontendInstruction,
responses: [{
agent: 'server',
message: `I have successfully obscured your content.`,
}],
success: true,
}
}
/**
* Register a candidate in database.
* @param {object} candidate - The candidate data object.
Expand Down Expand Up @@ -1280,6 +1301,14 @@ class Q extends Avatar {
activeBotId = this.activeBotId
return super.chat(message, activeBotId, threadId, itemId, shadowId, conversation, processStartTime)
}
/**
* Given an itemId, obscures aspects of contents of the data record. Obscure is a vanilla function for MyLife, so does not require intervening intelligence and relies on the factory's modular LLM.
* @param {Guid} iid - The item id
* @returns {Object} - The obscured item object
*/
async obscure(iid){
return await this.#factory.obscure(iid)
}
upload(){
throw new Error('MyLife avatar cannot upload files.')
}
Expand Down
5 changes: 3 additions & 2 deletions inc/js/routes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
members,
migrateBot,
migrateChat,
obscure,
passphraseReset,
privacyPolicy,
retireBot,
Expand Down Expand Up @@ -52,7 +53,7 @@ import {
keyValidation,
logout as apiLogout,
memory,
obscure,
obscure as apiObscure,
register,
tokenValidation,
} from './api-functions.mjs'
Expand Down Expand Up @@ -93,7 +94,7 @@ _apiRouter.post('/challenge/:mid', challenge)
_apiRouter.post('/entry/:mid', entry)
_apiRouter.post('/keyValidation/:mid', keyValidation)
_apiRouter.post('/memory/:mid', memory)
_apiRouter.post('/obscure/:iid', obscure)
_apiRouter.post('/obscure/:mid', apiObscure)
_apiRouter.post('/register', register)
_apiRouter.post('/upload', upload)
_apiRouter.post('/upload/:mid', upload)
Expand Down

0 comments on commit b4a2429

Please sign in to comment.