diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f865d19 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +OPENAI_ACCESS_TOKEN=dummy \ No newline at end of file diff --git a/.gitignore b/.gitignore index c453501..671667a 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ node_modules # Ignore master key for decrypting credentials and more. /config/master.key + +.env diff --git a/Gemfile b/Gemfile index 40668a8..5a89313 100644 --- a/Gemfile +++ b/Gemfile @@ -55,3 +55,7 @@ group :development do end gem "active_model_serializers", "~> 0.10.13" + +gem "dotenv-rails", groups: %i[development test] +gem "ruby-openai" +gem "pry" diff --git a/Gemfile.lock b/Gemfile.lock index 717b53e..871309d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,6 +78,7 @@ GEM builder (3.2.4) case_transform (0.2) activesupport + coderay (1.1.3) concurrent-ruby (1.2.0) crass (1.0.6) database_cleaner (2.0.2) @@ -91,7 +92,17 @@ GEM irb (>= 1.5.0) reline (>= 0.3.1) diff-lcs (1.5.0) + dotenv (2.8.1) + dotenv-rails (2.8.1) + dotenv (= 2.8.1) + railties (>= 3.2) erubi (1.12.0) + faraday (2.7.10) + faraday-net_http (>= 2.0, < 3.1) + ruby2_keywords (>= 0.0.4) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (3.0.2) globalid (1.1.0) activesupport (>= 5.0) haml (6.1.1) @@ -117,6 +128,7 @@ GEM mini_mime (1.1.2) minitest (5.17.0) msgpack (1.6.0) + multipart-post (2.3.0) net-imap (0.3.4) date net-protocol @@ -133,6 +145,9 @@ GEM racc (~> 1.4) pg (1.4.5) prettier_print (1.2.1) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) puma (5.6.5) nio4r (~> 2.0) racc (1.6.2) @@ -186,6 +201,10 @@ GEM rspec-mocks (~> 3.12) rspec-support (~> 3.12) rspec-support (3.12.1) + ruby-openai (4.2.0) + faraday (>= 1) + faraday-multipart (>= 1) + ruby2_keywords (0.0.5) syntax_tree (6.1.1) prettier_print (>= 1.2.0) syntax_tree-haml (4.0.3) @@ -218,11 +237,14 @@ DEPENDENCIES bootsnap database_cleaner debug + dotenv-rails pg (~> 1.1) prettier_print + pry puma (~> 5.0) rails (~> 7.0.4, >= 7.0.4.2) rspec-rails + ruby-openai syntax_tree syntax_tree-haml syntax_tree-rbs diff --git a/app/services/exercise_recommender_service.rb b/app/services/exercise_recommender_service.rb new file mode 100644 index 0000000..59071f5 --- /dev/null +++ b/app/services/exercise_recommender_service.rb @@ -0,0 +1,38 @@ +class ExerciseRecommenderService + attr_reader :client + + def initialize + @client = OpenAI::Client.new + end + + def recommend_next_exercise(current_exercises) + response = + @client.chat( + parameters: { + model: "gpt-3.5-turbo", + messages: messages(current_exercises) + } + ) + + body = JSON.parse(response["choices"][0]["message"]["content"]) + + return body["name"], body["instructions"] + end + + def messages(current_exercises) + exercise_names = current_exercises.pluck(:name).join(", ") + + return [ + { + "role" => "system", + "content" => + "You will be provided a list of exercise names. Your task is to suggest the next exercise to do. Make the response in the JSON format: {\"name\": \"exercise name\", \"instructions\": \"exercise instructions\"}." + }, + { + "role" => "user", + "content" => + "My current exercises are: #{exercise_names}. What should my next exercise be?" + } + ] + end +end diff --git a/config/initializers/openai.rb b/config/initializers/openai.rb new file mode 100644 index 0000000..17f4af7 --- /dev/null +++ b/config/initializers/openai.rb @@ -0,0 +1,3 @@ +OpenAI.configure do |config| + config.access_token = ENV.fetch("OPENAI_ACCESS_TOKEN") +end diff --git a/package-lock.json b/package-lock.json index 4c60401..00e3e16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "exercise-tracker", + "name": "Exercise-tracker", "lockfileVersion": 2, "requires": true, "packages": {