Files
leadchat/enterprise/app/models/captain/assistant_response.rb
Pranav 6096932f76 feat: Add a review step for FAQs generated from conversations before using it (#10693)
This PR introduces a review step for generated FAQs, allowing a human to
validate and approve them before use in customer interactions. While
hallucinations are minimal, this step ensures accurate and reliable FAQs
for Captain to use during LLM calls when responding to customers.

- Added a status field for the FAQ
- Allow the filter on the UI.
<img width="1072" alt="Screenshot 2025-01-15 at 6 39 26 PM"
src="https://github.com/user-attachments/assets/81dfc038-31e9-40e6-8a09-586ebc4e8384"
/>
2025-01-16 09:54:34 +05:30

67 lines
2.1 KiB
Ruby

# == Schema Information
#
# Table name: captain_assistant_responses
#
# id :bigint not null, primary key
# answer :text not null
# 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
# document_id :bigint
#
# Indexes
#
# index_captain_assistant_responses_on_account_id (account_id)
# index_captain_assistant_responses_on_assistant_id (assistant_id)
# index_captain_assistant_responses_on_document_id (document_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 :document, optional: true, class_name: 'Captain::Document'
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