UNPKG

theprogrammablemind

Version:

492 lines (459 loc) • 15.6 kB
const { InitCalls } = require('./helpers') const DigraphInternal = require('./digraph_internal') const debug = require('./debug') const gs = (g) => async (contexts, separator, lastSeparator) => { if (!Array.isArray(contexts)) { throw new Error('Expected a list') } let s = '' if (!separator) { separator = ' ' } if (!lastSeparator) { lastSeparator = separator } let nextSeparator = '' for (let i = 0; i < contexts.length; ++i) { const context = contexts[i] const value = await g(context) if (i > 0) { if (i === contexts.length - 1) { nextSeparator = lastSeparator } else { nextSeparator = separator } } s += nextSeparator + value } return s } const isA = (hierarchy) => (child, parent, { strict = false } = {}) => { if (!child || !parent) { return false } if (strict) { if (child.marker) { child = child.marker } if (parent.marker) { parent = parent.marker } return hierarchy.isA(child, parent) } else { if (hierarchy.isA(child.marker || child, parent.marker || parent)) { return true } for (const childT of child.types || [child]) { for (const parentT of parent.types || [parent]) { if (hierarchy.isA(childT, parentT)) { return true } } } return false } } class ErrorReason extends Error { constructor (context) { super(JSON.stringify(context)) this.reason = context } } const cleanAssign = (dest, ...srcs) => { for (const key in dest) { let found = false for (const src of srcs) { if (src[key]) { found = true break } } if (!found) { delete dest[key] } } Object.assign(dest, ...srcs) } const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => { if (!args.objects) { args.objects = config.get('objects') args.getObjects = getObjects(args.objects) } if (args.uuid) { args.objects = args.getObjects(args.uuid) } if (!hierarchy) { hierarchy = config.hierarchy } // callId args.calls = new InitCalls(args.isInstance ? `${args.isInstance}#${config.name}` : config.name) if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) { args.calls = new InitCalls(Object.keys(global.theprogrammablemind.loadForTesting)[0]) } args.cleanAssign = cleanAssign args.km = (name) => config.getConfig(name) args.api = (name) => config.getConfig(name).api args.error = (context) => { throw new ErrorReason(context) } args.kms = config.getConfigs() args.config = config args.hierarchy = hierarchy args.isA = isA(hierarchy) // args.listable = listable(hierarchy) // args.asList = asList args.retry = () => { throw new RetryError() } args.fragments = (query) => { return config.fragment(args, query) } args.breakOnSemantics = false args.theDebugger = { breakOnSemantics: (value) => args.breakOnSemantics = value } if (!logs) { } args.log = (message) => logs.push(message) args.addAssumedScoped = (args, assumed) => { const addAssumed = (args, ...moreAssumed) => { return { ...args, assumed: Object.assign({}, assumed, (args.assumed || {}), ...moreAssumed) } } args.s = (c) => config.getSemantics(logs).apply(args, c) args.g = (c, a = {}) => { return config.getGenerators(logs).apply(addAssumed(args, a), c, a) } args.gp = (c, a = {}) => { return config.getGenerators(logs).apply(addAssumed(args, a, { paraphrase: true, isResponse: false, response: false }), c, { paraphrase: true, isResponse: false, response: false }) } args.gr = (c, a = {}) => { return config.getGenerators(logs).apply(addAssumed(args, a, { paraphrase: false, isResponse: true }), { ...c, paraphrase: false, isResponse: true }) } args.e = (c) => { if (!c) { return } return config.getEvaluator(args.s, args.calls, logs, c) } args.gs = gs(args.g) args.gsp = gs(args.gp) args.gsr = gs(args.gr) } // for semantics args.addAssumedScoped(args, {}) const getAPI = (uuid) => { if (config && config.getAPI) { return config.getAPI(uuid) } } const getAPIs = (uuid) => { if (config && config.getAPIs) { return config.getAPIs(uuid) } } args.getUUIDScoped = (uuid) => { return { api: getAPI(uuid), apis: getAPIs(uuid) } } config.getAddedArgs(args) Object.assign(args, args.getUUIDScoped(uuidForScoping || config.uuid)) args.apis = args.apis || ((name) => config.getConfig(name).api) /* if (uuidForScoping) { Object.assign(args, args.getUUIDScoped(uuidForScoping)) } */ // sets args for all the API. that make a copy so the args must be fully setup by here except for scoped config.setArgs(args) } const getObjects = (objects) => { return (uuid) => { if (objects && objects.namespaced) { return objects.namespaced[uuid] } return objects } } const processContext = async (context, { objects = {}, config, logs = [] }) => { const generators = config.getGenerators(logs) const semantics = config.getSemantics(logs) // map to hash config = config || {} if (config.config) { config = config } const response = {} // NA but passed in // generators = new Generators(generators.map((g) => new Generator(normalizeGenerator(g)))) // semantics = new Semantics(semantics.map((g) => new Semantic(normalizeSemantic(g)))) const hierarchy = new DigraphInternal((config.config || {}).hierarchy || []) const args = { objects, response, getObjects: getObjects(objects) } setupArgs(args, config, logs, hierarchy) context = await semantics.apply(args, context) const generated = await generators.apply(args, context) const assumed = { paraphrase: true, response: false, isResponse: false } const paraphrases = await generators.apply({ ...args, assumed }, context, { paraphrase: true, response: false, isResponse: false }) let responses = [] if (context.isResponse) { responses = generated } return { context, generated, paraphrases, responses } } const setupProcessB = ({ config, initializer, allowDelta = false, rebuildingTemplate = false } = {}) => { const key = config._key const data = Object.assign({ key, version: '3' }, { uuid: config._uuid }) if (rebuildingTemplate) { data.return_rtf_associations = true } if (allowDelta && config.allowDelta && config.hasDelta()) { // console.log('config', config) data.delta = config.delta() } else { config.toData(data) // Object.assign(data, config.config) } // config.toServer(data) if (data.namespaces) { for (const uuid of Object.keys(data.namespaces)) { const km = config.configs.find((km) => km.uuid === uuid) data.namespaces[uuid].name = km.name } } // const generators = new Generators((data.generators || []).map((g) => new Generator(normalizeGenerator(g)))) delete data.generators // const semantics = new Semantics((data.semantics || []).map((g) => new Semantic(normalizeSemantic(g)))) delete data.semantics // const hierarchy = new DigraphInternal((config.config || {}).hierarchy || []) const hierarchy = config.hierarchy return { data, // generators, // semantics, hierarchy } } const setupContexts = (rawContexts) => { let first = true const contexts = [] contexts.push({ marker: 'controlStart', controlRemove: true }) let previous for (const context of rawContexts) { if (first) { first = false } else { contexts.push({ marker: 'controlBetween', controlRemove: true, previous }) } contexts.push(context) previous = context } contexts.push({ marker: 'controlEnd', controlRemove: true, previous }) let _index = 0 const id = (context) => { context.context_index = _index ++_index } contexts.forEach(id) return contexts } const processContextsB = async ({ config, hierarchy, semantics, generators, json, isTest, rebuildingTemplate, isInstance, instance, query, data, retries, url, commandLineArgs, forTemplate }) => { // TODO fix this name to contextsPrime const contextsPrime = [] const generatedPrime = [] const paraphrasesPrime = [] const paraphrasesParenthesizedPrime = [] const generatedParenthesizedPrime = [] const responsesPrime = [] const contexts = setupContexts(json.contexts) const objects = config.get('objects') const args = { objects, isResponse: true, response: json, isTest, isInstance, getObjects: getObjects(objects), instance, contexts } if (!json.logs) { json.logs = [] } setupArgs(args, config, json.logs, hierarchy) const toDo = [...contexts] args.insert = (context) => toDo.unshift(context) let overlap, lastRange config.debugLoops = commandLineArgs && commandLineArgs.debugLoops let context_id_counter = 0 while (toDo.length > 0) { const context = toDo.shift() args.calls.next() let contextPrime = context context.topLevel = true context_id_counter += 1 context.context_id = context_id_counter try { if (json.has_errors) { throw new Error('There are errors in the logs. Run with the -d flag and grep for Error') } const generateParenthesized = isTest || (commandLineArgs && commandLineArgs.save) if (!config.get('skipSemantics')) { const semantics = config.getSemantics(json.logs) try { contextPrime = await semantics.apply(args, context) } catch (e) { if (e.message == 'Maximum call stack size exceeded') { const mostCalled = semantics.getMostCalled() e.message += `\nThe most called semantic was:\nnotes: ${mostCalled.notes}\nmatch: ${mostCalled.matcher.toString()}\napply: ${mostCalled._apply.toString()}\n` } if (isInstance) { console.log('error', e.error) } let reason = e.reason if (!reason) { if (e.error) { reason = e.error[0] } } contextPrime = await semantics.apply(args, { marker: 'error', context, text: e ? e.toString() : 'not available', // reason: e.reason, reason, error: e.stack || e.error }) if (rebuildingTemplate) { throw e } } } if (contextPrime.controlRemove) { continue } const paraphrases = [] const paraphrasesParenthesized = [] const generatedParenthesized = [] if (forTemplate) { // noop } else { let assumed = { isResponse: true } const generated = contextPrime.isResponse ? await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed) : '' let generatedParenthesized = [] if (generateParenthesized) { config.parenthesized = true generatedParenthesized = contextPrime.isResponse ? await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed) : '' config.parenthesized = false } // assumed = { paraphrase: true, response: false }; assumed = { paraphrase: true, isResponse: false, response: false } if (generateParenthesized) { config.parenthesized = false } const paraphrases = await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed) let paraphrasesParenthesized = [] if (generateParenthesized) { config.parenthesized = true paraphrasesParenthesized = await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed) config.parenthesized = false } contextsPrime.push(contextPrime) generatedPrime.push(generated) paraphrasesPrime.push(paraphrases) if (generateParenthesized) { paraphrasesParenthesizedPrime.push(paraphrasesParenthesized) generatedParenthesizedPrime.push(generatedParenthesized) } if (contextPrime.isResponse) { responsesPrime.push(generated) } else { responsesPrime.push('') } } // add results to processed list config.config.objects.processed = config.config.objects.processed || [] config.config.objects.processed = config.config.objects.processed.slice(0, 5) config.config.objects.processed.unshift({ context: contextPrime, paraphrases: paraphrases, paraphrasesParenthesized, generatedParenthesized, responses: responsesPrime }) } catch (e) { if (Array.isArray(e)) { e = { errors: e } } e.context = contextPrime if (e.logs) { e.logs = e.logs.concat(json.logs) } else { e.logs = json.logs } e.metadata = json.metadata if (json.trace) { e.trace = json.trace } throw e } } return { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime } } // instance template loadTemplate const loadInstance = async (config, instance) => { const transitoryMode = global.transitoryMode global.transitoryMode = false /* if (config.name == 'people' && instance.name == 'people') { debugger } */ const rl = instance.resultss.length if (rl > 0) { config.addAssociations(instance.resultss[instance.resultss.length-1].rtf_associations || []) } /* TODO needs updating if still wanted if (instance && (instance.associations || instance.learned_contextual_priorities)) { if (!config.config.retrain) { if (instance.associations) { config.addAssociations(instance.associations) } if (instance.learned_contextual_priorities && instance.learned_contextual_priorities.length > 0) { config.addPriorities(instance.learned_contextual_priorities) } } } */ // const { /* data, generators, semantics, */ hierarchy } = setupProcessB({ config }) const hierarchy = config.hierarchy for (const i in (instance.resultss || [])) { const results = instance.resultss[i] if (results.extraConfig) { // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false) const uuid = config.nameToUUID(instance.name) // used to do a CLONE config.addInternal(instance.template.configs[i], { uuid, addFirst: true, handleCalculatedProps: true }) } else if (results.apply) { const objects = getObjects(config.get('objects'))(config.uuid) const args = { objects, getObjects: getObjects(objects) } if (instance.configs) { args.isInstance = `instance${i}` args.instance = instance.configs[i] } const uuid = config.nameToUUID(instance.name) setupArgs(args, config, config.logs, hierarchy, uuid) await results.apply(args) } else if (results.isFragment) { } else { if (results.skipSemantics) { config.config.skipSemantics = results.skipSemantics } const args = { config, hierarchy, json: results, commandLineArgs: {}, forTemplate: true } args.isInstance = `instance${i}` args.instance = '' await processContextsB(args) if (results.skipSemantics) { config.config.skipSemantics = null } } } global.transitoryMode = transitoryMode } module.exports = { setupProcessB, ErrorReason, // listable, setupArgs, processContext, getObjects, gs, processContextsB, loadInstance, isA }