mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-06-30 03:22:17 +00:00
is update adds logging for changes made in the AI admin panel. When making configuration changes to Embeddings, LLMs, Personas, Tools, or Spam that aren't site setting related, changes will now be logged in Admin > Logs & Screening. This will help admins debug issues related to AI. In this update a helper lib is created called `AiStaffActionLogger` which can be easily used in the future to add logging support for any other admin config we need logged for AI.
168 lines
4.5 KiB
Ruby
168 lines
4.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DiscourseAi
|
|
module Admin
|
|
class AiToolsController < ::Admin::AdminController
|
|
requires_plugin ::DiscourseAi::PLUGIN_NAME
|
|
|
|
before_action :find_ai_tool, only: %i[test edit update destroy]
|
|
|
|
def index
|
|
ai_tools = AiTool.all
|
|
render_serialized({ ai_tools: ai_tools }, AiCustomToolListSerializer, root: false)
|
|
end
|
|
|
|
def new
|
|
end
|
|
|
|
def edit
|
|
render_serialized(@ai_tool, AiCustomToolSerializer)
|
|
end
|
|
|
|
def create
|
|
ai_tool = AiTool.new(ai_tool_params)
|
|
ai_tool.created_by_id = current_user.id
|
|
|
|
if ai_tool.save
|
|
RagDocumentFragment.link_target_and_uploads(ai_tool, attached_upload_ids)
|
|
log_ai_tool_creation(ai_tool)
|
|
render_serialized(ai_tool, AiCustomToolSerializer, status: :created)
|
|
else
|
|
render_json_error ai_tool
|
|
end
|
|
end
|
|
|
|
def update
|
|
initial_attributes = @ai_tool.attributes.dup
|
|
|
|
if @ai_tool.update(ai_tool_params)
|
|
RagDocumentFragment.update_target_uploads(@ai_tool, attached_upload_ids)
|
|
log_ai_tool_update(@ai_tool, initial_attributes)
|
|
render_serialized(@ai_tool, AiCustomToolSerializer)
|
|
else
|
|
render_json_error @ai_tool
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
tool_logger_details = {
|
|
tool_id: @ai_tool.id,
|
|
name: @ai_tool.name,
|
|
tool_name: @ai_tool.tool_name,
|
|
subject: @ai_tool.name,
|
|
}
|
|
|
|
if @ai_tool.destroy
|
|
log_ai_tool_deletion(tool_logger_details)
|
|
head :no_content
|
|
else
|
|
render_json_error @ai_tool
|
|
end
|
|
end
|
|
|
|
def test
|
|
@ai_tool.assign_attributes(ai_tool_params) if params[:ai_tool]
|
|
parameters = params[:parameters].to_unsafe_h
|
|
|
|
# we need an llm so we have a tokenizer
|
|
# but will do without if none is available
|
|
llm = LlmModel.first&.to_llm
|
|
runner = @ai_tool.runner(parameters, llm: llm, bot_user: current_user)
|
|
result = runner.invoke
|
|
|
|
if result.is_a?(Hash) && result[:error]
|
|
render_json_error result[:error]
|
|
else
|
|
render json: { output: result }
|
|
end
|
|
rescue ActiveRecord::RecordNotFound => e
|
|
render_json_error e.message, status: 400
|
|
rescue => e
|
|
render_json_error "Error executing the tool: #{e.message}", status: 400
|
|
end
|
|
|
|
private
|
|
|
|
def attached_upload_ids
|
|
params[:ai_tool][:rag_uploads].to_a.map { |h| h[:id] }
|
|
end
|
|
|
|
def find_ai_tool
|
|
@ai_tool = AiTool.find(params[:id].to_i)
|
|
end
|
|
|
|
def ai_tool_params
|
|
params
|
|
.require(:ai_tool)
|
|
.permit(
|
|
:name,
|
|
:tool_name,
|
|
:description,
|
|
:script,
|
|
:summary,
|
|
:rag_chunk_tokens,
|
|
:rag_chunk_overlap_tokens,
|
|
:rag_llm_model_id,
|
|
rag_uploads: [:id],
|
|
parameters: [:name, :type, :description, :required, enum: []],
|
|
)
|
|
.except(:rag_uploads)
|
|
end
|
|
|
|
def ai_tool_logger_fields
|
|
{
|
|
name: {
|
|
},
|
|
tool_name: {
|
|
},
|
|
description: {
|
|
},
|
|
summary: {
|
|
},
|
|
enabled: {
|
|
},
|
|
rag_chunk_tokens: {
|
|
},
|
|
rag_chunk_overlap_tokens: {
|
|
},
|
|
rag_llm_model_id: {
|
|
},
|
|
script: {
|
|
type: :large_text,
|
|
},
|
|
parameters: {
|
|
type: :large_text,
|
|
},
|
|
}
|
|
end
|
|
|
|
def log_ai_tool_creation(ai_tool)
|
|
logger = DiscourseAi::Utils::AiStaffActionLogger.new(current_user)
|
|
|
|
entity_details = { tool_id: ai_tool.id, subject: ai_tool.name }
|
|
entity_details[:parameter_count] = ai_tool.parameters.size if ai_tool.parameters.present?
|
|
|
|
logger.log_creation("tool", ai_tool, ai_tool_logger_fields, entity_details)
|
|
end
|
|
|
|
def log_ai_tool_update(ai_tool, initial_attributes)
|
|
logger = DiscourseAi::Utils::AiStaffActionLogger.new(current_user)
|
|
entity_details = { tool_id: ai_tool.id, subject: ai_tool.name }
|
|
|
|
logger.log_update(
|
|
"tool",
|
|
ai_tool,
|
|
initial_attributes,
|
|
ai_tool_logger_fields,
|
|
entity_details,
|
|
)
|
|
end
|
|
|
|
def log_ai_tool_deletion(tool_details)
|
|
logger = DiscourseAi::Utils::AiStaffActionLogger.new(current_user)
|
|
logger.log_deletion("tool", tool_details)
|
|
end
|
|
end
|
|
end
|
|
end
|