UNPKG

eliza-core

Version:

A rendition of ELIZA program engine by Weizenbaum sharable for all javascript environments

455 lines (454 loc) 20.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); var rxjs_1 = require("rxjs"); var operators_1 = require("rxjs/operators"); var decompo_1 = require("./decompo"); var Reassemble_1 = require("./Reassemble"); var estring = __importStar(require("./estring")); var mention = __importStar(require("./mention-router")); var key_1 = require("./key"); var key_goto_1 = require("./key-goto"); var key_stack_1 = require("./key-stack"); var PrePostUtil = __importStar(require("./pre-post-utils")); var printers = __importStar(require("./printers")); var utils_1 = require("./utils"); var exceptions_1 = require("./exceptions"); var printSynonyms = true; var printKeys = true; var PRINT_PRE_POST = true; var PRINT_INITIAL_FINAL = true; function loadEliza(script$, keyFilter) { return __awaiter(this, void 0, void 0, function () { var eliza; return __generator(this, function (_a) { switch (_a.label) { case 0: eliza = new ElizaImpl(keyFilter || (function (key) { return true; })); return [4, eliza.readScript(script$).toPromise()]; case 1: _a.sent(); return [2, eliza]; } }); }); } exports.loadEliza = loadEliza; function loadElizaInEnglish(script$) { return __awaiter(this, void 0, void 0, function () { var eliza; return __generator(this, function (_a) { switch (_a.label) { case 0: eliza = new ElizaImpl(function (key) { return true; }, function (sentence) { return sentence.split(' '); }); return [4, eliza.readScript(script$).toPromise()]; case 1: _a.sent(); return [2, eliza]; } }); }); } exports.loadElizaInEnglish = loadElizaInEnglish; var ElizaImpl = (function () { function ElizaImpl(keyFilter, tokenizer) { this.keyFilter = keyFilter; this.tokenizer = tokenizer; this.mem = []; this.keys = []; this.synonyms = []; this.preList = []; this.postList = []; this.annotates = []; this.tweakList = []; this.initialStr = 'Hello.'; this.finalStr = 'Goodbye.'; this.quitList = []; this.lastDecomp = []; this.lastReasemb = []; this.finished = false; } ElizaImpl.prototype.getInitialStr = function () { return this.initialStr; }; ElizaImpl.prototype.isFinished = function () { return this.finished; }; ElizaImpl.prototype.collect = function (s) { var _this = this; var matchedPattern = [ { tryMatch: function (testStr) { return estring.match(testStr, '*reasmb: *'); }, onMatched: function (matchedParts) { if (!_this.lastReasemb) { throw new exceptions_1.ScriptInterpretingError('A Reasmb rule missing decomp rule'); } _this.lastReasemb.push(new Reassemble_1.Reassemble(matchedParts[1], _this.lastDecomp[_this.lastDecomp.length - 1])); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*decomp: *'); }, onMatched: function (matchedParts) { if (!_this.lastDecomp) { throw new exceptions_1.ScriptInterpretingError('A Decomp rule missing Key Initialization'); } _this.lastReasemb = []; var temp = matchedParts[1]; var newMatch = estring.match(temp, '$ *'); _this.lastDecomp.push(new decompo_1.Decomp(newMatch ? newMatch[0] : temp, newMatch ? true : false, _this.lastReasemb)); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*key: * #*'); }, onMatched: function (matchedParts) { _this.lastDecomp = []; _this.lastReasemb = null; var n = 0; if (matchedParts[2].length > 0) { n = parseInt(matchedParts[2], 10); if (isNaN(n)) { throw new exceptions_1.UnexpectedNumberException(matchedParts[2], 'key'); } } _this.keys.push(new key_1.Key(matchedParts[1], n, _this.lastDecomp)); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*key: *'); }, onMatched: function (matchedParts) { _this.lastDecomp = []; _this.lastReasemb = null; _this.keys.push(new key_1.Key(matchedParts[1], 0, _this.lastDecomp)); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*mention: *@* *'); }, onMatched: function (matchedParts) { var words = JSON.parse("[" + matchedParts[3] + "]"); _this.synonyms.push({ tag: matchedParts[2], words: words.slice(1), }); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*annotate: *'); }, onMatched: function (matchedParts) { var tag = matchedParts[1].trim(); if (tag.length < 1 || _this.annotates.find(function (w) { return w === tag; })) { throw new exceptions_1.DuplicateAnnotateException(tag); } _this.annotates.push(tag); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*pre: * => *'); }, onMatched: function (matchedParts) { _this.preList.push({ src: JSON.parse(matchedParts[1]), dest: JSON.parse(matchedParts[2]) }); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*post: * => *'); }, onMatched: function (matchedParts) { _this.postList.push({ src: JSON.parse(matchedParts[1]), dest: JSON.parse(matchedParts[2]) }); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*tweak: * => *'); }, onMatched: function (matchedParts) { _this.tweakList.push({ src: JSON.parse(matchedParts[1]), dest: JSON.parse(matchedParts[2]) }); }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*initial: *'); }, onMatched: function (matchedParts) { _this.initialStr = matchedParts[1]; }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*final: *'); }, onMatched: function (matchedParts) { _this.finalStr = matchedParts[1]; }, }, { tryMatch: function (testStr) { return estring.match(testStr, '*quit: *'); }, onMatched: function (matchedParts) { _this.quitList.push(" " + matchedParts[1] + " "); }, }, { tryMatch: function (testStr) { var parts = estring.match(testStr, '*: *'); if (parts && _this.annotates.indexOf(estring.trim(parts[0])) > -1) { return parts; } return null; }, onMatched: function (matchedParts) { var instruction = estring.trim(matchedParts[0]); if (!_this.lastReasemb) { throw new exceptions_1.ScriptInterpretingError('An annotated Reasmb rule missing decomp rule'); } _this.lastReasemb.push(new Reassemble_1.Reassemble(matchedParts[1], _this.lastDecomp[_this.lastDecomp.length - 1], instruction)); }, }, ].find(function (_a) { var tryMatch = _a.tryMatch, onMatched = _a.onMatched; var matchedParts = tryMatch(s); if (matchedParts) { onMatched(matchedParts); return true; } return false; }); if (!matchedPattern) { throw new exceptions_1.UnknownRuleException(s); } }; ElizaImpl.prototype.toJson = function () { var toPrint = {}; if (printKeys) { toPrint.keys = this.keys.map(function (k) { return printers.snapshotKey(k); }); } if (printSynonyms) { toPrint.mentionRoutes = this.synonyms; } if (PRINT_PRE_POST) { toPrint.preList = this.preList; toPrint.postList = this.postList; } if (PRINT_INITIAL_FINAL) { toPrint.initial = this.initialStr; toPrint.final = this.finalStr; toPrint.quitList = this.quitList.join(' '); } return toPrint; }; ElizaImpl.prototype.processHyperInput = function (s) { var matchedParts = estring.match(s, '*.*'); while (matchedParts) { var reply = this.sentence(matchedParts[0]); if (reply) { return reply; } s = estring.trim(matchedParts[1]); matchedParts = estring.match(s, '*.*'); } if (s.length > 0) { var reply = this.sentence(s); if (reply) { return reply; } } var m = this.mem.shift(); if (m) { return { assembled: { reassembled: m } }; } var key = this.keys.find(function (k) { return k.getKey() === 'xnone'; }); if (key) { var context = this.fullyDecompose(key, s); if (context && context.assembled) { return context; } } return null; }; ElizaImpl.prototype.processInput = function (s) { if (typeof s !== 'string') { throw new exceptions_1.InvalidStringException(s); } s = estring.replaceAll(s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); s = estring.replaceAll(s, '@#$%^&*()_-+=~`{[}]|:;<>\\"', ' '); s = estring.replaceAll(s, ',?!', '...'); s = estring.compress(s); return this.processHyperInput(s); }; ElizaImpl.prototype.readScript = function (script$) { var _this = this; return rxjs_1.concat(script$, rxjs_1.of('\n')).pipe(operators_1.scan(function (_a, chunk) { var buffer = _a.buffer; var split = (buffer + chunk).split('\n'); var rest = split.pop(); return { buffer: rest || '', lines: split }; }, { buffer: '', lines: [''] }), operators_1.concatMap(function (pack) { return pack.lines; }), operators_1.filter(function (line) { return line.trim().length > 0 && !line.startsWith('%'); }), operators_1.tap(function (line) { return _this.collect(line); })); }; ElizaImpl.prototype.sentence = function (s) { var _this = this; s = PrePostUtil.translate(this.preList, s).trim(); s = estring.pad(s); if (this.quitList.indexOf(s) >= 0) { this.finished = true; return { assembled: { reassembled: this.finalStr } }; } if (this.tokenizer) { var result_1 = null; return key_stack_1.buildKeyStack(this.keys.filter(function (k) { return _this.keyFilter(k.getKey()); }), this.tokenizer(s)) .find(function (key) { var ctx = _this.fullyDecompose(key, s); if (ctx) { result_1 = ctx; return true; } return false; }) ? result_1 : null; } var sortedReplyContexts = this.keys.filter(function (k) { return _this.keyFilter(k.getKey()); }) .map(function (key) { return _this.fullyDecompose(key, s); }) .filter(utils_1.notEmpty).sort(function (ctxA, ctxB) { return (ctxA.matches || { slottedTokens: [{ token: s, scopes: {} }] }) .slottedTokens.filter(function (t) { return Object.keys(t.scopes).length < 1; }) .map(function (t) { return t.token; }).join('').length - (ctxB.matches || { slottedTokens: [{ token: s, scopes: {} }] }) .slottedTokens.filter(function (t) { return Object.keys(t.scopes).length < 1; }) .map(function (t) { return t.token; }).join('').length; }); return sortedReplyContexts[0] || null; }; ElizaImpl.prototype.decompose = function (key, s) { var _this = this; var ASSEMBLE_FUNC = this.assemble; return (key.getDecomp() || []).map(function (decomposition) { var matches = mention.matchDecomposition(_this.synonyms, s, decomposition.getPattern()); if (!matches) { return null; } return { decomposition: decomposition, matches: matches, assembled: null, }; }).filter(utils_1.notEmpty).sort(function (ctxA, ctxB) { return (ctxA.matches || { slottedTokens: [{ token: s, scopes: {} }] }) .slottedTokens.filter(function (t) { return Object.keys(t.scopes).length < 1; }) .map(function (t) { return t.token; }).join('').length - (ctxB.matches || { slottedTokens: [{ token: s, scopes: {} }] }) .slottedTokens.filter(function (t) { return Object.keys(t.scopes).length < 1; }) .map(function (t) { return t.token; }).join('').length; }) .find(function (ctx) { ctx.assembled = _this.assemble(ctx.decomposition, ctx.matches.slottedTokens); if (!ctx.assembled) { return false; } if (ctx.assembled instanceof key_goto_1.GotoKey) { if (ctx.assembled.getKey()) { return true; } } else { return true; } return false; }) || null; }; ElizaImpl.prototype.fullyDecompose = function (key, s) { var _this = this; var decomposeCtx = this.decompose(key, s); var _loop_1 = function () { if (decomposeCtx.assembled instanceof key_goto_1.GotoKey) { var gotoKey = decomposeCtx.assembled; decomposeCtx = this_1.decompose(gotoKey, s); return "continue"; } if (!decomposeCtx.assembled) { return { value: null }; } var assembledResult = decomposeCtx.assembled; assembledResult.reassembled = PrePostUtil .translate(this_1.tweakList, assembledResult.reassembled); Object.keys(assembledResult.annotations).forEach(function (k) { assembledResult.annotations[k] = PrePostUtil .translate(_this.tweakList, assembledResult.annotations[k]); }); return { value: { decomposition: decomposeCtx.decomposition, matches: decomposeCtx.matches, assembled: assembledResult, } }; }; var this_1 = this; while (decomposeCtx) { var state_1 = _loop_1(); if (typeof state_1 === "object") return state_1.value; } return null; }; ElizaImpl.prototype.assemble = function (d, decomposedSlots) { var _this = this; var decomposedTokens = decomposedSlots.map(function (s) { return s.token; }); var rule = d.nextRule(); var assembledResult = rule.assemble(decomposedTokens.map(function (token) { return PrePostUtil.translate(_this.postList, token).trim(); })); if (assembledResult.gotoKey && assembledResult.gotoKey.length > 0) { var gotoKey = this.keys.find(function (k) { return k.getKey() === assembledResult.gotoKey; }); if (gotoKey && gotoKey.getKey()) { return new key_goto_1.GotoKey(gotoKey); } throw new exceptions_1.GotoLostException(rule.getTemplate()); } if (!assembledResult.result) { return null; } if (d.isMemoryKey()) { this.mem.push(assembledResult.result); return null; } return { reassembled: assembledResult.result, annotations: d.getAnnotates() .map(function (annotate) { return annotate.assemble(decomposedTokens); }) .reduce(function (reduced, current) { if (current.annotation) { reduced[current.annotation] = current.result + ''; } return reduced; }, {}), }; }; return ElizaImpl; }());