diff --git a/Gemfile b/Gemfile index c7438135..63c9929a 100644 --- a/Gemfile +++ b/Gemfile @@ -118,6 +118,9 @@ gem 'image_processing', '~> 1.2' gem 'ruby-vips', '>= 2.1.0' gem 'aws-sdk-s3', require: false +# Octokig [https://github.com/octokit/octokit.rb] +# Mostly used to import openAI prompts from GitHub repo using the import_prompts.rake task +gem 'octokit', '~> 6.1.1' # Generate QRCode [https://github.com/whomwah/rqrcode] gem 'rqrcode', '~> 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index c80c8297..99c397e8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/faker-ruby/faker.git - revision: 4558f1bb9bb80c13b2ff0e3fcad78ac02c7f5515 + revision: a342e3e2200ca7862ef30e8e54bddc215dbd1ff8 specs: faker (3.2.0) i18n (>= 1.8.11, < 2) @@ -158,7 +158,7 @@ GEM down (5.4.1) addressable (~> 2.8) erubi (1.12.0) - faraday (2.7.8) + faraday (2.7.9) faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) faraday-multipart (1.0.4) @@ -170,8 +170,8 @@ GEM rake globalid (1.1.0) activesupport (>= 5.0) - groupdate (6.2.1) - activesupport (>= 5.2) + groupdate (6.3.0) + activesupport (>= 6.1) hashie (5.0.0) honeybadger (5.2.1) htmlentities (4.3.4) @@ -191,7 +191,7 @@ GEM invisible_captcha (2.1.0) rails (>= 5.2) io-console (0.6.0) - irb (1.7.0) + irb (1.7.1) reline (>= 0.3.0) jbuilder (2.11.5) actionview (>= 5.0.0) @@ -249,6 +249,9 @@ GEM rack (>= 1.2, < 4) snaky_hash (~> 2.0) version_gem (~> 1.1) + octokit (6.1.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) oj (3.15.0) omniauth (2.1.1) hashie (>= 3.4.6) @@ -302,8 +305,9 @@ GEM activesupport (= 7.0.6) bundler (>= 1.15.0) railties (= 7.0.6) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.1.1) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) rails-html-sanitizer (1.6.0) loofah (~> 2.21) @@ -334,7 +338,7 @@ GEM chunky_png (~> 1.0) rqrcode_core (~> 1.0) rqrcode_core (1.2.0) - rubocop (1.53.1) + rubocop (1.54.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) @@ -361,6 +365,9 @@ GEM ruby_http_client (3.5.5) rubyzip (2.3.2) safely_block (0.4.0) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) selenium-webdriver (4.10.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -467,6 +474,7 @@ DEPENDENCIES merit nokogiri (~> 1.15.0) noticed (~> 1.5) + octokit (~> 6.1.1) oj (~> 3.15.0) omniauth (~> 2.1.0) omniauth-google-oauth2 (~> 1.1.1) diff --git a/app/models/prompt.rb b/app/models/prompt.rb index 623a6065..3d56de9b 100644 --- a/app/models/prompt.rb +++ b/app/models/prompt.rb @@ -3,11 +3,12 @@ # Table name: prompts # # id :uuid not null, primary key -# function :string +# function_call :string +# functions :text # label :string(50) not null -# model :string default("gpt-3.5"), not null -# prompt :text not null -# title :string(50) not null +# messages :text not null +# model :string +# title :string(150) not null # created_at :datetime not null # updated_at :datetime not null # organization_id :uuid @@ -19,13 +20,28 @@ # index_prompts_on_organization_id (organization_id) # class Prompt < ApplicationRecord - validates :label, presence: true, length: { minimum: 3, maximum: 50 }, uniqueness: { case_sensitive: false } - validates :title, presence: true, length: { minimum: 3, maximum: 50 } + validates :label, presence: true, length: { minimum: 3, maximum: 50 }, uniqueness: { case_sensitive: false } + validates :title, presence: true, length: { minimum: 3, maximum: 150 } + validates :messages, presence: true # Prompts table is used to saved prompts that are used by AI to extract critical information. # labels is the name of the prompt # title is a short description of the prompts - # prompt is the prompt ;-) - # some organization may require specific prompts + # message is formatted as openAI message + + # Retrieves the messages with dynamic parameter replacement + # + # @param params [Hash] The parameters used to replace placeholders in the message + # @return [String] The message with placeholders replaced by corresponding parameter values + def get_messages(params = {}) + replaced_messages = messages.dup + + params.each do |key, value| + escaped_value = value.to_s.gsub(/["\\]/, '\\\\\0') + replaced_messages.gsub!("%{#{key}}", escaped_value) + end + + replaced_messages + end end diff --git a/app/models/topic.rb b/app/models/topic.rb index 05bfca75..c73e4543 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -14,11 +14,12 @@ # # Indexes # -# index_topics_on_event_id (event_id) -# index_topics_on_name (name) -# index_topics_on_question_id (question_id) -# index_topics_on_room_id (room_id) -# index_topics_on_user_id (user_id) +# index_topics_on_event_id (event_id) +# index_topics_on_name (name) +# index_topics_on_question_id (question_id) +# index_topics_on_question_id_and_room_id_and_user_id (question_id,room_id,user_id) UNIQUE +# index_topics_on_room_id (room_id) +# index_topics_on_user_id (user_id) # class Topic < ApplicationRecord end diff --git a/app/services/prompt_retriever_service.rb b/app/services/prompt_retriever_service.rb index cf0fb742..13ef6c35 100644 --- a/app/services/prompt_retriever_service.rb +++ b/app/services/prompt_retriever_service.rb @@ -6,7 +6,7 @@ module PromptRetrieverService # @param label [String] The label of the prompt to retrieve # @param organization_id [String, nil] The organization ID (optional) # @return [Hash, nil] A hash with :title, :prompt, :model, and :function if a prompt is found, nil otherwise - def self.retrieve(label, organization_id = nil) + def self.retrieve(label, organization_id = nil, params = {}) prompt = Prompt.find_by(label: label, organization_id: organization_id) # Fallback in case we have no prompt when passing a label AND an organization_id @@ -16,12 +16,20 @@ def self.retrieve(label, organization_id = nil) return unless prompt - { + result = { title: prompt.title, - prompt: prompt.prompt, + messages: prompt.messages, model: prompt.model, - function: prompt.function || nil + functions: prompt.functions || nil, + function_call: prompt.function_call || nil } + + if params + result[:messages] = prompt.get_messages(params) + end + + result + end end diff --git a/app/sidekiq/event_topics_extraction_job.rb b/app/sidekiq/event_topics_extraction_job.rb new file mode 100644 index 00000000..128289a6 --- /dev/null +++ b/app/sidekiq/event_topics_extraction_job.rb @@ -0,0 +1,16 @@ +class EventTopicsExtractionJob + include Sidekiq::Job + + require "openai" + + def perform(event) + # Initialize an openAI client + client = OpenAI::Client.new + + # Fetch all the questions from an event + + # Aggregate the questions in one document + + # Extract the topics from the questions with openAI + end +end diff --git a/app/sidekiq/question_keywords_extraction_job.rb b/app/sidekiq/question_keywords_extraction_job.rb index 57a0e4dc..b1038b3e 100644 --- a/app/sidekiq/question_keywords_extraction_job.rb +++ b/app/sidekiq/question_keywords_extraction_job.rb @@ -2,6 +2,7 @@ class QuestionKeywordsExtractionJob include Sidekiq::Job require "openai" + require "yaml" require_relative "../services/prompt_retriever_service.rb" def perform(question) @@ -11,20 +12,28 @@ def perform(question) # Parse the question qh = JSON.parse(question) - # Use GTP 4 Chat to extract the relevant keywords from the question - pr = PromptRetrieverService.retrieve("question-keyword-extraction", nil) - puts "## PROMPT ##" - puts pr + question_title = qh.dig("title") + # Use Chat GPT to extract the relevant keywords from the question + pr = PromptRetrieverService.retrieve("question-keyword-extraction", nil, {title: question_title}) + # puts "## PROMPT ##" + # puts pr.inspect + + messages = JSON.parse(pr[:messages]) + + params = { + model: pr[:model], + messages: messages, + temperature: 0.7, + user: qh.dig("user_id") + } + + # puts params + response = client.chat( - parameters: { - model: "gpt-4", - messages: [ - { role: "system", content: pr[:prompt] }, - { role: "user", content: "Extract keywords from this text:\n\n" + qh.dig("title")} - ], - temperature: 0.7, - user: qh.dig("user_id") - }) + parameters: params + ) + + # puts response keywords = response.dig("choices", 0, "message","content") keywords = keywords.split(", ") keywords.map{ |word| word.strip.chomp(".") } diff --git a/app/sidekiq/question_processing_job.rb b/app/sidekiq/question_processing_job.rb index 53c27827..e49e89d1 100644 --- a/app/sidekiq/question_processing_job.rb +++ b/app/sidekiq/question_processing_job.rb @@ -1,14 +1,21 @@ +# app/sidekiq/question_processing_job.rb class QuestionProcessingJob include Sidekiq::Job def perform(question) - # Extract key elements from the question such as Tone, Keywords - # Topics are extracted via a cron job - - # Extract Tone from the quesstion + # Extract Tone from the question QuestionToneJob.perform_async(question) - - # Extract Keywords from the question - QuestionKeywordsExtractionJob.perform_async(question) + + # Extract the status from the question JSON + question_status = JSON.parse(question)['status'] + + # Check if the question status is not "rejected" + if question_status != "rejected" + # Extract Keywords from the question + QuestionKeywordsExtractionJob.perform_async(question) + + # Extract Topic from the question + QuestionTopicExtractionJob.perform_async(question) + end end end diff --git a/app/sidekiq/question_topic_extraction_job.rb b/app/sidekiq/question_topic_extraction_job.rb new file mode 100644 index 00000000..4241bec0 --- /dev/null +++ b/app/sidekiq/question_topic_extraction_job.rb @@ -0,0 +1,71 @@ +# app/sidekiq/question_topic_extraction_job.rb + +# Description: used to extract the topic covered by a question. + +class QuestionTopicExtractionJob + include Sidekiq::Job + + require "openai" + + def perform(question) + # Initialize an openAI client + client = OpenAI::Client.new + + # Parse the question + qh = JSON.parse(question) + # puts "## Question ##" + # puts qh + + # Extracting key values from the question + room_id = qh.dig("room_id") + question_id = qh.dig("id") + question_title = qh.dig("title") + user_id = qh.dig("user_id") + + # Find the event id + event_id = Room.select(:event_id).find(room_id).event_id + puts "## Event id: #{event_id}" + + # Extracting the topic from the question using openAI + pr = PromptRetrieverService.retrieve("question-topic-extraction", nil, {title: question_title}) + # puts "## PROMPT ##" + # puts pr.inspect + + messages = JSON.parse(pr[:messages]) + + params = { + model: pr[:model], + messages: messages, + temperature: 0.7, + user: qh.dig("user_id") + } + + # puts params + + response = client.chat( + parameters: params + ) + + # puts response + + topics = response.dig("choices", 0, "message","content") + topics = topics.split(", ") + topics.map{ |word| word.strip.chomp(".") } + puts "TOPICS IS ARRAY? #{topics.kind_of?(Array)}" + puts "QUESTION: #{question_title}" + puts "TOPICS AS ARRAY: #{topics}" + if topics.kind_of?(Array) + topics.each do |topic| + param = { + event_id: event_id, + question_id: question_id, + room_id: room_id, + user_id: user_id, + description: "Question: #{question_title}", + name: topic + } + Topic.upsert(param , unique_by: [:question_id, :room_id, :user_id]) + end + end + end +end diff --git a/app/sidekiq/question_topics_extraction_job.rb b/app/sidekiq/question_topics_extraction_job.rb deleted file mode 100644 index aea9130c..00000000 --- a/app/sidekiq/question_topics_extraction_job.rb +++ /dev/null @@ -1,13 +0,0 @@ -class QuestionTopicsExtractionJob - include Sidekiq::Job - - require "openai" - - def perform(question) - # Initialize an openAI client - client = OpenAI::Client.new - - # Parse the question - question = JSON.parse(question) - end -end diff --git a/db/migrate/20230514234427_create_prompts.rb b/db/migrate/20230514234427_create_prompts.rb index efb7881a..80bcd734 100644 --- a/db/migrate/20230514234427_create_prompts.rb +++ b/db/migrate/20230514234427_create_prompts.rb @@ -3,10 +3,11 @@ def change create_table :prompts, id: :uuid do |t| t.uuid :organization_id t.string :label, null: false, limit: 50 - t.string :title, null: false, limit: 50 + t.string :title, null: false, limit: 150 t.string :model - t.text :message, null: false - t.text :function + t.text :messages, null: false + t.text :functions + t.string :function_call t.timestamps end diff --git a/db/migrate/20230623213927_add_columns_to_prompts.rb b/db/migrate/20230623213927_add_columns_to_prompts.rb deleted file mode 100644 index 9381c753..00000000 --- a/db/migrate/20230623213927_add_columns_to_prompts.rb +++ /dev/null @@ -1,9 +0,0 @@ -class AddColumnsToPrompts < ActiveRecord::Migration[7.0] - def change - add_column :prompts, :model, :string, null: false, default: 'gpt-3.5' - add_column :prompts, :function, :string - - # Add an index on the 'model' column - add_index :prompts, :model - end -end diff --git a/db/migrate/20230705005152_add_unique_indexe_to_topics.rb b/db/migrate/20230705005152_add_unique_indexe_to_topics.rb new file mode 100644 index 00000000..76347d11 --- /dev/null +++ b/db/migrate/20230705005152_add_unique_indexe_to_topics.rb @@ -0,0 +1,5 @@ +class AddUniqueIndexeToTopics < ActiveRecord::Migration[7.0] + def change + add_index :topics, [:question_id, :room_id, :user_id], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 48761688..4fe0311b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_06_23_213927) do +ActiveRecord::Schema[7.0].define(version: 2023_07_05_005152) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -334,14 +334,15 @@ end create_table "prompts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "label", limit: 50, null: false - t.string "title", limit: 50, null: false t.uuid "organization_id" - t.text "prompt", null: false + t.string "label", limit: 50, null: false + t.string "title", limit: 150, null: false + t.string "model" + t.text "messages", null: false + t.text "functions" + t.string "function_call" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "model", default: "gpt-3.5", null: false - t.string "function" t.index ["label", "organization_id"], name: "index_prompts_on_label_and_organization_id", unique: true t.index ["model"], name: "index_prompts_on_model" t.index ["organization_id"], name: "index_prompts_on_organization_id" @@ -437,6 +438,7 @@ t.datetime "updated_at", null: false t.index ["event_id"], name: "index_topics_on_event_id" t.index ["name"], name: "index_topics_on_name" + t.index ["question_id", "room_id", "user_id"], name: "index_topics_on_question_id_and_room_id_and_user_id", unique: true t.index ["question_id"], name: "index_topics_on_question_id" t.index ["room_id"], name: "index_topics_on_room_id" t.index ["user_id"], name: "index_topics_on_user_id" diff --git a/lib/tasks/import_prompts.rake b/lib/tasks/import_prompts.rake new file mode 100644 index 00000000..096e7a25 --- /dev/null +++ b/lib/tasks/import_prompts.rake @@ -0,0 +1,75 @@ +require 'octokit' +require 'base64' +require 'json' + +namespace :prompts do + desc "Import prompts from YAML file in a private GitHub repository" + task import: :environment do + # Retrieves prompts from a YAML file in a private GitHub repository and imports them into the database. + # Environment Variables: + # - GITHUB_REPO: The repository name in the format 'username/repo'. + # - FILE_PATH: The path to the YAML file in the repository. + # - GITHUB_TOKEN: Personal access token with repo access for authentication. + + # Usage: + # rake prompts:import + # GITHUB_REPO=your_username/your_repo FILE_PATH=path/to/your_file.yaml GITHUB_TOKEN=your_github_token rake prompts:import + + repository = ENV['GITHUB_REPO'] || raise("Repository not provided. Please set the 'GITHUB_REPO' environment variable.") + file_path = ENV['FILE_PATH'] || raise("File path not provided. Please set the 'FILE_PATH' environment variable.") + github_token = ENV['GITHUB_TOKEN'] || raise("GitHub token not provided. Please set the 'GITHUB_TOKEN' environment variable.") + + client = Octokit::Client.new(access_token: github_token) + file_content = client.contents(repository, path: file_path).content + + # Decode the base64 string + decoded_content = Base64.decode64(file_content) + + # Parse the YAML data + prompts_data = YAML.safe_load(decoded_content) + + prompts_data.each do |prompt_key, prompt_data| + label = prompt_data['label'] + organization_id = prompt_data['organization_id'] + + prompt = Prompt.find_or_initialize_by(label: label, organization_id: organization_id) + + prompt.title = prompt_data['title'] + prompt.model = prompt_data['model'] + prompt.messages = parse_messages(prompt_data['messages']) + prompt.functions = parse_functions(prompt_data['functions']) + prompt.function_call = prompt_data['function_call'] + + if prompt.persisted? + prompt.save + puts "Prompt with label '#{prompt.label}' updated successfully." + else + prompt.save + puts "Prompt with label '#{prompt.label}' imported successfully." + end + end + end + + # Parse the messages field based on the format + def self.parse_messages(messages) + parsed_messages = YAML.safe_load(messages) + parsed_messages.to_json + end + + # Parse the functions field + def self.parse_functions(functions) + return nil if functions.nil? + + parsed_functions = [] + + functions.each do |function| + parsed_functions << { + name: function['name'], + description: function['description'], + parameters: function['parameters'] + } + end + + parsed_functions.to_json + end +end diff --git a/lib/tasks/prompts.rake b/lib/tasks/prompts.rake deleted file mode 100644 index 8f6d033b..00000000 --- a/lib/tasks/prompts.rake +++ /dev/null @@ -1,71 +0,0 @@ -require 'aws-sdk-s3' - -namespace :prompts do - - # Usage: - # Used to upload the a .yml file contaning the prompts to be uploaded to the - # prompts table to a bucket. - # - rake "prompts:upload_with_path[db/seeds/my_prompts.yml]" - desc "Upload and update prompts from a specified .yml file" - task :upload_with_path, [:filepath] => :environment do |_, args| - filepath = args[:filepath] || 'prompts.yml' - - prompts_data = YAML.load_file(Rails.root.join(filepath)) - - # Connect to the DigitalOcean Space - s3_client = Aws::S3::Client.new( - region: 'your_space_region', - access_key_id: 'your_access_key', - secret_access_key: 'your_secret_access_key', - endpoint: 'https://your_space_name.your_space_region.digitaloceanspaces.com' - ) - - # Upload the prompts file to the DigitalOcean Space - s3_client.put_object( - bucket: 'your_space_name', - key: File.basename(filepath), - body: YAML.dump(prompts_data) - ) - - puts "Uploaded prompts from #{filepath} to DigitalOcean Space" - end - - # Usage: - # Used to upload the a .yml file contaning the prompts to be uploaded to the - # prompts table to a bucket. - # - rake "prompts:import_from_space[filepath]" - desc "Create or update prompts from a YAML file" - task :import_from_space, [:filepath] => :environment do |_, args| - filepath = args[:filepath] || 'prompts.yml' - - # Connect to the DigitalOcean Space - s3_client = Aws::S3::Client.new( - region: 'your_space_region', - access_key_id: 'your_access_key', - secret_access_key: 'your_secret_access_key', - endpoint: 'https://your_space_name.your_space_region.digitaloceanspaces.com' - ) - - # Retrieve the prompts file from the DigitalOcean Space - file_response = s3_client.get_object(bucket: 'your_space_name', key: filepath) - prompts_data = YAML.load(file_response.body.read) - - prompts_created = 0 - prompts_updated = 0 - - prompts_data.each do |label, prompt_data| - prompt = Prompt.find_or_initialize_by(label: label) - if prompt.new_record? - prompts_created += 1 - else - prompts_updated += 1 - end - prompt.update(prompt_data) - end - - puts "Prompts imported from DigitalOcean Space: #{filepath}" - puts "Prompts created: #{prompts_created}" - puts "Prompts updated: #{prompts_updated}" - end - -end diff --git a/lib/tasks/update_query_key_insights.rake b/lib/tasks/update_query_key_insights.rake index bd4b17f2..cbc059d3 100644 --- a/lib/tasks/update_query_key_insights.rake +++ b/lib/tasks/update_query_key_insights.rake @@ -26,7 +26,9 @@ namespace :update_query_key_insights do puts("[#{Time.now.utc}] Running update_keywords :: INI#{' (dry_run activated)' if dry_run}") - Question.all.each do |question| + questions = Question.where("keywords = '{}'").not_rejected + + questions.each do |question| puts("Updating keywords for question id: #{question.id} title: #{question.title} #{' (dry_run activated)' if dry_run}") QuestionKeywordsExtractionJob.perform_async(question.to_json) unless dry_run end @@ -34,4 +36,23 @@ namespace :update_query_key_insights do puts("[#{Time.now.utc}] Running update_keywords :: END#{' (dry_run activated)' if dry_run}") end + # Usage: + # - rake update_query_key_insights:update_topic + # - rake "update_query_key_insights:update_topic[false]" + desc 'Update queries with missing topic' + task :update_topic, [:dry_run] => :environment do |_t, args| + dry_run = true unless args[:dry_run] == 'false' + + puts("[#{Time.now.utc}] Running update_keywords :: INI#{' (dry_run activated)' if dry_run}") + + questions = Question.not_rejected + + questions.each do |question| + puts("Updating keywords for question id: #{question.id} title: #{question.title} #{' (dry_run activated)' if dry_run}") + QuestionTopicExtractionJob.perform_async(question.to_json) unless dry_run + end + + puts("[#{Time.now.utc}] Running update_keywords :: END#{' (dry_run activated)' if dry_run}") + end + end diff --git a/package.json b/package.json index 33e7b4f4..d087dcda 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "app", "private": "true", "dependencies": { - "@honeybadger-io/js": "6.1.2", + "@honeybadger-io/js": "6.1.3", "@hotwired/stimulus": "3.2.1", "@hotwired/turbo-rails": "7.3.0", "@rails/actiontext": "7.0.6", @@ -12,7 +12,7 @@ "chartjs-plugin-datalabels": "2.2.0", "chartkick": "5.0.1", "esbuild": "0.18.6", - "flowbite": "1.6.6", + "flowbite": "1.7.0", "flowbite-datepicker": "1.2.2", "js-confetti": "0.11.0", "postcss": "8.4.24", diff --git a/test/fixtures/prompts.yml b/test/fixtures/prompts.yml index c7386fc6..2bed67a8 100644 --- a/test/fixtures/prompts.yml +++ b/test/fixtures/prompts.yml @@ -3,11 +3,12 @@ # Table name: prompts # # id :uuid not null, primary key -# function :string +# function_call :string +# functions :text # label :string(50) not null -# model :string default("gpt-3.5"), not null -# prompt :text not null -# title :string(50) not null +# messages :text not null +# model :string +# title :string(150) not null # created_at :datetime not null # updated_at :datetime not null # organization_id :uuid diff --git a/test/fixtures/topics.yml b/test/fixtures/topics.yml index a0928c32..4cc4b367 100644 --- a/test/fixtures/topics.yml +++ b/test/fixtures/topics.yml @@ -14,11 +14,12 @@ # # Indexes # -# index_topics_on_event_id (event_id) -# index_topics_on_name (name) -# index_topics_on_question_id (question_id) -# index_topics_on_room_id (room_id) -# index_topics_on_user_id (user_id) +# index_topics_on_event_id (event_id) +# index_topics_on_name (name) +# index_topics_on_question_id (question_id) +# index_topics_on_question_id_and_room_id_and_user_id (question_id,room_id,user_id) UNIQUE +# index_topics_on_room_id (room_id) +# index_topics_on_user_id (user_id) # one: diff --git a/test/models/prompt_test.rb b/test/models/prompt_test.rb index bb376c58..45d1442f 100644 --- a/test/models/prompt_test.rb +++ b/test/models/prompt_test.rb @@ -3,11 +3,12 @@ # Table name: prompts # # id :uuid not null, primary key -# function :string +# function_call :string +# functions :text # label :string(50) not null -# model :string default("gpt-3.5"), not null -# prompt :text not null -# title :string(50) not null +# messages :text not null +# model :string +# title :string(150) not null # created_at :datetime not null # updated_at :datetime not null # organization_id :uuid diff --git a/test/models/topic_test.rb b/test/models/topic_test.rb index 4e49d1ad..6a58dad7 100644 --- a/test/models/topic_test.rb +++ b/test/models/topic_test.rb @@ -14,11 +14,12 @@ # # Indexes # -# index_topics_on_event_id (event_id) -# index_topics_on_name (name) -# index_topics_on_question_id (question_id) -# index_topics_on_room_id (room_id) -# index_topics_on_user_id (user_id) +# index_topics_on_event_id (event_id) +# index_topics_on_name (name) +# index_topics_on_question_id (question_id) +# index_topics_on_question_id_and_room_id_and_user_id (question_id,room_id,user_id) UNIQUE +# index_topics_on_room_id (room_id) +# index_topics_on_user_id (user_id) # require "test_helper" diff --git a/test/sidekiq/question_topics_extraction_job_test.rb b/test/sidekiq/question_topic_extraction_job_test.rb similarity index 66% rename from test/sidekiq/question_topics_extraction_job_test.rb rename to test/sidekiq/question_topic_extraction_job_test.rb index 75f89b07..5c44e986 100644 --- a/test/sidekiq/question_topics_extraction_job_test.rb +++ b/test/sidekiq/question_topic_extraction_job_test.rb @@ -1,5 +1,5 @@ require 'test_helper' -class QuestionTopicsExtractionJobTest < Minitest::Test +class QuestionTopicExtractionJobTest < Minitest::Test def test_example skip "add some examples to (or delete) #{__FILE__}" end diff --git a/yarn.lock b/yarn.lock index 281adc26..43c899e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8,9 +8,9 @@ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== "@babel/runtime@^7.21.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" - integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== dependencies: regenerator-runtime "^0.13.11" @@ -131,10 +131,10 @@ dependencies: stacktrace-parser "^0.1.10" -"@honeybadger-io/js@6.1.2": - version "6.1.2" - resolved "https://registry.yarnpkg.com/@honeybadger-io/js/-/js-6.1.2.tgz#7d06fbdead92ea3fa0051763dcd0c196289c0052" - integrity sha512-H/P/gs0AAIXhTe3kFNng5R9GZqCMSn4KMebRVEnyolNRUkUtYDCeWZqiej0w98011oGdv5+JUCDBJFd5tzUxEQ== +"@honeybadger-io/js@6.1.3": + version "6.1.3" + resolved "https://registry.yarnpkg.com/@honeybadger-io/js/-/js-6.1.3.tgz#97bb248969cf48edc61789daa5af87d345dfdd7f" + integrity sha512-Bo/YrOd0KFprRRL0nJaiqpuL/qStHVdOS0+fZsUBEm+W/kA42RIFFzbXvSUHAvkL5+BnQU5W8xE3JLqtPXTSlw== dependencies: "@honeybadger-io/core" "^6.0.0" "@types/aws-lambda" "^8.10.89" @@ -311,9 +311,9 @@ integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== "@types/node@*": - version "20.3.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.2.tgz#fa6a90f2600e052a03c18b8cb3fd83dd4e599898" - integrity sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw== + version "20.3.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.3.tgz#329842940042d2b280897150e023e604d11657d6" + integrity sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw== "@types/qs@*": version "6.9.7" @@ -413,9 +413,9 @@ camelcase-css@^2.0.1: integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503: - version "1.0.30001509" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz#2b7ad5265392d6d2de25cd8776d1ab3899570d14" - integrity sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA== + version "1.0.30001512" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz#7450843fb581c39f290305a83523c7a9ef0d4cb4" + integrity sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw== chart.js@4, chart.js@4.3.0: version "4.3.0" @@ -491,9 +491,9 @@ dlv@^1.1.3: integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== electron-to-chromium@^1.4.431: - version "1.4.446" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.446.tgz#c23fbc7884bfe43088d5eb908a858dbb35ab190b" - integrity sha512-4Gnw7ztEQ/E0eOt5JWfPn9jjeupfUlKoeW5ETKP9nLdWj+4spFoS3Stj19fqlKIaX28UQs0fNX+uKEyoLCBnkw== + version "1.4.450" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz#df232c961ee9bf4e8980f86e96a6e9f291720138" + integrity sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw== esbuild@0.18.6: version "0.18.6" @@ -529,9 +529,9 @@ escalade@^3.1.1: integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== fast-glob@^3.2.12: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + version "3.3.0" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" + integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -560,10 +560,10 @@ flowbite-datepicker@1.2.2: dependencies: flowbite "^1.4.5" -flowbite@1.6.6, flowbite@^1.4.5: - version "1.6.6" - resolved "https://registry.yarnpkg.com/flowbite/-/flowbite-1.6.6.tgz#6c7579fffb6fad270c8471c2898eb7c57fe8ce3e" - integrity sha512-T+IaFikHELo1PBKfT/axDqhAmKQLfm/dxVch2r07TZ+IcKwkorZjzwkVuw3OslTETniRIUf2qQvEhxk3bQCaew== +flowbite@1.7.0, flowbite@^1.4.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/flowbite/-/flowbite-1.7.0.tgz#82359dbd5e3b2b9591eaf18ea929fb77871346b2" + integrity sha512-OTTmnhRgv85Rs+mcMaVU7zB6EvRQs7BaQziyMUsZLRjW9aUpeQyqKjLmxsVMMCdr8isYPCLd6UL7X1IaSVI0WQ== dependencies: "@popperjs/core" "^2.9.3" mini-svg-data-uri "^1.4.3" @@ -666,9 +666,9 @@ is-number@^7.0.0: integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== jiti@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" - integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== + version "1.19.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1" + integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg== js-confetti@0.11.0: version "0.11.0"