tpmkms
Version:
Reusable libraries for Entodicton, a natural language to json converter
278 lines (256 loc) • 7.22 kB
JavaScript
const { knowledgeModule, where } = require('./runtime').theprogrammablemind
const { defaultContextCheck } = require('./helpers')
const helpers = require('./helpers')
const articles = require('./articles')
const evaluate = require('./evaluate')
const stm_tests = require('./stm.test.json')
class API {
initialize({ objects }) {
this._objects = objects
this.isAs = [
(child, parent) => child == parent
]
this._objects.mentioned = []
this._objects.variables = {}
this.idCounter = 0
this.maximumMentioned = 50
}
getId() {
return ++this.idCounter
}
addIsA(isA) {
if (!this.isAs.find( (f) => f == isA )) {
this.isAs.push(isA)
}
}
isA(child, parent) {
for (const isA of this.isAs) {
if (isA(child, parent)) {
return true
}
}
return false
}
getByType(type) {
return this._objects.mentioned.filter( (context) => this.isA(context.marker, type) )
}
mentioned({ context:concept, value=null, frameOfReference } = {}) {
if (!frameOfReference) {
frameOfReference = this._objects
}
// TODO value should perhaps have been called id as in concept id and then value could be value
if (value) {
concept = { ...concept, pullFromContext: false }
} else {
concept.pullFromContext = false
}
if (value) {
if (concept.marker == 'unknown') {
if (concept.value) {
concept.marker = concept.value
}
}
concept.value = value
}
concept.fromSTM = true
if (!concept.stm) {
concept.stm = {}
}
if (!concept.stm.id) {
concept.stm.id = this.getId()
}
frameOfReference.mentioned = (frameOfReference.mentioned || []).filter( (context) => context.stm && context.stm.id != concept.stm.id )
helpers.unshiftL(frameOfReference.mentioned, concept, this.maximumMentioned)
}
mentions({ context, frameOfReference, useHierarchy=true, all, condition = (() => true) } = {}) {
const mentioned = frameOfReference?.mentioned || this._objects.mentioned
const findPrevious = !!context.stm_previous
const forAll = []
const addForAll = (context) => {
if (!forAll.find( (c) => c.stm.id == context.stm.id)) {
forAll.push(context)
}
}
// care about value first
let findCounter = 0
for (const m of mentioned) {
if (context.value && (context.value == m.marker || context.value == m.value)) {
findCounter += 1
if (findPrevious && findCounter < 2) {
continue
}
if (condition()) {
if (all) {
allForAll(m)
} else {
return m
}
}
}
}
if (!useHierarchy) {
return
}
// care about marker second
findCounter = 0
for (const m of mentioned) {
if (context.marker != 'unknown' && this.isA(m.marker, context.marker)) {
findCounter += 1
if (findPrevious && findCounter < 2) {
continue
}
if (condition(m)) {
if (all) {
addForAll(m)
} else {
return m
}
}
}
// if (context.types && context.types.includes(m.marker)) {
if (context.types) {
for (const parent of context.types) {
if (parent != 'unknown' && this.isA(m.marker, parent)) {
findCounter += 1
if (findPrevious && findCounter < 2) {
continue
}
if (condition(m)) {
if (all) {
addForAll(m)
} else {
return m
}
}
}
}
}
}
findCounter = 0
if (context.types && context.types.length == 1) {
for (const m of mentioned) {
if (context.unknown) {
findCounter += 1
if (findPrevious && findCounter < 2) {
continue
}
if (condition(m)) {
if (all) {
addForAll(m)
} else {
return m
}
}
}
}
}
if (all) {
return forAll
}
}
getVariable(name) {
if (!name) {
return
}
let valueNew = this.mentions({ context: { marker: name, value: name }, useHierarchy: false }) || name
if (valueNew && valueNew.value) {
valueNew = valueNew.value
}
return valueNew
}
setVariable(name, value) {
this.mentioned({ context: { marker: name }, value })
}
}
const api = new API()
const config = {
name: 'stm',
operators: [
"([stm_previous|previous] ([memorable]))",
"(([memorable]) [stm_before|before])",
"([remember] (memorable/*))",
],
words: {
literals: {
"m1": [{"id": "memorable", development: true, "initial": "{ value: 'm1' }" }],
"m2": [{"id": "memorable", development: true, "initial": "{ value: 'm2' }" }],
},
},
bridges: [
{
id: 'memorable',
isA: ['theAble'],
words: helpers.words('memorable')
},
{
id: 'remember',
bridge: "{ ...next(operator), postModifiers: ['rememberee'], rememberee: after[0] }",
isA: ['verb'],
semantic: async ({context, api, e}) => {
let value = (await e(context.rememberee)).evalue
if (value == context.rememberee.value) {
value = context.rememberee
}
api.mentioned({ context: value })
},
},
{
id: 'stm_previous',
bridge: '{ ...after[0], modifiers: ["stm_previous"], stm_previous: operator, pullFromContext: true }',
},
{
id: 'stm_before',
isA: ['adjective'],
bridge: '{ ...before[0], postModifiers: ["stm_previous"], stm_previous: operator, pullFromContext: true }',
},
],
semantics: [
{
where: where(),
notes: 'pull from context',
// match: ({context}) => context.marker == 'it' && context.pullFromContext, // && context.value,
match: ({context, callId}) => context.pullFromContext && !context.same, // && context.value,
apply: async ({callId, context, kms, e, log, retry}) => {
context.value = kms.stm.api.mentions({ context })
if (!context.value) {
// retry()
context.value = { marker: 'answerNotKnown' }
return
}
const instance = await e(context.value)
if (instance.evalue && !instance.edefault) {
context.value = instance.evalue
}
if (context.evaluate) {
context.evalue = context.value
}
},
},
],
}
const initializer = ({config}) => {
config.addArgs(({kms}) => ({
mentioned: (args) => {
kms.stm.api.mentioned(args)
},
mentions: (args) => {
return kms.stm.api.mentions(args)
},
}))
}
knowledgeModule( {
config,
api: () => new API(),
includes: [evaluate, articles],
initializer,
module,
description: 'short term memory',
test: {
name: './stm.test.json',
contents: stm_tests,
checks: {
context: [...defaultContextCheck(), 'pullFromContext', 'stm_id'],
objects: [{ property: 'mentioned', filter: helpers.defaultContextCheckProperties }],
},
},
})