{"id":16908029,"url":"https://github.com/cjrh/empatico","last_synced_at":"2025-03-20T17:17:11.308Z","repository":{"id":70770342,"uuid":"412961016","full_name":"cjrh/empatico","owner":"cjrh","description":"Emotion detection microservice based on natural language inference","archived":false,"fork":false,"pushed_at":"2024-11-12T11:39:04.000Z","size":1683,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-25T15:44:54.141Z","etag":null,"topics":["emotion-detection","mnli","natural-language-inference","natural-language-processing","sentiment-analysis","sentiment-classification"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cjrh.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["cjrh"]}},"created_at":"2021-10-03T02:54:05.000Z","updated_at":"2024-11-12T11:39:08.000Z","dependencies_parsed_at":"2024-04-23T21:42:50.327Z","dependency_job_id":"b91bc237-f6c0-4b64-948d-0313441a6617","html_url":"https://github.com/cjrh/empatico","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/cjrh%2Fempatico","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjrh%2Fempatico/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjrh%2Fempatico/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjrh%2Fempatico/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cjrh","download_url":"https://codeload.github.com/cjrh/empatico/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244656738,"owners_count":20488640,"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":["emotion-detection","mnli","natural-language-inference","natural-language-processing","sentiment-analysis","sentiment-classification"],"created_at":"2024-10-13T18:49:52.583Z","updated_at":"2025-03-20T17:17:11.284Z","avatar_url":"https://github.com/cjrh.png","language":"Python","funding_links":["https://github.com/sponsors/cjrh"],"categories":[],"sub_categories":[],"readme":"empatico\n========\n\nEmotion detection microservice based on natural language inference\n\n.. raw:: html\n\n    \u003cp align=\"center\" width=\"100%\"\u003e\n        \u003cimg width=\"100%\" src=\"https://raw.githubusercontent.com/cjrh/empatico/main/clown.jpg\"\u003e\n    \u003c/p\u003e\n\n\n.. contents:: Table of Contents\n\n\nDemo\n----\n\nLaunch the model (dev mode, auto-reloading):\n\n.. code-block:: bash\n\n    $ python3 -m venv .venv\n    $ source ./venv/bin/activate\n    (.venv) $ pip install -r requirements.txt\n    (.venv) $ pip install flit\n    (.venv) $ flit install --symlink\n    (.venv) $ uvicorn empatico:app --reload\n    INFO:     Will watch for changes in these directories: ['/home/caleb/Documents/repos/empatico']\n    INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\n    INFO:     Started reloader process [303534] using watchgod\n\nThere are several classifications already set up. You just need to provide the\ntext:\n\n.. code-block:: bash\n\n    $ curl --request POST \\\n        --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"I love when you speak to me rudely\"}' \\\n        http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"mixed\",\n        \"score\": 92.90633797645569\n      },\n      {\n        \"label\": \"anger\",\n        \"score\": 95.19177079200745\n      },\n      {\n        \"label\": \"sarcastic\",\n        \"score\": 97.97245264053345\n      }\n    ]\n\nWow, a label for sarcasm! Here's another one:\n\n.. code-block:: bash\n\n    $ curl --request POST \\\n        --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"Best insurance company in europe what a joke\"}' \\\n        http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"negative\",\n        \"score\": 99.07029867172241\n      },\n      {\n        \"label\": \"mixed\",\n        \"score\": 92.89084672927856\n      },\n      {\n        \"label\": \"anger\",\n        \"score\": 99.08776879310608\n      },\n      {\n        \"label\": \"sadness\",\n        \"score\": 92.85369515419006\n      },\n      {\n        \"label\": \"bitter\",\n        \"score\": 99.18588995933533\n      },\n      {\n        \"label\": \"sarcastic\",\n        \"score\": 99.7484564781189\n      },\n      {\n        \"label\": \"fear\",\n        \"score\": 89.00700807571411\n      },\n      {\n        \"label\": \"disgust\",\n        \"score\": 99.62377548217773\n      },\n      {\n        \"label\": \"surprise\",\n        \"score\": 99.7963547706604\n      }\n    ]\n\nAgain sarcasm is detected (99.7% probability), with a few other comorbid emotions. Another test of \nthe sarcasm detector:\n\n.. code-block:: bash\n\n    $ curl --request POST \\\n        --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"yes go ahead and sue me, I''m sure that will work out fine for you\"}' \\\n        http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"sarcastic\",\n        \"score\": 96.60570025444031\n      },\n      {\n        \"label\": \"helpful\",\n        \"score\": 87.13959455490112\n      },\n      {\n        \"label\": \"trust\",\n        \"score\": 89.57158923149109\n      }\n    ]\n\nIt isn't always negative:\n\n.. code-block:: bash\n\n    $ curl --request POST \\\n        --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"Staff were wonderful and made the trip that much more pleasant. Thank you!\"}' \\\n        http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"positive\",\n        \"score\": 94.82141733169556\n      },\n      {\n        \"label\": \"satisfied\",\n        \"score\": 95.2349305152893\n      },\n      {\n        \"label\": \"helpful\",\n        \"score\": 95.06783485412598\n      },\n      {\n        \"label\": \"joy\",\n        \"score\": 95.37110924720764\n      }\n    ]\n\nBy default, a rich array of emotional labels is provided:\n\n.. code-block:: bash\n\n    $ curl --request POST \\\n        --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"The only way you could have done any worse is lose my package completely.\"}' \\\n        http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"negative\",\n        \"score\": 98.56123924255371\n      },\n      {\n        \"label\": \"anger\",\n        \"score\": 97.950679063797\n      },\n      {\n        \"label\": \"sadness\",\n        \"score\": 89.63329792022705\n      },\n      {\n        \"label\": \"disappointment\",\n        \"score\": 87.91854977607727\n      },\n      {\n        \"label\": \"bitter\",\n        \"score\": 90.94756841659546\n      },\n      {\n        \"label\": \"fear\",\n        \"score\": 90.21917581558228\n      },\n      {\n        \"label\": \"disgust\",\n        \"score\": 90.52256941795349\n      },\n      {\n        \"label\": \"surprise\",\n        \"score\": 83.91632437705994\n      }\n    ]\n\nDefault labels (and reporting threshold)\n----------------------------------------\n\nYou can also control the cutoff threshold for reporting. Here we set it to zero,\nwhich disables the filter. This shows all the default hypotheses (which are \nexpressed as labels):\n\n.. code-block:: bash\n\n    $ curl --request POST \\\n        --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"The kids were so looking forward to the trip but the rain washed away all our plans.\", \\\n            \"report_threshold\": 0.0}' \\\n        http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"positive\",\n        \"score\": 0.7067840080708265\n      },\n      {\n        \"label\": \"negative\",\n        \"score\": 98.16489219665527\n      },\n      {\n        \"label\": \"mixed\",\n        \"score\": 98.80892634391785\n      },\n      {\n        \"label\": \"satisfied\",\n        \"score\": 0.7183659821748734\n      },\n      {\n        \"label\": \"neutral1\",\n        \"score\": 0.5342578981071711\n      },\n      {\n        \"label\": \"neutral2\",\n        \"score\": 0.034320083796046674\n      },\n      {\n        \"label\": \"neutral3\",\n        \"score\": 4.02584969997406\n      },\n      {\n        \"label\": \"factual\",\n        \"score\": 6.705068796873093\n      },\n      {\n        \"label\": \"anger\",\n        \"score\": 33.71554911136627\n      },\n      {\n        \"label\": \"sadness\",\n        \"score\": 98.14655780792236\n      },\n      {\n        \"label\": \"disappointment\",\n        \"score\": 99.36606287956238\n      },\n      {\n        \"label\": \"bitter\",\n        \"score\": 61.47879958152771\n      },\n      {\n        \"label\": \"sarcastic\",\n        \"score\": 31.848391890525818\n      },\n      {\n        \"label\": \"helpful\",\n        \"score\": 71.62957191467285\n      },\n      {\n        \"label\": \"fear\",\n        \"score\": 17.39620268344879\n      },\n      {\n        \"label\": \"disgust\",\n        \"score\": 4.311040416359901\n      },\n      {\n        \"label\": \"surprise\",\n        \"score\": 90.2463436126709\n      },\n      {\n        \"label\": \"hope\",\n        \"score\": 0.21583051420748234\n      },\n      {\n        \"label\": \"trust\",\n        \"score\": 37.46950924396515\n      },\n      {\n        \"label\": \"joy\",\n        \"score\": 0.47363536432385445\n      }\n    ]\n\nIt is really interesting that while the \"overall\" positive score is 0.7% and\nthe \"overall\" negative score is 98%, we do still see a \"mixed\" score\nof 98.8%. This can be interpreted as \"while there were both positive and\nnegative sentiments expressed, the negative outweighs the positive\".\n\nCustomizable hypotheses\n-----------------------\n\nYou can also provide your own hypotheses, which means you can generalise this\nto many difference kinds of classifications:\n\n.. code-block:: bash\n\n    $ curl --request POST --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"The democrats are ruining this country\", \\\n        \"report_threshold\": 0.0, \\\n        \"hypotheses\": {\"politics\": \"this text is about politics\", \\\n        \"sport\": \"this text is about sport\"}}' http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"politics\",\n        \"score\": 97.42230772972107\n      },\n      {\n        \"label\": \"sport\",\n        \"score\": 0.16288807382807136\n      }\n    ]\n    ~\n    $ curl --request POST --header \"Content-Type: application/json\" \\\n        --data '{\"text\": \"The tour de france was exhilarating to watch\", \\\n        \"report_threshold\": 0.0, \\\n        \"hypotheses\": {\"politics\": \"this text is about politics\", \\\n        \"sport\": \"this text is about sport\"}}' http://127.0.0.1:8000/emotions | jq\n    [\n      {\n        \"label\": \"politics\",\n        \"score\": 0.4232536070048809\n      },\n      {\n        \"label\": \"sport\",\n        \"score\": 97.9870855808258\n      }\n    ]\n\nBackground\n----------\n\nThe underlying technique for using natural language inference for classification\nwas described by Joe Davison here: \n\nhttps://joeddav.github.io/blog/2020/05/29/ZSL.html\n\nThe underlying idea is that, instead of using a model specifically trained for\nbinary, ternary, or n-ary classification, we might instead try to use a model\ndesigned for *inference* and test whether a particular hypothesis is supported\nby a piece of text. This dramatically expands the scope of possible labels \nto apply to a given piece of text, and you don't need the model to have been\nspecifally trained for those labels either.\n\nThe model being used in the code is \n`facebook/bart-large-mnli \u003chttps://huggingface.co/facebook/bart-large-mnli\u003e`_.\n\nRunning the server in dev\n-------------------------\n\n.. code-block:: bash\n\n    $ uvicorn empatico:app --reload\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcjrh%2Fempatico","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcjrh%2Fempatico","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcjrh%2Fempatico/lists"}