{"id":13623549,"url":"https://github.com/ava-ia/core","last_synced_at":"2025-04-15T14:33:26.894Z","repository":{"id":57155012,"uuid":"59555562","full_name":"ava-ia/core","owner":"ava-ia","description":"Agnostic Virtual Assistant","archived":false,"fork":false,"pushed_at":"2023-05-25T02:23:41.000Z","size":342,"stargazers_count":218,"open_issues_count":5,"forks_count":21,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-12T02:22:38.795Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ava-ia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-05-24T08:37:23.000Z","updated_at":"2024-11-17T20:23:55.000Z","dependencies_parsed_at":"2024-01-11T19:14:22.550Z","dependency_job_id":"a6e71181-1f93-4979-92d2-bfde2fab561f","html_url":"https://github.com/ava-ia/core","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ava-ia%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ava-ia%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ava-ia%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ava-ia%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ava-ia","download_url":"https://codeload.github.com/ava-ia/core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249089147,"owners_count":21210924,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T21:01:33.026Z","updated_at":"2025-04-15T14:33:26.546Z","avatar_url":"https://github.com/ava-ia.png","language":"JavaScript","funding_links":["https://paypal.me/soyjavi"],"categories":["JavaScript"],"sub_categories":[],"readme":"# \u003ca href='https://github.com/ava-ia/core'\u003e\u003cimg src='https://dl.dropboxusercontent.com/s/pdoawhkvg295ish/ava.png?dl=0' height='128'\u003e\u003c/a\u003e\n\n[![npm version](https://img.shields.io/npm/v/ava-ia.svg?style=flat-square)](https://www.npmjs.com/package/ava-ia) [![Build Status](http://img.shields.io/travis/ava-ia/core/master.svg?style=flat-square)](https://travis-ci.org/ava-ia/core) [![NPM Status](http://img.shields.io/npm/dm/ava-ia.svg?style=flat-square)](https://www.npmjs.org/package/ava-ia) [![devDependency Status](https://img.shields.io/david/ava-ia/core.svg?style=flat-square)](https://david-dm.org/ava-ia/core#info=dependencies) [![Donate](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square)](https://paypal.me/soyjavi)\n[![npm](https://img.shields.io/npm/l/botkit.svg?style=flat-square)](https://spdx.org/licenses/MIT)\n\nThe main purpose of AVA (Agnostic Virtual Assistant) is create a clever/fast assistant for any kind of context. This repository concerns the *core* of AVA so feel free for try in your NodeJS projects.\n\nNowadays we can find a lot of assistants, and more and more in the coming years, all of us know that Apps in the future will be more *conversational* and less *click/action*. For that reason our approach is create an agnostic and reusable system for help developers to create any kind of virtual assistants.\n\nThis is an Open Source project, so any help will be welcomed.\n\n\n## A little story about language processing... *and how Ava works*.\n\nIf you have never worked with assistants/bots then you have to know that we need to analyze a given input and give it a semantic value. To do this often use NLP, *Natural Language Processing*. AVA in its case incorporates its own NLP but as you will see later we can use either. For example:\n\n\u003e \"I need an appointment with the dentist tomorrow at 2pm in London\"\n\nAVA must understand your sentence and creates a *sentence relations scenario* like:\n  + **SUBJECT** `I`\n  + **ACTION** `need`\n  + **VALUE** `1`\n  + **OBJECT** `appointment`\n  + **ITEM** `the dentist`\n  + **WHEN** `Fri Jun 11 2016 14:00:00 GMT+0700 (ICT)`\n  + **LOCATION** `London`\n\nAlso gives you a *contextual information*:\n  + **LANGUAGE** = `en`\n  + **TYPE** = `declarative`\n  + **SENTIMENT** = `0` (neutral)\n  + **CLASSIFIER** = `/travel/transit`\n  + **PROFILE** *(If previously user has talked with AVA, returns a history)*\n\nAva depends on how you set up, but the next step is to process all the intents set. An intent is nothing more than a set of rules for scenarios *sentence relations* and *contextual information*.\n  + **has LOCATION?** *yes, London*\n  + **is negative SENTIMENT?** *no, is neutral*\n  + **know WHEN?** *yes, tomorrow at 2pm*\n  +\n\nIf any intent is successful, it will be assigned an action (or more) which will be returned to the user in answer mode.\n  + Set an appointment in phone's calendar like `${ITEM} in ${LOCATION} on ${DATE}`\n\nAnd that is, :)\n\n\n## Installation\n\nAVA can be installed as an [npm package](https://www.npmjs.org/package/ava-ia):\n\n```bash\n$ npm install --save ava-ia\n```\n\n\n## Basic usage\n\n```js\nimport Ava from `ava-ia`;\nimport { weather, movie } from `ava-ia/lib/intents`;\nimport { forecastYahoo, forecastMSN, movieDB } from `ava-ia/lib/actions`;\n\n// 1. New instance\nconst ava = new Ava({\n  debug: true // If you want see intents/actions trace log.\n});\n\n// 2. Configure the intents\nava\n  .intent(weather, [forecastYahoo, forecastMSN])\n  .intent(movie, movieDB);\n\n// 3. Chat with Ava\nava.listen('Do you know if tomorrow will rain in Bangkok?')\n  .then(state =\u003e console.log(state))\n  .catch(error =\u003e console.log(state))\n```\n\n\n## Instance methods\n\n#### intent()\nThe purpose of this method is to *teach* Ava about what kinds of things it can *answer* for you. As you read in the introduction the core of ava use *Intents* and *Actions* which are simple functions that receive a state and return it with an internal composition.\n\nThe method `intent` is *chainable* that means you can attach all the intents you need, more intents means Ava is more clever 😉. This method takes two parameters:\n\n  - `intent`: the *function* you wanna attach\n  - `actions`: an action *function* (or *Array* of functions) those will call if the intent is is satisfactorily resolved.\n\n```js\nimport { weather } from `ava-ia/lib/intents`;\nimport { forecastYahoo } from `ava-ia/lib/actions`;\n\nava.intent(weather, forecastYahoo);\n```\n\nIf we want attach two *actions* for the same *intent* just write:\n\n```js\nimport { forecastYahoo, forecastMSN } from `ava-ia/lib/actions`;\n\nava.intent(weather, [forecastYahoo, forecastMSN]);\n```\n\nAva will wait for the first successful action, that means it's like a race between the *actions* of a determinate *intent* and wins which finish first. If you wanna create a chain of `intents` it's quite easy:\n\n```js\nimport { weather, movie } from `ava-ia/lib/intents`;\nimport { forecastYahoo, movieDB } from `ava-ia/lib/actions`;\n\nava\n  .intent(weather, forecastYahoo)\n  .intent(movie, movieDB);\n```\n\n#### listen()\nThe purpose of this method is *talk* with Ava. Just receive an `string` parameter and returns a `Promise`:\n\n```js\nava.listen('Do you know if tomorrow will rain in Bangkok?')\n  .then(state =\u003e console.log(state))\n  .catch(error =\u003e console.log(state))\n```\n\nIf the promise is successful it will return a `object` with the state which contains the result of the processor and intents. The attributes of the *state* are:\n\n  - `rawSentence`: contains an *string* with the origin sentence.\n  - `language`: contains an *string* ISO code for language (cca2) of the sentence.\n  - `sentence`: contains an *string* sentence translated to english\n  - `taxonomy`: If `config.json` contains your [AlchemyAPI]() code containing an *array* of taxonomies.\n  - `classifier`: contains an array of terms for identify the sense of the sentence.\n  - `type`: *declarative*, *interrogative* or *exclamative* sentence.\n  - `topics`: contains an *array* of most important terms of the sentence.\n  - `tokens`: contains an *array* of rooted terms.\n  - `relations`: contains an *object* with the sentence relations:\n      + `subject`\n      + `adverb`\n      + `action`\n      + `object`\n      + `when`\n      + `location`\n      + `value`\n  - `sentiment`: contains an *number* being `-5` most negative , `0` neutral and `+5` most positive.\n\nThe most important attribute of *state* is `action` which contains an *object* with:\n  - `engine`: a *string* with the name of the action\n  - `ms`: contains the *number* of miliseconds waisted for resolve the action.\n  - `entity`: a *string* describing the type of content of the action.\n  - `title`: a *string*\n  - `text`: a *string* (optional).\n  - `value`: a *object* with explicit information about the content (optional).\n  - `image`: a *stringURL* (optional).\n  - `url`: a *url* with contains more info (optional).\n  - `related`: a *object* with extra information (optional).\n  - `date`: a *date* (optional).\n\nIn the case that Ava can't find a action for our sentence it will return an error that we can capture in the `catch` method.\n\n\n## Extend Ava with new *Intents* \u0026 *Actions*\nExtending Ava is quite easy, as you know all predefined *Intents* \u0026 *Actions* are stateless functions. So if you respect the input interface you can create your own Ava easily, lets see how.\n\n#### Create a new *Intent*\nRemember that when we set an intent in a determinate Ava instance we only need code:\n\n```js\nimport intentName from './intentName.js';\n\nava.intent(intentName, action);\n```\n\nAva will process your intent definition and will queue it on intents list to execute. But... what is your intent definition?, well you will receive two parameters:\n  - `state`: the actual *object* state.\n  - `actions`: a *array* of actions to execute if intent is successful.\n\nLets see the basic definition of your *intent*:\n\n**intentName.js**\n```js\nimport { resolve } from 'ava-ia/lib/helpers'\n\nexport default (state, actions) =\u003e {\n  resolve(state);\n};\n```\n\nAll intents must be *resolved* with the `state` (like a promise) but maybe your function it isn't a promise (async) for that reason we build the *helper* `resolve`. Just call it and your *intent* will be part of the factory of *intents*. Now we will see a complete example, our *intent* will:\n  - check if a list of *terms* are part of `state` attributes `tokens` and `classifier`\n  - check if the sentence has a specific syntax\n\n```js\n'use strict';\n\nimport { factoryActions, intersect, syntax, resolve } from 'ava-ia/lib/helpers'\n// -- Internal\nconst TERMS = [ 'film', 'movie' ];\nconst RULES = [\n  '[Person] want see [Noun]',\n];\n\nexport default (state, actions) =\u003e {\n  const tokens = intersect(TERMS, state.tokens);\n  const classifiers = intersect(TERMS, state.classifier);\n  const match = syntax(state.sentence, RULES);\n\n  if (tokens || classifiers || match) {\n    return factoryActions(state, actions);\n  } else {\n    return resolve(state);\n  }\n};\n```\n\nAs you can see, if we have `tokens`, or `classifiers` or `match` fulfilled we will call to our *actions* using the *helper* `factoryActions`. Easy right?\n\n#### Create a new *Action*\nBuild your own *actions* is quite easy, like *intents* is just create a *stateless* function. Actions functions only receive one parameter:\n  - `state`: the actual *object* state.\n\nsuccessful functions have two ways for communicate the action:\n  - `return` method for *sync* functions\n  - `resolve` *Promise* method  for *async* functions\n\nSo the easiest and basic example could be:\n\n```js\nexport default (state) =\u003e {\n  state.action = { value: 'Hello world!' };\n  return (state);\n}\n```\n\nAs you can see we just create the attribute `action` and return the state to Ava. But life sometimes is more difficult, so now we will create an *async* Action which will request *something* to a external data source:\n\n```js\nimport { entities } from 'ava-ia/lib/helpers'\n\nexport default (state) =\u003e {\n\n  return new Promise( async (resolve, reject) =\u003e {\n    response = await externalDataSource( {tokens: state.tokens} );\n\n    state.action = {\n      engine: 'mock',\n      type: entities.knowledge,\n      value: response.value\n    };\n\n    resolve(state);\n  });\n}\n```\n\nIn this example we use `resolve` method 'cause we are inside a *Promise*, as you see still being easy create any kind of *actions*.\n\n\n## Mastering in Ava\nIf you wanna learn more about Ava *internals* please take a look to our [wiki](https://github.com/ava-ia/core/wiki). Feel free to offer new features, improvements or anything you can think of. This project makes sense with your participation and experience using Ava.\n\n## Support\n\n### Funding\n\nThis software is provided to you as open source, free of charge. The time and effort to develop and maintain this project is dedicated by @soyjavi. If you (or your employer) benefit from this project, please consider a financial contribution. Your contribution helps continue the efforts that produce this and other open source software.\n\nFunds are accepted via [PayPal](https://paypal.me/soyjavi), any amount is appreciated.\n\n## License\n\nCopyright (c) 2016 Javier Jimenez Villar\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fava-ia%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fava-ia%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fava-ia%2Fcore/lists"}