| 
									
										
										
										
											2023-03-15 17:21:45 -03:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module DiscourseAi | 
					
						
							|  |  |  |   module Embeddings | 
					
						
							|  |  |  |     class EntryPoint | 
					
						
							|  |  |  |       def load_files | 
					
						
							| 
									
										
										
										
											2023-07-13 12:41:36 -03:00
										 |  |  |         require_relative "models/base" | 
					
						
							|  |  |  |         require_relative "models/all_mpnet_base_v2" | 
					
						
							|  |  |  |         require_relative "models/text_embedding_ada_002" | 
					
						
							| 
									
										
										
										
											2023-07-27 15:50:03 -03:00
										 |  |  |         require_relative "models/multilingual_e5_large" | 
					
						
							| 
									
										
										
										
											2023-07-13 12:41:36 -03:00
										 |  |  |         require_relative "strategies/truncation" | 
					
						
							|  |  |  |         require_relative "manager" | 
					
						
							| 
									
										
										
										
											2023-03-15 17:21:45 -03:00
										 |  |  |         require_relative "jobs/regular/generate_embeddings" | 
					
						
							| 
									
										
										
										
											2023-03-31 11:04:34 +11:00
										 |  |  |         require_relative "semantic_related" | 
					
						
							| 
									
										
										
										
											2023-03-31 15:29:56 -03:00
										 |  |  |         require_relative "semantic_search" | 
					
						
							| 
									
										
										
										
											2023-03-15 17:21:45 -03:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def inject_into(plugin) | 
					
						
							| 
									
										
										
										
											2023-07-31 18:33:37 -03:00
										 |  |  |         # Include random topics in the suggested list *only* if there are no related topics. | 
					
						
							|  |  |  |         plugin.register_modifier( | 
					
						
							|  |  |  |           :topic_view_suggested_topics_options, | 
					
						
							|  |  |  |         ) do |suggested_options, topic_view| | 
					
						
							|  |  |  |           related_topics = topic_view.related_topics | 
					
						
							|  |  |  |           include_random = related_topics.nil? || related_topics.length == 0
 | 
					
						
							|  |  |  |           suggested_options.merge(include_random: include_random) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Query and serialize related topics. | 
					
						
							| 
									
										
										
										
											2023-03-31 09:07:22 +11:00
										 |  |  |         plugin.add_to_class(:topic_view, :related_topics) do | 
					
						
							| 
									
										
										
										
											2023-03-31 11:04:34 +11:00
										 |  |  |           if topic.private_message? || !SiteSetting.ai_embeddings_semantic_related_topics_enabled | 
					
						
							| 
									
										
										
										
											2023-03-31 09:07:22 +11:00
										 |  |  |             return nil | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-02 16:58:09 -03:00
										 |  |  |           @related_topics ||= TopicQuery.new(@user).list_semantic_related_topics(topic).topics | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         plugin.add_to_class(:topic_query, :list_semantic_related_topics) do |topic| | 
					
						
							|  |  |  |           query_opts = { | 
					
						
							|  |  |  |             skip_ordering: true, | 
					
						
							|  |  |  |             per_page: SiteSetting.ai_embeddings_semantic_related_topics, | 
					
						
							|  |  |  |             unordered: true, | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if !SiteSetting.ai_embeddings_semantic_related_include_closed_topics | 
					
						
							|  |  |  |             query_opts[:status] = "open" | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           create_list(:semantic_related, query_opts) do |topics| | 
					
						
							|  |  |  |             candidate_ids = DiscourseAi::Embeddings::SemanticRelated.related_topic_ids_for(topic) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             topics | 
					
						
							|  |  |  |               .where.not(id: topic.id) | 
					
						
							|  |  |  |               .where(id: candidate_ids) | 
					
						
							|  |  |  |               .order("array_position(ARRAY#{candidate_ids}, topics.id)") # array_position forces the order of the topics to be preserved | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2023-03-31 09:07:22 +11:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         %i[topic_view TopicViewPosts].each do |serializer| | 
					
						
							| 
									
										
										
										
											2023-04-24 16:07:17 +01:00
										 |  |  |           plugin.add_to_serializer( | 
					
						
							|  |  |  |             serializer, | 
					
						
							|  |  |  |             :related_topics, | 
					
						
							|  |  |  |             include_condition: -> { SiteSetting.ai_embeddings_semantic_related_topics_enabled }, | 
					
						
							|  |  |  |           ) do | 
					
						
							| 
									
										
										
										
											2023-03-31 11:04:34 +11:00
										 |  |  |             if object.next_page.nil? && !object.topic.private_message? | 
					
						
							| 
									
										
										
										
											2023-03-31 09:07:22 +11:00
										 |  |  |               object.related_topics.map do |t| | 
					
						
							|  |  |  |                 SuggestedTopicSerializer.new(t, scope: scope, root: false) | 
					
						
							|  |  |  |               end | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-31 18:33:37 -03:00
										 |  |  |         # embeddings generation. | 
					
						
							| 
									
										
										
										
											2023-03-15 17:21:45 -03:00
										 |  |  |         callback = | 
					
						
							|  |  |  |           Proc.new do |topic| | 
					
						
							|  |  |  |             if SiteSetting.ai_embeddings_enabled | 
					
						
							|  |  |  |               Jobs.enqueue(:generate_embeddings, topic_id: topic.id) | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         plugin.on(:topic_created, &callback) | 
					
						
							|  |  |  |         plugin.on(:topic_edited, &callback) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |