feat(ee): Add Captain features (#10665)
Migration Guide: https://chwt.app/v4/migration This PR imports all the work related to Captain into the EE codebase. Captain represents the AI-based features in Chatwoot and includes the following key components: - Assistant: An assistant has a persona, the product it would be trained on. At the moment, the data at which it is trained is from websites. Future integrations on Notion documents, PDF etc. This PR enables connecting an assistant to an inbox. The assistant would run the conversation every time before transferring it to an agent. - Copilot for Agents: When an agent is supporting a customer, we will be able to offer additional help to lookup some data or fetch information from integrations etc via copilot. - Conversation FAQ generator: When a conversation is resolved, the Captain integration would identify questions which were not in the knowledge base. - CRM memory: Learns from the conversations and identifies important information about the contact. --------- Co-authored-by: Vishnu Narayanan <vishnu@chatwoot.com> Co-authored-by: Sojan <sojan@pepalo.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
class Api::V1::Accounts::Captain::AssistantResponsesController < Api::V1::Accounts::BaseController
|
||||
before_action :current_account
|
||||
before_action -> { check_authorization(Captain::Assistant) }
|
||||
|
||||
before_action :set_current_page, only: [:index]
|
||||
before_action :set_assistant, only: [:create]
|
||||
before_action :set_responses, except: [:create]
|
||||
before_action :set_response, only: [:show, :update, :destroy]
|
||||
|
||||
RESULTS_PER_PAGE = 25
|
||||
|
||||
def index
|
||||
base_query = @responses
|
||||
base_query = base_query.where(assistant_id: permitted_params[:assistant_id]) if permitted_params[:assistant_id].present?
|
||||
base_query = base_query.where(document_id: permitted_params[:document_id]) if permitted_params[:document_id].present?
|
||||
|
||||
@responses_count = base_query.count
|
||||
|
||||
@responses = base_query.page(@current_page).per(RESULTS_PER_PAGE)
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
def create
|
||||
@response = Current.account.captain_assistant_responses.new(response_params)
|
||||
@response.save!
|
||||
end
|
||||
|
||||
def update
|
||||
@response.update!(response_params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@response.destroy
|
||||
head :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_assistant
|
||||
@assistant = Current.account.captain_assistants.find_by(id: params[:assistant_id])
|
||||
end
|
||||
|
||||
def set_responses
|
||||
@responses = Current.account.captain_assistant_responses.includes(:assistant, :document).ordered
|
||||
end
|
||||
|
||||
def set_response
|
||||
@response = @responses.find(permitted_params[:id])
|
||||
end
|
||||
|
||||
def set_current_page
|
||||
@current_page = permitted_params[:page] || 1
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
params.permit(:id, :assistant_id, :page, :document_id, :account_id)
|
||||
end
|
||||
|
||||
def response_params
|
||||
params.require(:assistant_response).permit(
|
||||
:question,
|
||||
:answer,
|
||||
:document_id,
|
||||
:assistant_id
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::BaseController
|
||||
before_action :current_account
|
||||
before_action -> { check_authorization(Captain::Assistant) }
|
||||
|
||||
before_action :set_assistant, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
@assistants = account_assistants.ordered
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
def create
|
||||
@assistant = account_assistants.create!(assistant_params)
|
||||
end
|
||||
|
||||
def update
|
||||
@assistant.update!(assistant_params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@assistant.destroy
|
||||
head :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_assistant
|
||||
@assistant = account_assistants.find(params[:id])
|
||||
end
|
||||
|
||||
def account_assistants
|
||||
@account_assistants ||= Captain::Assistant.for_account(Current.account.id)
|
||||
end
|
||||
|
||||
def assistant_params
|
||||
params.require(:assistant).permit(:name, :description, config: [:product_name, :feature_faq, :feature_memory])
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,58 @@
|
||||
class Api::V1::Accounts::Captain::DocumentsController < Api::V1::Accounts::BaseController
|
||||
before_action :current_account
|
||||
before_action -> { check_authorization(Captain::Assistant) }
|
||||
|
||||
before_action :set_current_page, only: [:index]
|
||||
before_action :set_documents, except: [:create]
|
||||
before_action :set_document, only: [:show, :destroy]
|
||||
before_action :set_assistant, only: [:create]
|
||||
RESULTS_PER_PAGE = 25
|
||||
|
||||
def index
|
||||
base_query = @documents
|
||||
base_query = base_query.where(assistant_id: permitted_params[:assistant_id]) if permitted_params[:assistant_id].present?
|
||||
|
||||
@documents_count = base_query.count
|
||||
@documents = base_query.page(@current_page).per(RESULTS_PER_PAGE)
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
def create
|
||||
return render_could_not_create_error('Missing Assistant') if @assistant.nil?
|
||||
|
||||
@document = @assistant.documents.build(document_params)
|
||||
@document.save!
|
||||
end
|
||||
|
||||
def destroy
|
||||
@document.destroy
|
||||
head :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_documents
|
||||
@documents = Current.account.captain_documents.includes(:assistant).ordered
|
||||
end
|
||||
|
||||
def set_document
|
||||
@document = @documents.find(permitted_params[:id])
|
||||
end
|
||||
|
||||
def set_assistant
|
||||
@assistant = Current.account.captain_assistants.find_by(id: document_params[:assistant_id])
|
||||
end
|
||||
|
||||
def set_current_page
|
||||
@current_page = permitted_params[:page] || 1
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
params.permit(:assistant_id, :page, :id, :account_id)
|
||||
end
|
||||
|
||||
def document_params
|
||||
params.require(:document).permit(:name, :external_link, :assistant_id)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
class Api::V1::Accounts::Captain::InboxesController < Api::V1::Accounts::BaseController
|
||||
before_action :current_account
|
||||
before_action -> { check_authorization(Captain::Assistant) }
|
||||
|
||||
before_action :set_assistant
|
||||
def index
|
||||
@inboxes = @assistant.inboxes
|
||||
end
|
||||
|
||||
def create
|
||||
inbox = Current.account.inboxes.find(assistant_params[:inbox_id])
|
||||
@captain_inbox = @assistant.captain_inboxes.build(inbox: inbox)
|
||||
@captain_inbox.save!
|
||||
end
|
||||
|
||||
def destroy
|
||||
@captain_inbox = @assistant.captain_inboxes.find_by!(inbox_id: permitted_params[:inbox_id])
|
||||
@captain_inbox.destroy!
|
||||
head :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_assistant
|
||||
@assistant = account_assistants.find(permitted_params[:assistant_id])
|
||||
end
|
||||
|
||||
def account_assistants
|
||||
@account_assistants ||= Current.account.captain_assistants
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
params.permit(:assistant_id, :id, :account_id, :inbox_id)
|
||||
end
|
||||
|
||||
def assistant_params
|
||||
params.require(:inbox).permit(:inbox_id)
|
||||
end
|
||||
end
|
||||
@@ -1,34 +0,0 @@
|
||||
class Api::V1::Accounts::ResponseSourcesController < Api::V1::Accounts::BaseController
|
||||
before_action :current_account
|
||||
before_action :check_authorization
|
||||
before_action :find_response_source, only: [:add_document, :remove_document]
|
||||
|
||||
def parse
|
||||
links = PageCrawlerService.new(params[:link]).page_links
|
||||
render json: { links: links }
|
||||
end
|
||||
|
||||
def create
|
||||
@response_source = Current.account.response_sources.new(response_source_params)
|
||||
@response_source.save!
|
||||
end
|
||||
|
||||
def add_document
|
||||
@response_source.response_documents.create!(document_link: params[:document_link])
|
||||
end
|
||||
|
||||
def remove_document
|
||||
@response_source.response_documents.find(params[:document_id]).destroy!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_response_source
|
||||
@response_source = Current.account.response_sources.find(params[:id])
|
||||
end
|
||||
|
||||
def response_source_params
|
||||
params.require(:response_source).permit(:name, :source_link,
|
||||
response_documents_attributes: [:document_link])
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user