This repository hosts the source code and documentation for the Bachelor's thesis of Niklas Franz.
The thesis aims to conceptualize and implement a research instrument capable of observing the interaction between humans and Artificial Intelligence. To achieve this, a web application, which is simulating a business process involving two AI's, is embedded in an experiment using a questionnaire tool comprising several stages. Each stage hosts it's own variant of the web application business process and includes several questionnaires.
The web application consists of multiple services encapsulated in docker containers and are orchestrated using docker-compose. The primary services are:
- a frontend webpage, built with Vue.js and Vuetify
- a RESTful backend API, built with Express.js
- a backend database, using MySQL DBMS
There are several secondary services supporting the usage and workflow of the primary services:
- NGINX reverse-proxy: a reverse proxy that routes all services into a single port route that can then be accessed from a single hostname
- adminer / phpmyadmin: a database administration tool to view and manipulate the data in the database from the web
- portainer: a docker orchestration tool to remotely administrate the docker containers on the host-server from the web
The containers support a development and production environment. For the production environment, hostnames are changed from localhost to the live domain (cpfexperiment.lswi.de).
When added to the HTTP query string, following query parameters change the behaivior of the web application:
| parameter | type | effect / behaivior | default value |
|---|---|---|---|
| timeout | int | controls the time in minutes until the application is forced to stop | 6 |
| maxJobs | int | controls the amount of jobs the participant has to complete before the application is stopped | 6 |
| debug | boolean (true/false) | controls if debug parameters are shown | false |
| scenarioId | int (0-4) | controls which ai scenario the app will implement | 1 |
| prolificId | string | if any string is given, a session is created in the backend and metrics are enabled | none |
| aiExperienceId | int (1-6) | controls which ai experience the app will host | 1 |
| experimentId | string (1-5) | reference for which part of the experiment the app is used; will be associated with the backend session | none |
Following metrics are generated during the process when using the app:
| action_name | value | occurance | state | job_count | part_nr | sessionId |
|---|---|---|---|---|---|---|
| block_job | part_nr selected job | when pressing "Auftrag blockieren" | current state | current job number (starts at 1) | null | sessionId |
| get_job | part_nr blocked job | when pressing "Auftrag abholen" | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| start_countdown | name of the last ai used (cbr/ann) | when the countdown is started (only scenarios 2 & 4) | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| complete_countdown | null | when the countdown completed without intervention (only scenarios 2 & 4) | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| interrupt_countdown | time left | when the countdown is interrupted (only scenarios 2 & 4) | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| save_fruit | fruit selected | when pressing "Sorte speichern" | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| execute_scan | null | when pressing "Scan starten" (excluding scenario 0) | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| save_quality | quality selected | when pressing "Qualität speichern" | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| deliver_job | part_nr selected job | when pressing "Auftrag ausliefern" | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| invalid_action | action_name of illegal action | when pressing an invalid button | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| question_frustration | likert scale answer | when answering the questionnaire (excluding scenario 0) | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| question_trust | likert scale answer | when answering the questionnaire (excluding scenario 0) | current state | current job number (starts at 1) | part_nr blocked job | sessionId |
| app_end | end reason (time / jobs complete) | when the app ends through timeout or job limit | null | current job number (starts at 1) | null | sessionId |
- MacOS or Linux
- Docker
- NodeJS
The App is designed to work in both a development environment (on a local machine) and a production environment (on a web-server). While both setups rely on the docker virtualization egnine at their core and are similar in many aspects, some aspects of the app differ depending on the environment the app is running in.
In the .env-File located at the project root, environment-specific parameters are stored and change the way the app behaves. Following parameters should be present:
| Description | Development | Production | |
|---|---|---|---|
| App-Environment | A short string used by the components to determine the app-environment | DEV | PROD |
| Port | The port allocated by the ingress controller, which serves as an entry point to the app | 80 | 3000 |
| Base-Url | The url that is used by Vue to be able to locate ressources (such as the API) | http://localhost | https://cpfexperiment.lswi.de |
| Routing Architecture | The app routing | the ingress controller (app-entry point) is directly accessible under the base-url and the specified port (default http://localhost:80) | relies on a reverse proxy, that redirects incoming requests to the ingress controller |
In the .mysql.env-File, located in services/database-mysql/.mysql.env, parameters used by the MySQL-Database, such as a database user and password, are configured. Following parameters should be present:
TODO The app routing the ingress controller (app-entry point) is directly accessible under
the base-url and the specified port (default http://localhost:80)
relies on a reverse proxy, that redirects incoming requests to the ingress controller
On a fresh install, after cloning the repository and installing all dependencies, the bin/setup-application.sh script can be executed.
Using the users input while providing app-environment specific defaults, the global Env-File located in the root directory and the MySQL-Env-File located in services/database-mysql/.mysql.env are created. The script is also handling all other steps necessary to fully configure the application.
The app can be started using the command docker compose up -d. Likewise, it is stopped using docker compose down
Important: the aforementioned Env files must be present, either manually created or by using the setup script, or the app will notify you and abort.
While developing the app locally on your machine, the default git commit workflow should be used.
Most source code changes from origin/main can be integrated into an existing app-setup by executing the command docker compose restart.
This will reinstall the dependencies of both front- and backend-services inside the containers (using npm install).
In a production environment, the vue-service is used to fully recompile the vue-app into the caddy-service.
Thus, all changes in the backend and frontend are integrated automatically on restart.
On a production environment, when only the frontend-service has changed since the last commit, the command docker compose up -d is sufficient to rebuild the frontend.
If the docker compose orchestration file has been modified (docker-compose.yaml), a full restart of the docker compose orchestration is necessary to rebuild the app. This can be done by executing the command docker compose down, followed by docker compose up -d. This is also the best way to integrate changes if you are unsure what changes actually have been made.