{"id":24405254,"url":"https://github.com/iagoleal/eliza","last_synced_at":"2025-04-12T00:30:24.870Z","repository":{"id":49321568,"uuid":"330842313","full_name":"iagoleal/eliza","owner":"iagoleal","description":"An implementation of ELIZA, Weizenbaum's classic chatbot.","archived":false,"fork":false,"pushed_at":"2021-05-14T02:37:38.000Z","size":158,"stargazers_count":19,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T20:12:33.249Z","etag":null,"topics":["artificial-intelligence","chatbot","eliza","symbolic-artificial-intelligence"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iagoleal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-19T02:32:14.000Z","updated_at":"2025-01-22T12:45:01.000Z","dependencies_parsed_at":"2022-08-26T22:31:01.212Z","dependency_job_id":null,"html_url":"https://github.com/iagoleal/eliza","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/iagoleal%2Feliza","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iagoleal%2Feliza/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iagoleal%2Feliza/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iagoleal%2Feliza/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iagoleal","download_url":"https://codeload.github.com/iagoleal/eliza/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248500885,"owners_count":21114566,"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":["artificial-intelligence","chatbot","eliza","symbolic-artificial-intelligence"],"created_at":"2025-01-20T04:41:10.344Z","updated_at":"2025-04-12T00:30:24.811Z","avatar_url":"https://github.com/iagoleal.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Eliza Chatbot\n\n| **Build Status** |\n|:----------------:|\n| [![Build Status][build-img]][build-url] |\n\nThis is a Haskell implementation of Joseph Weizenbaum's classic chatbot ELIZA,\nbased upon the description found on his 1966 ACM paper [[1]](#1).\n\nThe idea for ELIZA comes from the 60s, the golden era of symbolic artificial intelligence.\nAs such, its answers are based on textual pattern matching,\ndifferently from the more modern chatbots based on machine learning.\nNevertheless, it was still an interesting project for putting Haskell's parsing capabilities into practice\nand the result can be pretty fun.\nIf you are stressed while debuging some code on the middle of the night,\ntry starting an `eliza` REPL and have some chat.\n\nSince people say an asciinema is worth more than a thousand words...\n[![asciicast](https://asciinema.org/a/400665.svg)](https://asciinema.org/a/400665)\n\n# Installation\n\nThe easiest and recommended way to install s using [stack](https://docs.haskellstack.org/en/stable/README/).\nTo directly install the executable to your path (Stack by default uses `~/.local/bin/`), run\n\n```\nstack setup \u0026\u0026 stack install\n```\n\nIf you just want to run the program to try it out without any installation or copy,\nyou can use the one-liner\n\n```\nstack setup \u0026\u0026 stack run\n```\n\n# Usage\n\nThis program consists of a simple REPL-like conversation between you and a program following a certain script.\nThe script to the bot is a JSON file and should be passed as the first command line argument:\n\n```\neliza path/to/script.json\n```\n\nIf no argument is passed, the program defaults to (kind of) emulate a Rogerian psychiatrist.\n\n## Writing a script\n\nThe bot bases its answers on decomposition / reassembly rules\ndefined in a JSON file who acts as a \"script\"\n(in the screenwriter sense, not the computer program sense).\nThe program comes with the doctor script from Weizenbaum's paper already bundled\nand loaded by default but you can write any set of rules you want.\nSee the folder `scripts/` for examples of ready to use scripts.\n\nNote: on what follows, `\u003cword\u003e` stands for a sequence of alphanumeric characters\nand `\u003cnumber\u003e` for a sequence of digits representing a positive number.\n\nA script consists of a single JSON object that must have the following fields:\n\n| Field           | Type             | Optional                |\n|:----------------|:-----------------|:------------------------|\n| `\"greetings\"`   | Array of strings | No                      |\n| `\"goodbyes\"`    | Array of strings | No                      |\n| `\"default\"`     | Array of strings | No                      |\n| `\"groups\"`      | Object           | Yes (defaults to empty) |\n| `\"reflections\"` | Object           | Yes (defaults to empty) |\n| `\"keywords\"`    | Array of objects | No                      |\n\nThe fields `\"greetings\"`, `\"goodbyes\"`, and `\"default\"`\nstore, respectively, the program's possible initial messages,\npossible final messages, and the default replies to choose from\nwhen the input doesn't match the decomposition rules for any keyword.\n\nThe optional field `\"groups\"` is a dictionary storing in the field `\"\u003cword\u003e\"`\nan array of strings. Any decomposition rule referring to this group\nmatches any element of the array.\n\nThe optional field `\"reflections\"` is a dictionary storing strings.\nThese are the system's simplest rewriting rules,\nIf there is a field of the form `\"\u003cword1\u003e\": \"\u003cword2\u003e\"`,\nthe program will substitute any occurrence of `\u003cword1\u003e` in the input for `\u003cword2\u003e`.\nNotice that this exchange happens _after_ the keyword scanning\nbut _before_ testing the decomposition rules.\n\nThe field `\"keywords\"` store an array of objects following a specific schema.\n\n| Field          | Type             | Optional                |\n|:---------------|:-----------------|:------------------------|\n| `\"keyword\"`    | String           | No                      |\n| `\"precedence\"` | Integer          | Yes (defaults to 0)     |\n| `\"rules\"`      | Array of objects | No                      |\n| `\"memory\"`     | Array of objects | Yes (defaults to empty) |\n\nBoth `\"rules`\" and `\"memory\"` store the same kind of object, herein called a rule.\nEach rule is itself an object with two fields:\n`\"decomposition\"` storing a string and\n`\"reassembly\"` storing an array of strings.\nThese represent the decomposition rule and choices of reassembly rules\nin the case of a match.\nHow to write them is explained below.\n\n### Decomposition rules\n\nThere are two options for a decomposition rule.\nEither it is of the form `\"=\u003cword\u003e\"`,\nin which case it tells the program to try the rules associated with the keyword `\u003cword\u003e`,\nor it consists of a string of space separated expressions as described below.\n\n| Expression            | Description                         |\n|:----------------------|:------------------------------------|\n| `\u003cword\u003e`              | match exactly `\u003cword\u003e`              |\n| `*`                   | match zero or more words            |\n| `#\u003cnumber\u003e`           | match exactly `\u003cnumber\u003e` words      |\n| `[\u003cword\u003e ... \u003cword\u003e]` | match any of word in the list       |\n| `@\u003cword\u003e`             | match a keyword from group `\u003cword\u003e` |\n\nEach expression matches a certain kind of word or phrase.\nSo, for example, the rule `\"* I [love hate] #4 @family *\"`\ncan only match a phrase consisting of anything followed by the word `you`,\nfollowed by one of `love` or `hate`, followed by exactly two words,\nfollowed by any word of the group `family` followed by anything.\nThis means that the phrase `\"I love to ski with my children on cold weekends\"`\nmatches into the list `[\"\", \"I\", \"love\", \"to ski with my\", \"children\", \"on cold weekends\"]`.\nIf a phrase does not match the rule structure, the program skips the rule.\n\n### Reassembly rules\n\nThere are three kinds of reassembly rule.\nIt can be a newkey directive, `\":newkey\"`,\ntelling the program to continue looking for keywords on the stack,\nit can point to another keyword, `\"\u003cword\u003e\"`,\nor it can be a proper reassembly rule,\nthat is, a string where the special term `$\u003cnumber\u003e` may appear.\nThe reassembly process substitutes `$\u003cnumber\u003e` by the `\u003cnumber\u003e`th element\nof the decomposed input. No length checks are made,\nso you must guarantee that the decomposition has enough elements.\n\n| Expression                        | Description                                         |\n|:----------------------------------|:----------------------------------------------------|\n| `:newkey`                         | try rules for next keyword on the stack             |\n| `=\u003cword\u003e`                         | try rules for keyword `\u003cword\u003e`                      |\n| `\u003cword\u003e ... $\u003cnumber\u003e ... \u003cword\u003e` | interpolate `\u003cnumber\u003e`th word on the list on string |\n\n## Differences to the original implementation\n\nI began by following Weizenbaum's paper by heart\nbut later diverged on some implementation details.\nThis is a list of what's different:\n\n- Scripts are JSON files instead of MAD-SLIP files.\n- There are many greetings and goodbyes options.\n- Reassembly rules are chosen randomly after a given decomposition rule match,\nwhereas in the original, the bot keeps a state and cycles through them.\n- Any keyword can be used as a memory transformation, not just one.\n\n## References\n\u003ca id=\"1\"\u003e[1]\u003c/a\u003e\nJoseph Weizenbaum. 1966. ELIZA — A Computer Program for the Study of Natural Language Communication Between Man and Machine. Commun. ACM 9, 1 (Jan. 1966), 36–45. DOI: https://doi.org/10.1145/365153.365168\n\n\n[build-img]: https://github.com/iagoleal/eliza/actions/workflows/ci.yml/badge.svg?branch=master\n[build-url]: https://github.com/iagoleal/eliza/actions/workflows/ci.yml\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiagoleal%2Feliza","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiagoleal%2Feliza","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiagoleal%2Feliza/lists"}