{"id":19459806,"url":"https://github.com/jsflo/emotionrecserver","last_synced_at":"2026-04-11T16:43:22.795Z","repository":{"id":187794765,"uuid":"133042359","full_name":"JsFlo/EmotionRecServer","owner":"JsFlo","description":"Ktor server for Tensorflow serving using local inference (Local model with Tensorflow Java Api) and GCP inference (Model uploaded to ML:Engine)","archived":false,"fork":false,"pushed_at":"2018-09-03T16:49:29.000Z","size":155,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-08T02:16:03.910Z","etag":null,"topics":["kotlin","ktor","tensorflow","tensorflow-java","tensorflow-java-client"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","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/JsFlo.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}},"created_at":"2018-05-11T13:21:47.000Z","updated_at":"2024-02-29T20:24:34.000Z","dependencies_parsed_at":"2023-08-12T06:52:20.246Z","dependency_job_id":null,"html_url":"https://github.com/JsFlo/EmotionRecServer","commit_stats":null,"previous_names":["jsflo/emotionrecserver"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JsFlo%2FEmotionRecServer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JsFlo%2FEmotionRecServer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JsFlo%2FEmotionRecServer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JsFlo%2FEmotionRecServer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JsFlo","download_url":"https://codeload.github.com/JsFlo/EmotionRecServer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240664480,"owners_count":19837563,"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":["kotlin","ktor","tensorflow","tensorflow-java","tensorflow-java-client"],"created_at":"2024-11-10T17:34:10.209Z","updated_at":"2026-04-11T16:43:17.752Z","avatar_url":"https://github.com/JsFlo.png","language":"Kotlin","readme":"# EmotionRecServer\nKtor server for providing emotion recognition. This is done through a trained TensorFlow model that is either located locally or uploaded to Google Cloud Platform [ML Engine](https://cloud.google.com/ml-engine/).\n\nI wrote an [article covering the specific TensorFlow model I trained](https://medium.com/@jsflo.dev/training-a-tensorflow-model-to-recognize-emotions-a20c3bcd6468).\n\n## Modes of inference\n* Local Inference\n* GCP Inference [ML Engine]\n\nTo be able to choose which inference mode the server will use you will have to set a property in the application configuration found in  `/api_ktor/src/main/resources/application.conf`.\n\n```\nktor {\n    ...\n    application {\n        ...\n        gcp = false\n    }\n}\n\n```\n\nSetting *gcp* to *false* will configure the server to use the local inference otherwise it will use the model hosted in GCP.\n\n### Local Inference\nLocalInference will use the Java TensorFlow Api to load the trained model.\n\nTo be able to use local inference you first have to point the Server to the location of your model.\n\n**TODO**: Currently this is done through a static variable but this should be moved to a config file.\n\n`/api_ktor/src/main/kotlin/com/emotionrec/api/Server.kt`\n```java\nval LOCAL_INF_MODEL = \"./src/main/resources/1\"\nval LOCAL_INF_TAG = \"serve\"\n```\n\nThe first is the location of the model relative to the project and the other is the tag used while saving the model through the [SavedModelApi](https://medium.com/@jsflo.dev/saving-and-loading-a-tensorflow-model-using-the-savedmodel-api-17645576527).\n\n### GCP ML Engine Inference\nIn order to use the the predictions coming from the model hosted on GCP you will have to upload a saved model to your GCP account. You will need to have two things.\n* Path to your model\n* Credential File\n\n#### Path to your model\n`\"projects/ml-happy-rec/models/happy_rec_model/versions/v2:predict\"`\n\nThis is a hardcoded path found in the `RetrofitNetwork.kt` and should be changed to point to your specific model.\n\n#### Credentials\n**TODO**: Value should be set through config\n\n`/api_ktor/src/main/kotlin/com/emotionrec/api/Server.kt`\n```java\nval GOOGLE_CRED_FILE = \"happy_rec_cred.json\"\n```\n\nThis is currently handled through the use of the Google credential file given through GCP.\n\n## Running the Server\nTo run the api_ktor application: `./gradlew api_ktor:run`\nwhich will use the default settings (port) defined in the application.conf file.\n\n```\nktor {\n    deployment {\n        port = 8378\n        environment = development\n        watch = [ emotionrec ]\n    }\n\n    application {\n        id = emotionrec\n        modules = [com.emotionrec.api.ServerKt.main]\n        gcp = false\n    }\n}\n```\n### Simple Api\n**GET** /ping\n* Used for sanity checks and returns \"pong\"\n\n**POST** /prediction\n* Accepts [PostPredictionData].\n* Expects the [PostPredictionData.image_array]:\n    * to be an array of size **2304**\n    * String array separated by a delimiter [PostPredictionData.delimiter] (default: [DEFAULT_DELIMITER])\n\n* Responds with [PredictionError] or [PredictionResponse]\n\n**POST** /predictionImage\n* Accepts mutlipart file image upload\n* Responds with [PredictionError] or [PredictionResponse]\n\n#### PredictionResponse\n```json\n{\n    \"sortedPredictions\": [\n        {\n            \"probability\": 0.99999285,\n            \"emotion\": \"ANGRY\"\n        },\n        {\n            \"probability\": 0.0000035176417,\n            \"emotion\": \"SAD\"\n        },\n        {\n            \"probability\": 0.0000018190486,\n            \"emotion\": \"FEAR\"\n        },\n        {\n            \"probability\": 0.0000018007337,\n            \"emotion\": \"NEUTRAL\"\n        },\n        {\n            \"probability\": 1.873281e-8,\n            \"emotion\": \"HAPPY\"\n        },\n        {\n            \"probability\": 3.4072745e-11,\n            \"emotion\": \"DISGUST\"\n        },\n        {\n            \"probability\": 2.9763858e-12,\n            \"emotion\": \"SURPRISE\"\n        }\n    ],\n    \"guessedPrediction\": {\n        \"probability\": 0.99999285,\n        \"emotion\": \"ANGRY\"\n    }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsflo%2Femotionrecserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsflo%2Femotionrecserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsflo%2Femotionrecserver/lists"}