mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-09 16:46:11 +00:00
Currently, it’s unclear whether an FAQ item is generated from a document, derived from a conversation, or added manually. This PR resolves the issue by providing visibility into the source of each FAQ. Users can now see whether an FAQ was generated or manually added and, if applicable, by whom. - Move the document_id to a polymorphic relation (documentable). - Updated the APIs to accommodate the change. - Update the service to add corresponding references. - Updated the specs. <img width="1007" alt="Screenshot 2025-01-15 at 11 27 56 PM" src="https://github.com/user-attachments/assets/7d58f798-19c0-4407-b3e2-748a919d14af" /> --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
68 lines
2.2 KiB
Ruby
68 lines
2.2 KiB
Ruby
# == Schema Information
|
|
#
|
|
# Table name: captain_assistant_responses
|
|
#
|
|
# id :bigint not null, primary key
|
|
# answer :text not null
|
|
# documentable_type :string
|
|
# embedding :vector(1536)
|
|
# question :string not null
|
|
# status :integer default("approved"), not null
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
# account_id :bigint not null
|
|
# assistant_id :bigint not null
|
|
# documentable_id :bigint
|
|
#
|
|
# Indexes
|
|
#
|
|
# idx_cap_asst_resp_on_documentable (documentable_id,documentable_type)
|
|
# index_captain_assistant_responses_on_account_id (account_id)
|
|
# index_captain_assistant_responses_on_assistant_id (assistant_id)
|
|
# index_captain_assistant_responses_on_status (status)
|
|
# vector_idx_knowledge_entries_embedding (embedding) USING ivfflat
|
|
#
|
|
class Captain::AssistantResponse < ApplicationRecord
|
|
self.table_name = 'captain_assistant_responses'
|
|
|
|
belongs_to :assistant, class_name: 'Captain::Assistant'
|
|
belongs_to :account
|
|
belongs_to :documentable, polymorphic: true, optional: true
|
|
has_neighbors :embedding, normalize: true
|
|
|
|
validates :question, presence: true
|
|
validates :answer, presence: true
|
|
|
|
before_validation :ensure_account
|
|
before_validation :ensure_status
|
|
after_commit :update_response_embedding
|
|
|
|
scope :ordered, -> { order(created_at: :desc) }
|
|
scope :by_account, ->(account_id) { where(account_id: account_id) }
|
|
scope :by_assistant, ->(assistant_id) { where(assistant_id: assistant_id) }
|
|
scope :with_document, ->(document_id) { where(document_id: document_id) }
|
|
|
|
enum status: { pending: 0, approved: 1 }
|
|
|
|
def self.search(query)
|
|
embedding = Captain::Llm::EmbeddingService.new.get_embedding(query)
|
|
nearest_neighbors(:embedding, embedding, distance: 'cosine').limit(5)
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_status
|
|
self.status ||= :approved
|
|
end
|
|
|
|
def ensure_account
|
|
self.account = assistant&.account
|
|
end
|
|
|
|
def update_response_embedding
|
|
return unless saved_change_to_question? || saved_change_to_answer? || embedding.nil?
|
|
|
|
Captain::Llm::UpdateEmbeddingJob.perform_later(self, "#{question}: #{answer}")
|
|
end
|
|
end
|