{"id":21042719,"url":"https://github.com/yugabytedb-samples/yugaplus","last_synced_at":"2025-05-15T17:31:09.646Z","repository":{"id":220583288,"uuid":"731692543","full_name":"YugabyteDB-Samples/YugaPlus","owner":"YugabyteDB-Samples","description":"A sample movie recommendation service that takes user questions in plain English and provides recommendations using a gen AI stack.","archived":false,"fork":false,"pushed_at":"2024-02-26T15:41:02.000Z","size":37895,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-14T18:45:22.833Z","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":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YugabyteDB-Samples.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,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-12-14T16:46:47.000Z","updated_at":"2024-03-21T22:22:29.000Z","dependencies_parsed_at":"2024-02-26T16:57:17.397Z","dependency_job_id":null,"html_url":"https://github.com/YugabyteDB-Samples/YugaPlus","commit_stats":null,"previous_names":["yugabytedb-samples/yugaplus"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YugabyteDB-Samples%2FYugaPlus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YugabyteDB-Samples%2FYugaPlus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YugabyteDB-Samples%2FYugaPlus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YugabyteDB-Samples%2FYugaPlus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YugabyteDB-Samples","download_url":"https://codeload.github.com/YugabyteDB-Samples/YugaPlus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225365969,"owners_count":17462973,"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-11-19T14:08:47.237Z","updated_at":"2024-11-19T14:08:47.964Z","avatar_url":"https://github.com/YugabyteDB-Samples.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# YugaPlus: Movie Recommendations Service with OpenAI, Spring AI, and PostgreSQL pgvector\n\nThis is a sample movie recommendation service that is built on an OpenAI embedding model, Spring AI framework and PostgreSQL pgvector.\n\n\u003cimg width=\"812\" alt=\"yugaplus-screenshot\" src=\"https://github.com/YugabyteDB-Samples/YugaPlus/assets/1537233/afa794a7-4ed5-41e6-ba59-fb07d7c5c0cd\"\u003e\n\nThe service takes user questions written in plain English and uses a gen AI stack (OpenAI, Spring AI and PostgreSQL pgvector) to provide the user with the most relevant movie recommendations.\n\n## Prerequisites\n\n1. The latest version of Docker and Docker Compose.\n2. [OpenAI API key](https://platform.openai.com)\n\nIf you're planning to run the app on bare metal, then make sure to have:\n\n1. Node.js 20+\n2. Java 21+. Use [sdkman](https://sdkman.io) to install it within a minute.\n3. Maven 3.9+\n\n## Start Database Instance In Docker\n\nThe pgvector extension is supported by a single-server PostgreSQL instance as well as a multi-node YugabyteDB cluster. Feel free to use any of the database options.\n\n### Start PostgreSQL in Docker\n\n1. Create the `postgres-volume` directory for the Postgres container's volume in your home dir. The volume is handy if you'd like to access the logs easily and don't want to lose data when the container is recreated from scratch:\n\n    ```shell\n    mkdir ~/postgres-volume\n    ```\n\n2. Create a custom Docker network:\n\n    ```shell\n    docker network create yugaplus-network\n    ```\n\n3. Start the Postgres container with the pgvector extension:\n\n    ```shell\n    docker run --name postgres --net yugaplus-network \\\n        -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password \\\n        -p 5432:5432 \\\n        -v ~/postgres-volume/:/var/lib/postgresql/data \\\n        -d ankane/pgvector:latest\n    ```\n\n4. Make sure the container is running:\n\n    ```shell\n    docker container ls -f name=postgres\n    ```\n\n### Start YugabyteDB in Docker\n\n1. Create a custom Docker network:\n\n    ```shell\n    docker network create yugaplus-network\n    ```\n\n2. Start a YugabyteDB cluster:\n\n    ```shell\n    rm -r ~/yugabyte-volume\n    mkdir ~/yugabyte-volume\n\n    docker run -d --name yugabytedb-node1 --net yugaplus-network \\\n    -p 15433:15433 -p 7001:7000 -p 9001:9000 -p 5433:5433 \\\n    -v ~/yugabyte-volume/node1:/home/yugabyte/yb_data --restart unless-stopped \\\n    yugabytedb/yugabyte:latest \\\n    bin/yugabyted start --base_dir=/home/yugabyte/yb_data --daemon=false\n    \n    # Wait until the first node is initialized and ready to accept connection\n    while ! docker exec -it yugabytedb-node1 postgres/bin/pg_isready -U yugabyte -h yugabytedb-node1; do sleep 1; done\n\n    docker run -d --name yugabytedb-node2 --net yugaplus-network \\\n    -p 15434:15433 -p 7002:7000 -p 9002:9000 -p 5434:5433 \\\n    -v ~/yugabyte-volume/node2:/home/yugabyte/yb_data --restart unless-stopped \\\n    yugabytedb/yugabyte:latest \\\n    bin/yugabyted start --join=yugabytedb-node1 --base_dir=/home/yugabyte/yb_data --daemon=false\n        \n    docker run -d --name yugabytedb-node3 --net yugaplus-network \\\n    -p 15435:15433 -p 7003:7000 -p 9003:9000 -p 5435:5433 \\\n    -v ~/yugabyte-volume/node3:/home/yugabyte/yb_data --restart unless-stopped \\\n    yugabytedb/yugabyte:latest \\\n    bin/yugabyted start --join=yugabytedb-node1 --base_dir=/home/yugabyte/yb_data --daemon=false\n    ```\n\n## Start Application\n\nYou have an option of deploying the application in Docker or on your host operating system (bare metal).\n\n## Start Application With Docker Compose\n\nBy default, the containers will attempt to connect to the PostgreSQL container.\nIf you use YugabyteDB:\n\n1. Update the following settings in the `docker-compose.yaml`:\n\n    ```yaml\n    - DB_URL=jdbc:postgresql://yugabytedb-node1:5433/yugabyte\n    - DB_USER=yugabyte\n    - DB_PASSWORD=yugabyte\n    ```\n\n2. If you use YugabyteDB 2.20.1 or later, then add the following parameter:\n\n    ```yaml\n    - DB_CONN_INIT_SQL=\"SET yb_silence_advisory_locks_not_supported_error=true\"\n    ```\n\nDuring the first run, build an image and only then start the containers:\n\n```shell\ndocker-compose up --build\n```\n\nOnce the image is ready, use this command to start the containers:\n\n```shell\ndocker-compose up\n```\n\n## Start Application in Docker\n\nStart the backend in Docker:\n\n1. Create a Docker image for the backend:\n\n    ```shell\n    cd backend\n    docker build -t yugaplus-backend .  \n    ```\n\n2. Start a backend container:\n\n    For PostgreSQL:\n\n    ```shell\n    docker run --name yugaplus-backend --net yugaplus-network -p 8080:8080 \\\n        -e DB_URL=jdbc:postgresql://postgres:5432/postgres \\\n        -e DB_USER=postgres \\\n        -e DB_PASSWORD=password \\\n        -e OPENAI_API_KEY=your-api-key \\\n        yugaplus-backend\n    ```\n\n    For YugabyteDB:\n\n    ```shell\n    docker run --name yugaplus-backend --net yugaplus-network -p 8080:8080 \\\n        -e DB_URL=jdbc:postgresql://yugabytedb-node1:5433/yugabyte \\\n        -e DB_USER=yugabyte \\\n        -e DB_PASSWORD=yugabyte \\\n        -e OPENAI_API_KEY=your-api-key \\\n        yugaplus-backend\n    ```\n\nStart the frontend in Docker:\n\n1. Create a Docker image for the frontend:\n\n    ```shell\n    cd frontend\n    docker build -t yugaplus-frontend .  \n    ```\n\n2. Start a frontend container:\n\n    ```shell\n    docker run --name yugaplus-frontend --net yugaplus-network -p 3000:3000 \\\n        -e REACT_APP_PROXY_URL=http://yugaplus-backend:8080 \\\n        yugaplus-frontend\n    ```\n\n### Start Application on Bare Metal\n\nBy default, the backend will attempt to connect to the PostgreSQL container.\nIf you use YugabyteDB:\n\n1. Update the following settings in the `application.properties` file:\n\n    ```properties\n    spring.datasource.url = jdbc:postgresql://yugabytedb-node1:5433/yugabyte\n    spring.datasource.username = yugabyte\n    spring.datasource.password = yugabyte\n    ```\n\n2. If you use YugabyteDB 2.20.1 or later, then add the following parameter:\n\n    ```properties\n    spring.datasource.hikari.connection-init-sql=\"SET yb_silence_advisory_locks_not_supported_error=true\"\n    ```\n\nStart the backend:\n\n1. Provide your OpenAI key in the `backend/src/main/resources/application.properties` file:\n\n    ```properties\n    spring.ai.openai.api-key=sk-\n    ```\n\n2. Go to the backend directory and start the app:\n\n    ```shell\n    cd backend\n    mvn spring-boot:run\n    ```\n\nStart the frontend:\n\n1. Go to the frontend directory:\n\n    ```shell\n    cd frontend\n    ```\n\n2. Start the app:\n\n    ```shell\n    npm install\n    npm start\n    ```\n\n## Test Application\n\nGo to [http://localhost:3000](http://localhost:3000) and test the application.\n\nSign in using the following credentials:\n\n* `user1@gmail.com/password` - already has some movies in the library\n* `user2@gmail.com/password` - the library is empty\n\nTry a few prompts:\n*A movie about a space adventure.*\n*A kids-friendly movie with unexpected ending.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyugabytedb-samples%2Fyugaplus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyugabytedb-samples%2Fyugaplus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyugabytedb-samples%2Fyugaplus/lists"}