Add support for search_articles
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#
|
||||
class Article < ApplicationRecord
|
||||
include PgSearch::Model
|
||||
include LlmFormattable
|
||||
|
||||
has_many :associated_articles,
|
||||
class_name: :Article,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
class LlmFormatter::ArticleLlmFormatter
|
||||
attr_reader :article
|
||||
|
||||
def initialize(article)
|
||||
@article = article
|
||||
end
|
||||
|
||||
def format(*)
|
||||
<<~TEXT
|
||||
Title: #{article.title}
|
||||
ID: #{article.id}
|
||||
Status: #{article.status}
|
||||
Category: #{article.category&.name || 'Uncategorized'}
|
||||
Author: #{article.author&.name}
|
||||
Views: #{article.views}
|
||||
Created At: #{article.created_at}
|
||||
Updated At: #{article.updated_at}
|
||||
Content:
|
||||
#{article.content}
|
||||
TEXT
|
||||
end
|
||||
end
|
||||
@@ -21,10 +21,12 @@ class Captain::Copilot::ChatService < Llm::BaseOpenAiService
|
||||
end
|
||||
|
||||
def register_tools
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::GetConversationService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::SearchConversationService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::GetArticleService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::GetContactService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::GetConversationService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::SearchArticleService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::SearchContactService)
|
||||
@tool_registry.register_tool(Captain::Tools::Copilot::SearchConversationService)
|
||||
end
|
||||
|
||||
def build_initial_messages(config)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
class Captain::Tools::Copilot::GetArticleService < Captain::Tools::BaseService
|
||||
def name
|
||||
'get_article'
|
||||
end
|
||||
|
||||
def description
|
||||
'Get details of an article including its content and metadata'
|
||||
end
|
||||
|
||||
def parameters
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
article_id: {
|
||||
type: 'number',
|
||||
description: 'The ID of the article to retrieve'
|
||||
},
|
||||
account_id: {
|
||||
type: 'number',
|
||||
description: 'The ID of the account the article belongs to'
|
||||
}
|
||||
},
|
||||
required: %w[article_id account_id]
|
||||
}
|
||||
end
|
||||
|
||||
def execute(arguments)
|
||||
article_id = arguments['article_id']
|
||||
account_id = arguments['account_id']
|
||||
|
||||
Rails.logger.info { "[CAPTAIN][GetArticle] #{article_id}, #{account_id}" }
|
||||
|
||||
return 'Missing required parameters' if article_id.blank? || account_id.blank?
|
||||
|
||||
article = Article.find_by(id: article_id, account_id: account_id)
|
||||
return 'Article not found' if article.nil?
|
||||
|
||||
article.to_llm_text
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
class Captain::Tools::Copilot::SearchArticleService < Captain::Tools::BaseService
|
||||
def name
|
||||
'search_article'
|
||||
end
|
||||
|
||||
def description
|
||||
'Search for articles based on query parameters'
|
||||
end
|
||||
|
||||
def parameters
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
account_id: {
|
||||
type: 'number',
|
||||
description: 'The ID of the account to search articles in'
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
description: 'Search articles by title or content (partial match)'
|
||||
},
|
||||
category_id: {
|
||||
type: 'number',
|
||||
description: 'Filter articles by category ID'
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
enum: %w[draft published archived],
|
||||
description: 'Filter articles by status'
|
||||
}
|
||||
},
|
||||
required: %w[account_id]
|
||||
}
|
||||
end
|
||||
|
||||
def execute(arguments)
|
||||
account_id = arguments['account_id']
|
||||
query = arguments['query']
|
||||
category_id = arguments['category_id']
|
||||
status = arguments['status']
|
||||
|
||||
Rails.logger.info do
|
||||
"[CAPTAIN][SearchArticle] account_id: #{account_id}, query: #{query}, category_id: #{category_id}, status: #{status}"
|
||||
end
|
||||
|
||||
return 'Missing required parameters' if account_id.blank?
|
||||
|
||||
articles = Article.where(account_id: account_id)
|
||||
articles = articles.where('title ILIKE :query OR content ILIKE :query', query: "%#{query}%") if query.present?
|
||||
articles = articles.where(category_id: category_id) if category_id.present?
|
||||
articles = articles.where(status: status) if status.present?
|
||||
|
||||
return 'No articles found' unless articles.exists?
|
||||
|
||||
<<~RESPONSE
|
||||
Total number of articles: #{articles.count}
|
||||
#{articles.map(&:to_llm_text).join("\n---\n")}
|
||||
RESPONSE
|
||||
end
|
||||
end
|
||||
@@ -47,17 +47,14 @@ class Captain::Tools::Copilot::SearchContactService < Captain::Tools::BaseServic
|
||||
contacts = Contact.where(account_id: account_id)
|
||||
contacts = contacts.where(email: email) if email.present?
|
||||
contacts = contacts.where(phone_number: phone_number) if phone_number.present?
|
||||
contacts = contacts.where('name ILIKE ?', "%#{name}%") if name.present?
|
||||
contacts = contacts.where('LOWER(name) ILIKE ?', "%#{name.downcase}%") if name.present?
|
||||
|
||||
return 'No contacts found' unless contacts.exists?
|
||||
|
||||
<<~RESPONSE
|
||||
Total number of contacts: #{contacts.count}
|
||||
#{
|
||||
contacts.map do |contact|
|
||||
contact.to_llm_text
|
||||
end.join("\n---\n")
|
||||
}
|
||||
|
||||
#{contacts.map(&:to_llm_text).join("\n---\n")}
|
||||
RESPONSE
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user