Skip to content

WIP: migrate persona to agent #1382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import DiscourseRoute from "discourse/routes/discourse";

export default class AdminPluginsShowDiscourseAiAgentsEdit extends DiscourseRoute {
async model(params) {
const allAgents = this.modelFor(
"adminPlugins.show.discourse-ai-agents"
);
const id = parseInt(params.id, 10);
return allAgents.findBy("id", id);
}

setupController(controller, model) {
super.setupController(controller, model);
controller.set(
"allAgents",
this.modelFor("adminPlugins.show.discourse-ai-agents")
);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { AUTO_GROUPS } from "discourse/lib/constants";
import DiscourseRoute from "discourse/routes/discourse";

export default class AdminPluginsShowDiscourseAiPersonasNew extends DiscourseRoute {
export default class AdminPluginsShowDiscourseAiAgentsNew extends DiscourseRoute {
async model() {
const record = this.store.createRecord("ai-persona");
const record = this.store.createRecord("ai-agent");
record.set("allowed_group_ids", [AUTO_GROUPS.trust_level_0.id]);
record.set("rag_uploads", []);
// these match the defaults on the table
record.set("rag_chunk_tokens", 374);
record.set("rag_chunk_overlap_tokens", 10);
record.set("rag_conversation_chunks", 10);
record.set("allow_personal_messages", true);
record.set("allow_agentl_messages", true);
record.set("tool_details", false);
return record;
}

setupController(controller, model) {
super.setupController(controller, model);
controller.set(
"allPersonas",
this.modelFor("adminPlugins.show.discourse-ai-personas")
"allAgents",
this.modelFor("adminPlugins.show.discourse-ai-agents")
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DiscourseRoute from "discourse/routes/discourse";

export default class DiscourseAiAiAgentsRoute extends DiscourseRoute {
model() {
return this.store.findAll("ai-agent");
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<AiAgentListEditor
@agents={{this.allAgents}}
@currentAgent={{this.model}}
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<AiAgentListEditor @agents={{this.model}} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<AiAgentListEditor
@agents={{this.allAgents}}
@currentAgent={{this.model}}
/>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default RouteTemplate(
const prefix = "discourse_ai.features.list.header";
return [
i18n(`${prefix}.name`),
i18n(`${prefix}.persona`),
i18n(`${prefix}.agent`),
i18n(`${prefix}.groups`),
"",
];
Expand Down Expand Up @@ -75,21 +75,21 @@ export default RouteTemplate(
</span>
</td>
<td
class="d-admin-row__detail ai-feature-list__row-item ai-feature-list__persona"
class="d-admin-row__detail ai-feature-list__row-item ai-feature-list__agent"
>
<DButton
class="btn-flat btn-small ai-feature-list__row-item-persona"
@translatedLabel={{feature.persona.name}}
@route="adminPlugins.show.discourse-ai-personas.edit"
@routeModels={{feature.persona.id}}
class="btn-flat btn-small ai-feature-list__row-item-agent"
@translatedLabel={{feature.agent.name}}
@route="adminPlugins.show.discourse-ai-agents.edit"
@routeModels={{feature.agent.id}}
/>
</td>
<td
class="d-admin-row__detail ai-feature-list__row-item ai-feature-list__groups"
>
{{#if (gt feature.persona.allowed_groups.length 0)}}
{{#if (gt feature.agent.allowed_groups.length 0)}}
<ul class="ai-feature-list__row-item-groups">
{{#each feature.persona.allowed_groups as |group|}}
{{#each feature.agent.allowed_groups as |group|}}
<li>{{group.name}}</li>
{{/each}}
</ul>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<section class="ai-persona-tool-editor__current admin-detail pull-left">
<section class="ai-agent-tool-editor__current admin-detail pull-left">
<AiToolEditor
@tools={{this.allTools}}
@model={{this.model}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<section class="ai-persona-tool-editor__current admin-detail pull-left">
<section class="ai-agent-tool-editor__current admin-detail pull-left">
<AiToolEditor
@tools={{this.allTools}}
@model={{this.model}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

module DiscourseAi
module Admin
class AiPersonasController < ::Admin::AdminController
class AiAgentsController < ::Admin::AdminController
requires_plugin ::DiscourseAi::PLUGIN_NAME

before_action :find_ai_persona, only: %i[edit update destroy create_user]
before_action :find_ai_agent, only: %i[edit update destroy create_user]

def index
ai_personas =
AiPersona.ordered.map do |persona|
ai_agents =
AiAgent.ordered.map do |agent|
# we use a special serializer here cause names and descriptions are
# localized for system personas
LocalizedAiPersonaSerializer.new(persona, root: false)
# localized for system agents
LocalizedAiAgentSerializer.new(agent, root: false)
end
tools =
DiscourseAi::Personas::Persona.all_available_tools.map do |tool|
DiscourseAi::Agents::Agent.all_available_tools.map do |tool|
AiToolSerializer.new(tool, root: false)
end
AiTool
Expand All @@ -36,7 +36,7 @@ def index
allowed_seeded_llm_ids: SiteSetting.ai_bot_allowed_seeded_models_map,
)
render json: {
ai_personas: ai_personas,
ai_agents: ai_agents,
meta: {
tools: tools,
llms: llms,
Expand All @@ -51,64 +51,64 @@ def new
end

def edit
render json: LocalizedAiPersonaSerializer.new(@ai_persona)
render json: LocalizedAiAgentSerializer.new(@ai_agent)
end

def create
ai_persona = AiPersona.new(ai_persona_params.except(:rag_uploads))
if ai_persona.save
RagDocumentFragment.link_target_and_uploads(ai_persona, attached_upload_ids)
ai_agent = AiAgent.new(ai_agent_params.except(:rag_uploads))
if ai_agent.save
RagDocumentFragment.link_target_and_uploads(ai_agent, attached_upload_ids)

render json: {
ai_persona: LocalizedAiPersonaSerializer.new(ai_persona, root: false),
ai_agent: LocalizedAiAgentSerializer.new(ai_agent, root: false),
},
status: :created
else
render_json_error ai_persona
render_json_error ai_agent
end
end

def create_user
user = @ai_persona.create_user!
user = @ai_agent.create_user!
render json: BasicUserSerializer.new(user, root: "user")
end

def update
if @ai_persona.update(ai_persona_params.except(:rag_uploads))
RagDocumentFragment.update_target_uploads(@ai_persona, attached_upload_ids)
if @ai_agent.update(ai_agent_params.except(:rag_uploads))
RagDocumentFragment.update_target_uploads(@ai_agent, attached_upload_ids)

render json: LocalizedAiPersonaSerializer.new(@ai_persona, root: false)
render json: LocalizedAiAgentSerializer.new(@ai_agent, root: false)
else
render_json_error @ai_persona
render_json_error @ai_agent
end
end

def destroy
if @ai_persona.destroy
if @ai_agent.destroy
head :no_content
else
render_json_error @ai_persona
render_json_error @ai_agent
end
end

def stream_reply
persona =
AiPersona.find_by(name: params[:persona_name]) ||
AiPersona.find_by(id: params[:persona_id])
return render_json_error(I18n.t("discourse_ai.errors.persona_not_found")) if persona.nil?
agent =
AiAgent.find_by(name: params[:agent_name]) ||
AiAgent.find_by(id: params[:agent_id])
return render_json_error(I18n.t("discourse_ai.errors.agent_not_found")) if agent.nil?

return render_json_error(I18n.t("discourse_ai.errors.persona_disabled")) if !persona.enabled
return render_json_error(I18n.t("discourse_ai.errors.agent_disabled")) if !agent.enabled

if persona.default_llm.blank?
if agent.default_llm.blank?
return render_json_error(I18n.t("discourse_ai.errors.no_default_llm"))
end

if params[:query].blank?
return render_json_error(I18n.t("discourse_ai.errors.no_query_specified"))
end

if !persona.user_id
return render_json_error(I18n.t("discourse_ai.errors.no_user_for_persona"))
if !agent.user_id
return render_json_error(I18n.t("discourse_ai.errors.no_user_for_agent"))
end

if !params[:username] && !params[:user_unique_id]
Expand Down Expand Up @@ -142,7 +142,7 @@ def stream_reply

DiscourseAi::AiBot::ResponseHttpStreamer.queue_streamed_reply(
io: io,
persona: persona,
agent: agent,
user: user,
topic: topic,
query: params[:query].to_s,
Expand Down Expand Up @@ -178,17 +178,17 @@ def stage_user
end
end

def find_ai_persona
@ai_persona = AiPersona.find(params[:id])
def find_ai_agent
@ai_agent = AiAgent.find(params[:id])
end

def attached_upload_ids
ai_persona_params[:rag_uploads].to_a.map { |h| h[:id] }
ai_agent_params[:rag_uploads].to_a.map { |h| h[:id] }
end

def ai_persona_params
def ai_agent_params
permitted =
params.require(:ai_persona).permit(
params.require(:ai_agent).permit(
:name,
:description,
:enabled,
Expand All @@ -209,23 +209,23 @@ def ai_persona_params
:allow_chat_channel_mentions,
:allow_chat_direct_messages,
:allow_topic_mentions,
:allow_personal_messages,
:allow_agentl_messages,
:tool_details,
:forced_tool_count,
:force_default_llm,
allowed_group_ids: [],
rag_uploads: [:id],
)

if tools = params.dig(:ai_persona, :tools)
if tools = params.dig(:ai_agent, :tools)
permitted[:tools] = permit_tools(tools)
end

if response_format = params.dig(:ai_persona, :response_format)
if response_format = params.dig(:ai_agent, :response_format)
permitted[:response_format] = permit_response_format(response_format)
end

if examples = params.dig(:ai_persona, :examples)
if examples = params.dig(:ai_agent, :examples)
permitted[:examples] = permit_examples(examples)
end

Expand Down
10 changes: 5 additions & 5 deletions app/controllers/discourse_ai/admin/ai_features_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ def edit
private

def serialize_features(features)
features.map { |feature| feature.merge(persona: serialize_persona(feature[:persona])) }
features.map { |feature| feature.merge(agent: serialize_agent(feature[:agent])) }
end

def serialize_feature(feature)
return nil if feature.blank?

feature.merge(persona: serialize_persona(feature[:persona]))
feature.merge(agent: serialize_agent(feature[:agent]))
end

def serialize_persona(persona)
return nil if persona.blank?
def serialize_agent(agent)
return nil if agent.blank?

serialize_data(persona, AiFeaturesPersonaSerializer, root: false)
serialize_data(agent, AiFeaturesAgentSerializer, root: false)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class RagDocumentFragmentsController < ::Admin::AdminController
requires_plugin ::DiscourseAi::PLUGIN_NAME

def indexing_status_check
if params[:target_type] == "AiPersona"
@target = AiPersona.find(params[:target_id])
if params[:target_type] == "AiAgent"
@target = AiAgent.find(params[:target_id])
elsif params[:target_type] == "AiTool"
@target = AiTool.find(params[:target_id])
else
Expand Down
Loading
Loading