diff --git a/app/controllers/discourse_ai/admin/ai_personas_controller.rb b/app/controllers/discourse_ai/admin/ai_personas_controller.rb
index b982677b..ca3059fc 100644
--- a/app/controllers/discourse_ai/admin/ai_personas_controller.rb
+++ b/app/controllers/discourse_ai/admin/ai_personas_controller.rb
@@ -15,7 +15,7 @@ module DiscourseAi
LocalizedAiPersonaSerializer.new(persona, root: false)
end
tools =
- DiscourseAi::AiBot::Personas::Persona.all_available_tools.map do |tool|
+ DiscourseAi::Personas::Persona.all_available_tools.map do |tool|
AiToolSerializer.new(tool, root: false)
end
AiTool
diff --git a/app/jobs/regular/create_ai_chat_reply.rb b/app/jobs/regular/create_ai_chat_reply.rb
index 41776a3b..61f824b6 100644
--- a/app/jobs/regular/create_ai_chat_reply.rb
+++ b/app/jobs/regular/create_ai_chat_reply.rb
@@ -12,11 +12,11 @@ module ::Jobs
return if message.blank?
personaClass =
- DiscourseAi::AiBot::Personas::Persona.find_by(id: args[:persona_id], user: message.user)
+ DiscourseAi::Personas::Persona.find_by(id: args[:persona_id], user: message.user)
return if personaClass.blank?
user = User.find_by(id: personaClass.user_id)
- bot = DiscourseAi::AiBot::Bot.as(user, persona: personaClass.new)
+ bot = DiscourseAi::Personas::Bot.as(user, persona: personaClass.new)
DiscourseAi::AiBot::Playground.new(bot).reply_to_chat_message(
message,
diff --git a/app/jobs/regular/create_ai_reply.rb b/app/jobs/regular/create_ai_reply.rb
index 16f24b2e..e8a0f0ea 100644
--- a/app/jobs/regular/create_ai_reply.rb
+++ b/app/jobs/regular/create_ai_reply.rb
@@ -10,13 +10,13 @@ module ::Jobs
persona_id = args[:persona_id]
begin
- persona = DiscourseAi::AiBot::Personas::Persona.find_by(user: post.user, id: persona_id)
- raise DiscourseAi::AiBot::Bot::BOT_NOT_FOUND if persona.nil?
+ persona = DiscourseAi::Personas::Persona.find_by(user: post.user, id: persona_id)
+ raise DiscourseAi::Personas::Bot::BOT_NOT_FOUND if persona.nil?
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona.new)
+ bot = DiscourseAi::Personas::Bot.as(bot_user, persona: persona.new)
DiscourseAi::AiBot::Playground.new(bot).reply_to(post)
- rescue DiscourseAi::AiBot::Bot::BOT_NOT_FOUND
+ rescue DiscourseAi::Personas::Bot::BOT_NOT_FOUND
Rails.logger.warn(
"Bot not found for post #{post.id} - perhaps persona was deleted or bot was disabled",
)
diff --git a/app/jobs/regular/stream_discover_reply.rb b/app/jobs/regular/stream_discover_reply.rb
index 48183f6e..f8b6d256 100644
--- a/app/jobs/regular/stream_discover_reply.rb
+++ b/app/jobs/regular/stream_discover_reply.rb
@@ -19,7 +19,7 @@ module Jobs
return if (llm_model = LlmModel.find_by(id: ai_persona_klass.default_llm_id)).nil?
bot =
- DiscourseAi::AiBot::Bot.as(
+ DiscourseAi::Personas::Bot.as(
Discourse.system_user,
persona: ai_persona_klass.new,
model: llm_model,
@@ -31,7 +31,7 @@ module Jobs
base = { query: query, model_used: llm_model.display_name }
context =
- DiscourseAi::AiBot::BotContext.new(
+ DiscourseAi::Personas::BotContext.new(
messages: [{ type: :user, content: query }],
skip_tool_details: true,
)
diff --git a/app/models/ai_persona.rb b/app/models/ai_persona.rb
index 867d44ce..9c1399ef 100644
--- a/app/models/ai_persona.rb
+++ b/app/models/ai_persona.rb
@@ -201,14 +201,14 @@ class AiPersona < ActiveRecord::Base
if inner_name.start_with?("custom-")
custom_tool_id = inner_name.split("-", 2).last.to_i
if AiTool.exists?(id: custom_tool_id, enabled: true)
- klass = DiscourseAi::AiBot::Tools::Custom.class_instance(custom_tool_id)
+ klass = DiscourseAi::Personas::Tools::Custom.class_instance(custom_tool_id)
end
else
inner_name = inner_name.gsub("Tool", "")
inner_name = "List#{inner_name}" if %w[Categories Tags].include?(inner_name)
begin
- klass = "DiscourseAi::AiBot::Tools::#{inner_name}".constantize
+ klass = "DiscourseAi::Personas::Tools::#{inner_name}".constantize
options[klass] = current_options if current_options
rescue StandardError
end
@@ -218,7 +218,7 @@ class AiPersona < ActiveRecord::Base
klass
end
- persona_class = DiscourseAi::AiBot::Personas::Persona.system_personas_by_id[self.id]
+ persona_class = DiscourseAi::Personas::Persona.system_personas_by_id[self.id]
if persona_class
instance_attributes.each do |key, value|
# description/name are localized
@@ -230,7 +230,7 @@ class AiPersona < ActiveRecord::Base
ai_persona_id = self.id
- Class.new(DiscourseAi::AiBot::Personas::Persona) do
+ Class.new(DiscourseAi::Personas::Persona) do
instance_attributes.each { |key, value| define_singleton_method(key) { value } }
define_singleton_method(:to_s) do
diff --git a/app/models/ai_tool.rb b/app/models/ai_tool.rb
index d6fde8b2..6ff5582a 100644
--- a/app/models/ai_tool.rb
+++ b/app/models/ai_tool.rb
@@ -36,7 +36,7 @@ class AiTool < ActiveRecord::Base
end
def runner(parameters, llm:, bot_user:, context: nil)
- DiscourseAi::AiBot::ToolRunner.new(
+ DiscourseAi::Personas::ToolRunner.new(
parameters: parameters,
llm: llm,
bot_user: bot_user,
diff --git a/db/fixtures/ai_bot/603_bot_ai_personas.rb b/db/fixtures/personas/603_ai_personas.rb
similarity index 86%
rename from db/fixtures/ai_bot/603_bot_ai_personas.rb
rename to db/fixtures/personas/603_ai_personas.rb
index 06c11169..eaea14ab 100644
--- a/db/fixtures/ai_bot/603_bot_ai_personas.rb
+++ b/db/fixtures/personas/603_ai_personas.rb
@@ -1,18 +1,18 @@
# frozen_string_literal: true
-DiscourseAi::AiBot::Personas::Persona.system_personas.each do |persona_class, id|
+DiscourseAi::Personas::Persona.system_personas.each do |persona_class, id|
persona = AiPersona.find_by(id: id)
if !persona
persona = AiPersona.new
persona.id = id
- if persona_class == DiscourseAi::AiBot::Personas::WebArtifactCreator
+ if persona_class == DiscourseAi::Personas::WebArtifactCreator
# this is somewhat sensitive, so we default it to staff
persona.allowed_group_ids = [Group::AUTO_GROUPS[:staff]]
else
persona.allowed_group_ids = [Group::AUTO_GROUPS[:trust_level_0]]
end
persona.enabled = true
- persona.priority = true if persona_class == DiscourseAi::AiBot::Personas::General
+ persona.priority = true if persona_class == DiscourseAi::Personas::General
end
names = [
diff --git a/lib/ai_bot/entry_point.rb b/lib/ai_bot/entry_point.rb
index 70d4bac5..3f9120a3 100644
--- a/lib/ai_bot/entry_point.rb
+++ b/lib/ai_bot/entry_point.rb
@@ -110,7 +110,7 @@ module DiscourseAi
scope.user.in_any_groups?(SiteSetting.ai_bot_allowed_groups_map)
end,
) do
- DiscourseAi::AiBot::Personas::Persona
+ DiscourseAi::Personas::Persona
.all(user: scope.user)
.map do |persona|
{
@@ -205,8 +205,7 @@ module DiscourseAi
include_condition: -> { SiteSetting.ai_bot_enabled && object.topic.private_message? },
) do
id = topic.custom_fields["ai_persona_id"]
- name =
- DiscourseAi::AiBot::Personas::Persona.find_by(user: scope.user, id: id.to_i)&.name if id
+ name = DiscourseAi::Personas::Persona.find_by(user: scope.user, id: id.to_i)&.name if id
name || topic.custom_fields["ai_persona"]
end
diff --git a/lib/ai_bot/personas/creative.rb b/lib/ai_bot/personas/creative.rb
deleted file mode 100644
index 338577b5..00000000
--- a/lib/ai_bot/personas/creative.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-#frozen_string_literal: true
-
-module DiscourseAi
- module AiBot
- module Personas
- class Creative < Persona
- def tools
- []
- end
-
- def system_prompt
- <<~PROMPT
- You are a helpful bot
- PROMPT
- end
- end
- end
- end
-end
diff --git a/lib/ai_bot/personas/persona.rb b/lib/ai_bot/personas/persona.rb
deleted file mode 100644
index 0d6745a3..00000000
--- a/lib/ai_bot/personas/persona.rb
+++ /dev/null
@@ -1,397 +0,0 @@
-#frozen_string_literal: true
-
-module DiscourseAi
- module AiBot
- module Personas
- class Persona
- class << self
- def rag_conversation_chunks
- 10
- end
-
- def vision_enabled
- false
- end
-
- def vision_max_pixels
- 1_048_576
- end
-
- def question_consolidator_llm_id
- nil
- end
-
- def force_default_llm
- false
- end
-
- def allow_chat_channel_mentions
- false
- end
-
- def allow_chat_direct_messages
- false
- end
-
- def system_personas
- @system_personas ||= {
- Personas::General => -1,
- Personas::SqlHelper => -2,
- Personas::Artist => -3,
- Personas::SettingsExplorer => -4,
- Personas::Researcher => -5,
- Personas::Creative => -6,
- Personas::DallE3 => -7,
- Personas::DiscourseHelper => -8,
- Personas::GithubHelper => -9,
- Personas::WebArtifactCreator => -10,
- }
- end
-
- def system_personas_by_id
- @system_personas_by_id ||= system_personas.invert
- end
-
- def all(user:)
- # listing tools has to be dynamic cause site settings may change
- AiPersona.all_personas.filter do |persona|
- next false if !user.in_any_groups?(persona.allowed_group_ids)
-
- if persona.system
- instance = persona.new
- (
- instance.required_tools == [] ||
- (instance.required_tools - all_available_tools).empty?
- )
- else
- true
- end
- end
- end
-
- def find_by(id: nil, name: nil, user:)
- all(user: user).find { |persona| persona.id == id || persona.name == name }
- end
-
- def name
- I18n.t("discourse_ai.ai_bot.personas.#{to_s.demodulize.underscore}.name")
- end
-
- def description
- I18n.t("discourse_ai.ai_bot.personas.#{to_s.demodulize.underscore}.description")
- end
-
- def all_available_tools
- tools = [
- Tools::ListCategories,
- Tools::Time,
- Tools::Search,
- Tools::Read,
- Tools::DbSchema,
- Tools::SearchSettings,
- Tools::SettingContext,
- Tools::RandomPicker,
- Tools::DiscourseMetaSearch,
- Tools::GithubFileContent,
- Tools::GithubPullRequestDiff,
- Tools::GithubSearchFiles,
- Tools::WebBrowser,
- Tools::JavascriptEvaluator,
- ]
-
- if SiteSetting.ai_artifact_security.in?(%w[lax strict])
- tools << Tools::CreateArtifact
- tools << Tools::UpdateArtifact
- tools << Tools::ReadArtifact
- end
-
- tools << Tools::GithubSearchCode if SiteSetting.ai_bot_github_access_token.present?
-
- tools << Tools::ListTags if SiteSetting.tagging_enabled
- tools << Tools::Image if SiteSetting.ai_stability_api_key.present?
-
- tools << Tools::DallE if SiteSetting.ai_openai_api_key.present?
- if SiteSetting.ai_google_custom_search_api_key.present? &&
- SiteSetting.ai_google_custom_search_cx.present?
- tools << Tools::Google
- end
-
- tools
- end
- end
-
- def id
- @ai_persona&.id || self.class.system_personas[self.class]
- end
-
- def tools
- []
- end
-
- def force_tool_use
- []
- end
-
- def forced_tool_count
- -1
- end
-
- def required_tools
- []
- end
-
- def temperature
- nil
- end
-
- def top_p
- nil
- end
-
- def options
- {}
- end
-
- def available_tools
- self
- .class
- .all_available_tools
- .filter { |tool| tools.include?(tool) }
- .concat(tools.filter(&:custom?))
- end
-
- def craft_prompt(context, llm: nil)
- system_insts =
- system_prompt.gsub(/\{(\w+)\}/) do |match|
- found = context.lookup_template_param(match[1..-2])
- found.nil? ? match : found.to_s
- end
-
- prompt_insts = <<~TEXT.strip
- #{system_insts}
- #{available_tools.map(&:custom_system_message).compact_blank.join("\n")}
- TEXT
-
- question_consolidator_llm = llm
- if self.class.question_consolidator_llm_id.present?
- question_consolidator_llm ||=
- DiscourseAi::Completions::Llm.proxy(
- LlmModel.find_by(id: self.class.question_consolidator_llm_id),
- )
- end
-
- if context.custom_instructions.present?
- prompt_insts << "\n"
- prompt_insts << context.custom_instructions
- end
-
- fragments_guidance =
- rag_fragments_prompt(
- context.messages,
- llm: question_consolidator_llm,
- user: context.user,
- )&.strip
-
- prompt_insts << fragments_guidance if fragments_guidance.present?
-
- prompt =
- DiscourseAi::Completions::Prompt.new(
- prompt_insts,
- messages: context.messages,
- topic_id: context.topic_id,
- post_id: context.post_id,
- )
-
- prompt.max_pixels = self.class.vision_max_pixels if self.class.vision_enabled
- prompt.tools = available_tools.map(&:signature) if available_tools
- available_tools.each do |tool|
- tool.inject_prompt(prompt: prompt, context: context, persona: self)
- end
- prompt
- end
-
- def find_tool(partial, bot_user:, llm:, context:, existing_tools: [])
- return nil if !partial.is_a?(DiscourseAi::Completions::ToolCall)
- tool_instance(
- partial,
- bot_user: bot_user,
- llm: llm,
- context: context,
- existing_tools: existing_tools,
- )
- end
-
- def allow_partial_tool_calls?
- available_tools.any? { |tool| tool.allow_partial_tool_calls? }
- end
-
- protected
-
- def tool_instance(tool_call, bot_user:, llm:, context:, existing_tools:)
- function_id = tool_call.id
- function_name = tool_call.name
- return nil if function_name.nil?
-
- tool_klass = available_tools.find { |c| c.signature.dig(:name) == function_name }
- return nil if tool_klass.nil?
-
- arguments = {}
- tool_klass.signature[:parameters].to_a.each do |param|
- name = param[:name]
- value = tool_call.parameters[name.to_sym]
-
- if param[:type] == "array" && value
- value =
- begin
- JSON.parse(value)
- rescue JSON::ParserError
- [value.to_s]
- end
- elsif param[:type] == "string" && value
- value = strip_quotes(value).to_s
- elsif param[:type] == "integer" && value
- value = strip_quotes(value).to_i
- end
-
- if param[:enum] && value && !param[:enum].include?(value)
- # invalid enum value
- value = nil
- end
-
- arguments[name.to_sym] = value if value
- end
-
- tool_instance =
- existing_tools.find { |t| t.name == function_name && t.tool_call_id == function_id }
-
- if tool_instance
- tool_instance.parameters = arguments
- tool_instance
- else
- tool_klass.new(
- arguments,
- tool_call_id: function_id || function_name,
- persona_options: options[tool_klass].to_h,
- bot_user: bot_user,
- llm: llm,
- context: context,
- )
- end
- end
-
- def strip_quotes(value)
- if value.is_a?(String)
- if value.start_with?('"') && value.end_with?('"')
- value = value[1..-2]
- elsif value.start_with?("'") && value.end_with?("'")
- value = value[1..-2]
- else
- value
- end
- else
- value
- end
- end
-
- def rag_fragments_prompt(conversation_context, llm:, user:)
- upload_refs =
- UploadReference.where(target_id: id, target_type: "AiPersona").pluck(:upload_id)
-
- return nil if !DiscourseAi::Embeddings.enabled?
- return nil if conversation_context.blank? || upload_refs.blank?
-
- latest_interactions =
- conversation_context.select { |ctx| %i[model user].include?(ctx[:type]) }.last(10)
-
- return nil if latest_interactions.empty?
-
- # first response
- if latest_interactions.length == 1
- consolidated_question = latest_interactions[0][:content]
- else
- consolidated_question =
- DiscourseAi::AiBot::QuestionConsolidator.consolidate_question(
- llm,
- latest_interactions,
- user,
- )
- end
-
- return nil if !consolidated_question
-
- vector = DiscourseAi::Embeddings::Vector.instance
- reranker = DiscourseAi::Inference::HuggingFaceTextEmbeddings
-
- interactions_vector = vector.vector_from(consolidated_question)
-
- rag_conversation_chunks = self.class.rag_conversation_chunks
- search_limit =
- if reranker.reranker_configured?
- rag_conversation_chunks * 5
- else
- rag_conversation_chunks
- end
-
- schema = DiscourseAi::Embeddings::Schema.for(RagDocumentFragment)
-
- candidate_fragment_ids =
- schema
- .asymmetric_similarity_search(
- interactions_vector,
- limit: search_limit,
- offset: 0,
- ) { |builder| builder.join(<<~SQL, target_id: id, target_type: "AiPersona") }
- rag_document_fragments ON
- rag_document_fragments.id = rag_document_fragment_id AND
- rag_document_fragments.target_id = :target_id AND
- rag_document_fragments.target_type = :target_type
- SQL
- .map(&:rag_document_fragment_id)
-
- fragments =
- RagDocumentFragment.where(upload_id: upload_refs, id: candidate_fragment_ids).pluck(
- :fragment,
- :metadata,
- )
-
- if reranker.reranker_configured?
- guidance = fragments.map { |fragment, _metadata| fragment }
- ranks =
- DiscourseAi::Inference::HuggingFaceTextEmbeddings
- .rerank(conversation_context.last[:content], guidance)
- .to_a
- .take(rag_conversation_chunks)
- .map { _1[:index] }
-
- if ranks.empty?
- fragments = fragments.take(rag_conversation_chunks)
- else
- fragments = ranks.map { |idx| fragments[idx] }
- end
- end
-
- <<~TEXT
-
- The following texts will give you additional guidance for your response.
- We included them because we believe they are relevant to this conversation topic.
-
- Texts:
-
- #{
- fragments
- .map do |fragment, metadata|
- if metadata.present?
- ["# #{metadata}", fragment].join("\n")
- else
- fragment
- end
- end
- .join("\n")
- }
-
- TEXT
- end
- end
- end
- end
-end
diff --git a/lib/ai_bot/playground.rb b/lib/ai_bot/playground.rb
index 685683fd..eea64f0e 100644
--- a/lib/ai_bot/playground.rb
+++ b/lib/ai_bot/playground.rb
@@ -150,13 +150,11 @@ module DiscourseAi
persona = nil
if persona_id
- persona =
- DiscourseAi::AiBot::Personas::Persona.find_by(user: post.user, id: persona_id.to_i)
+ persona = DiscourseAi::Personas::Persona.find_by(user: post.user, id: persona_id.to_i)
end
if !persona && persona_name = post.topic.custom_fields["ai_persona"]
- persona =
- DiscourseAi::AiBot::Personas::Persona.find_by(user: post.user, name: persona_name)
+ persona = DiscourseAi::Personas::Persona.find_by(user: post.user, name: persona_name)
end
# edge case, llm was mentioned in an ai persona conversation
@@ -172,11 +170,11 @@ module DiscourseAi
end
end
- persona ||= DiscourseAi::AiBot::Personas::General
+ persona ||= DiscourseAi::Personas::General
bot_user = User.find(persona.user_id) if persona && persona.force_default_llm
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona.new)
+ bot = DiscourseAi::Personas::Bot.as(bot_user, persona: persona.new)
new(bot).update_playground_with(post)
end
end
@@ -198,8 +196,8 @@ module DiscourseAi
bot_user = user || ai_persona.user
raise Discourse::InvalidParameters.new(:user) if bot_user.nil?
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona)
- playground = DiscourseAi::AiBot::Playground.new(bot)
+ bot = DiscourseAi::Personas::Bot.as(bot_user, persona: persona)
+ playground = new(bot)
playground.reply_to(
post,
@@ -236,14 +234,54 @@ module DiscourseAi
include_uploads: bot.persona.class.vision_enabled,
)
- bot
- .get_updated_title(messages, post, user)
- .tap do |new_title|
- PostRevisor.new(post.topic.first_post, post.topic).revise!(
- bot.bot_user,
- title: new_title.sub(/\A"/, "").sub(/"\Z/, ""),
- )
+ # conversation context may contain tool calls, and confusing user names
+ # clean it up
+ conversation = +""
+ messages.each do |context|
+ if context[:type] == :user
+ conversation << "User said:\n#{context[:content]}\n\n"
+ elsif context[:type] == :model
+ conversation << "Model said:\n#{context[:content]}\n\n"
end
+ end
+
+ system_insts = <<~TEXT.strip
+ You are titlebot. Given a conversation, you will suggest a title.
+
+ - You will never respond with anything but the suggested title.
+ - You will always match the conversation language in your title suggestion.
+ - Title will capture the essence of the conversation.
+ TEXT
+
+ instruction = <<~TEXT.strip
+ Given the following conversation:
+
+ {{{
+ #{conversation}
+ }}}
+
+ Reply only with a title that is 7 words or less.
+ TEXT
+
+ title_prompt =
+ DiscourseAi::Completions::Prompt.new(
+ system_insts,
+ messages: [type: :user, content: instruction],
+ topic_id: post.topic_id,
+ )
+
+ new_title =
+ bot
+ .llm
+ .generate(title_prompt, user: user, feature_name: "bot_title")
+ .strip
+ .split("\n")
+ .last
+
+ PostRevisor.new(post.topic.first_post, post.topic).revise!(
+ bot.bot_user,
+ title: new_title.sub(/\A"/, "").sub(/"\Z/, ""),
+ )
allowed_users = post.topic.topic_allowed_users.pluck(:user_id)
MessageBus.publish(
@@ -271,7 +309,7 @@ module DiscourseAi
end
context =
- BotContext.new(
+ DiscourseAi::Personas::BotContext.new(
participants: participants,
message_id: message.id,
channel_id: channel.id,
@@ -372,7 +410,7 @@ module DiscourseAi
end
context =
- BotContext.new(
+ DiscourseAi::Personas::BotContext.new(
post: post,
custom_instructions: custom_instructions,
messages:
@@ -575,8 +613,7 @@ module DiscourseAi
def schedule_bot_reply(post)
persona_id =
- DiscourseAi::AiBot::Personas::Persona.system_personas[bot.persona.class] ||
- bot.persona.class.id
+ DiscourseAi::Personas::Persona.system_personas[bot.persona.class] || bot.persona.class.id
::Jobs.enqueue(
:create_ai_reply,
post_id: post.id,
diff --git a/lib/ai_bot/response_http_streamer.rb b/lib/ai_bot/response_http_streamer.rb
index 125a8bbe..cfb2fbeb 100644
--- a/lib/ai_bot/response_http_streamer.rb
+++ b/lib/ai_bot/response_http_streamer.rb
@@ -77,8 +77,8 @@ module DiscourseAi
io.flush
persona_class =
- DiscourseAi::AiBot::Personas::Persona.find_by(id: persona.id, user: current_user)
- bot = DiscourseAi::AiBot::Bot.as(persona.user, persona: persona_class.new)
+ DiscourseAi::Personas::Persona.find_by(id: persona.id, user: current_user)
+ bot = DiscourseAi::Personas::Bot.as(persona.user, persona: persona_class.new)
data =
{
diff --git a/lib/automation/llm_tool_triage.rb b/lib/automation/llm_tool_triage.rb
index 7d7622ad..58b9210d 100644
--- a/lib/automation/llm_tool_triage.rb
+++ b/lib/automation/llm_tool_triage.rb
@@ -7,7 +7,7 @@ module DiscourseAi
return if !tool
return if !tool.parameters.blank?
- context = DiscourseAi::AiBot::BotContext.new(post: post)
+ context = DiscourseAi::Personas::BotContext.new(post: post)
runner = tool.runner({}, llm: nil, bot_user: Discourse.system_user, context: context)
runner.invoke
diff --git a/lib/discord/bot/persona_replier.rb b/lib/discord/bot/persona_replier.rb
index ad9a7841..425451bb 100644
--- a/lib/discord/bot/persona_replier.rb
+++ b/lib/discord/bot/persona_replier.rb
@@ -10,7 +10,7 @@ module DiscourseAi
.find { |persona| persona.id == SiteSetting.ai_discord_search_persona.to_i }
.new
@bot =
- DiscourseAi::AiBot::Bot.as(
+ DiscourseAi::Personas::Bot.as(
Discourse.system_user,
persona: @persona,
model: LlmModel.find(@persona.class.default_llm_id),
diff --git a/lib/discord/bot/search.rb b/lib/discord/bot/search.rb
index 051639ef..e33e35e7 100644
--- a/lib/discord/bot/search.rb
+++ b/lib/discord/bot/search.rb
@@ -4,7 +4,7 @@ module DiscourseAi
module Discord::Bot
class Search < Base
def initialize(body)
- @search = DiscourseAi::AiBot::Tools::Search
+ @search = DiscourseAi::Personas::Tools::Search
super(body)
end
diff --git a/lib/ai_bot/artifact_update_strategies/base.rb b/lib/personas/artifact_update_strategies/base.rb
similarity index 98%
rename from lib/ai_bot/artifact_update_strategies/base.rb
rename to lib/personas/artifact_update_strategies/base.rb
index 91bcb306..68e0b761 100644
--- a/lib/ai_bot/artifact_update_strategies/base.rb
+++ b/lib/personas/artifact_update_strategies/base.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module ArtifactUpdateStrategies
class InvalidFormatError < StandardError
end
diff --git a/lib/ai_bot/artifact_update_strategies/diff.rb b/lib/personas/artifact_update_strategies/diff.rb
similarity index 99%
rename from lib/ai_bot/artifact_update_strategies/diff.rb
rename to lib/personas/artifact_update_strategies/diff.rb
index 39ba8549..af96c0fb 100644
--- a/lib/ai_bot/artifact_update_strategies/diff.rb
+++ b/lib/personas/artifact_update_strategies/diff.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module ArtifactUpdateStrategies
class Diff < Base
attr_reader :failed_searches
diff --git a/lib/ai_bot/artifact_update_strategies/full.rb b/lib/personas/artifact_update_strategies/full.rb
similarity index 99%
rename from lib/ai_bot/artifact_update_strategies/full.rb
rename to lib/personas/artifact_update_strategies/full.rb
index 26f02a84..3942cdf8 100644
--- a/lib/ai_bot/artifact_update_strategies/full.rb
+++ b/lib/personas/artifact_update_strategies/full.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module ArtifactUpdateStrategies
class Full < Base
private
diff --git a/lib/ai_bot/personas/artist.rb b/lib/personas/artist.rb
similarity index 83%
rename from lib/ai_bot/personas/artist.rb
rename to lib/personas/artist.rb
index 03271424..93e2361e 100644
--- a/lib/ai_bot/personas/artist.rb
+++ b/lib/personas/artist.rb
@@ -1,19 +1,18 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class Artist < Persona
- def tools
- [Tools::Image]
- end
+ module Personas
+ class Artist < Persona
+ def tools
+ [Tools::Image]
+ end
- def required_tools
- [Tools::Image]
- end
+ def required_tools
+ [Tools::Image]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are artistbot and you are here to help people generate images.
You generate images using stable diffusion.
@@ -31,7 +30,6 @@ module DiscourseAi
- Be creative with your prompts, offer diverse options
- You can use the seeds to regenerate the same image and amend the prompt keeping general style
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/bot.rb b/lib/personas/bot.rb
similarity index 86%
rename from lib/ai_bot/bot.rb
rename to lib/personas/bot.rb
index 3248d031..62797f72 100644
--- a/lib/ai_bot/bot.rb
+++ b/lib/personas/bot.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
class Bot
attr_reader :model
@@ -13,7 +13,7 @@ module DiscourseAi
# limit is arbitrary, but 5 which was used in the past was too low
MAX_TOOLS = 20
- def self.as(bot_user, persona: DiscourseAi::AiBot::Personas::General.new, model: nil)
+ def self.as(bot_user, persona: DiscourseAi::Personas::General.new, model: nil)
new(bot_user, persona, model)
end
@@ -27,49 +27,8 @@ module DiscourseAi
attr_reader :bot_user
attr_accessor :persona
- def get_updated_title(conversation_context, post, user)
- system_insts = <<~TEXT.strip
- You are titlebot. Given a conversation, you will suggest a title.
-
- - You will never respond with anything but the suggested title.
- - You will always match the conversation language in your title suggestion.
- - Title will capture the essence of the conversation.
- TEXT
-
- # conversation context may contain tool calls, and confusing user names
- # clean it up
- conversation = +""
- conversation_context.each do |context|
- if context[:type] == :user
- conversation << "User said:\n#{context[:content]}\n\n"
- elsif context[:type] == :model
- conversation << "Model said:\n#{context[:content]}\n\n"
- end
- end
-
- instruction = <<~TEXT.strip
- Given the following conversation:
-
- {{{
- #{conversation}
- }}}
-
- Reply only with a title that is 7 words or less.
- TEXT
-
- title_prompt =
- DiscourseAi::Completions::Prompt.new(
- system_insts,
- messages: [type: :user, content: instruction],
- topic_id: post.topic_id,
- )
-
- DiscourseAi::Completions::Llm
- .proxy(model)
- .generate(title_prompt, user: user, feature_name: "bot_title")
- .strip
- .split("\n")
- .last
+ def llm
+ @llm ||= DiscourseAi::Completions::Llm.proxy(model)
end
def force_tool_if_needed(prompt, context)
diff --git a/lib/ai_bot/bot_context.rb b/lib/personas/bot_context.rb
similarity index 99%
rename from lib/ai_bot/bot_context.rb
rename to lib/personas/bot_context.rb
index ca32262a..5ac5b05c 100644
--- a/lib/ai_bot/bot_context.rb
+++ b/lib/personas/bot_context.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
class BotContext
attr_accessor :messages,
:topic_id,
diff --git a/lib/personas/creative.rb b/lib/personas/creative.rb
new file mode 100644
index 00000000..407c2240
--- /dev/null
+++ b/lib/personas/creative.rb
@@ -0,0 +1,17 @@
+#frozen_string_literal: true
+
+module DiscourseAi
+ module Personas
+ class Creative < Persona
+ def tools
+ []
+ end
+
+ def system_prompt
+ <<~PROMPT
+ You are a helpful bot
+ PROMPT
+ end
+ end
+ end
+end
diff --git a/lib/ai_bot/personas/dall_e_3.rb b/lib/personas/dall_e_3.rb
similarity index 83%
rename from lib/ai_bot/personas/dall_e_3.rb
rename to lib/personas/dall_e_3.rb
index 65666284..851756c8 100644
--- a/lib/ai_bot/personas/dall_e_3.rb
+++ b/lib/personas/dall_e_3.rb
@@ -1,19 +1,18 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class DallE3 < Persona
- def tools
- [Tools::DallE]
- end
+ module Personas
+ class DallE3 < Persona
+ def tools
+ [Tools::DallE]
+ end
- def required_tools
- [Tools::DallE]
- end
+ def required_tools
+ [Tools::DallE]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
As a DALL-E-3 bot, you're tasked with generating images based on user prompts.
- Be specific and detailed in your prompts. Include elements like subject, medium (e.g., oil on canvas), artist style, lighting, time of day, and website style (e.g., ArtStation, DeviantArt).
@@ -32,7 +31,6 @@ module DiscourseAi
Just generate the images
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/personas/discourse_helper.rb b/lib/personas/discourse_helper.rb
similarity index 90%
rename from lib/ai_bot/personas/discourse_helper.rb
rename to lib/personas/discourse_helper.rb
index 6c03a0a3..2e9db142 100644
--- a/lib/ai_bot/personas/discourse_helper.rb
+++ b/lib/personas/discourse_helper.rb
@@ -1,15 +1,14 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class DiscourseHelper < Persona
- def tools
- [Tools::DiscourseMetaSearch]
- end
+ module Personas
+ class DiscourseHelper < Persona
+ def tools
+ [Tools::DiscourseMetaSearch]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are Discourse Helper Bot
- Discourse Helper Bot understands *markdown* and responds in Discourse **markdown**.
@@ -41,7 +40,6 @@ module DiscourseAi
The date now is: {time}, much has changed since you were trained.
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/personas/general.rb b/lib/personas/general.rb
similarity index 62%
rename from lib/ai_bot/personas/general.rb
rename to lib/personas/general.rb
index 3e06a3f7..01c05e08 100644
--- a/lib/ai_bot/personas/general.rb
+++ b/lib/personas/general.rb
@@ -1,22 +1,21 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class General < Persona
- def tools
- [
- Tools::Search,
- Tools::Google,
- Tools::Image,
- Tools::Read,
- Tools::ListCategories,
- Tools::ListTags,
- ]
- end
+ module Personas
+ class General < Persona
+ def tools
+ [
+ Tools::Search,
+ Tools::Google,
+ Tools::Image,
+ Tools::Read,
+ Tools::ListCategories,
+ Tools::ListTags,
+ ]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are a helpful Discourse assistant.
You _understand_ and **generate** Discourse Markdown.
You live in a Discourse Forum Message.
@@ -27,7 +26,6 @@ module DiscourseAi
The participants in this conversation are: {participants}
The date now is: {time}, much has changed since you were trained.
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/personas/github_helper.rb b/lib/personas/github_helper.rb
similarity index 60%
rename from lib/ai_bot/personas/github_helper.rb
rename to lib/personas/github_helper.rb
index a0a2e499..a9798065 100644
--- a/lib/ai_bot/personas/github_helper.rb
+++ b/lib/personas/github_helper.rb
@@ -1,20 +1,19 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class GithubHelper < Persona
- def tools
- [
- Tools::GithubFileContent,
- Tools::GithubPullRequestDiff,
- Tools::GithubSearchCode,
- Tools::GithubSearchFiles,
- ]
- end
+ module Personas
+ class GithubHelper < Persona
+ def tools
+ [
+ Tools::GithubFileContent,
+ Tools::GithubPullRequestDiff,
+ Tools::GithubSearchCode,
+ Tools::GithubSearchFiles,
+ ]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are a helpful GitHub assistant.
You _understand_ and **generate** Discourse Flavored Markdown.
You live in a Discourse Forum Message.
@@ -22,7 +21,6 @@ module DiscourseAi
Your purpose is to assist users with GitHub-related tasks and questions.
When asked about a specific repository, pull request, or file, try to use the available tools to provide accurate and helpful information.
PROMPT
- end
end
end
end
diff --git a/lib/personas/persona.rb b/lib/personas/persona.rb
new file mode 100644
index 00000000..fb3eb155
--- /dev/null
+++ b/lib/personas/persona.rb
@@ -0,0 +1,395 @@
+#frozen_string_literal: true
+
+module DiscourseAi
+ module Personas
+ class Persona
+ class << self
+ def rag_conversation_chunks
+ 10
+ end
+
+ def vision_enabled
+ false
+ end
+
+ def vision_max_pixels
+ 1_048_576
+ end
+
+ def question_consolidator_llm_id
+ nil
+ end
+
+ def force_default_llm
+ false
+ end
+
+ def allow_chat_channel_mentions
+ false
+ end
+
+ def allow_chat_direct_messages
+ false
+ end
+
+ def system_personas
+ @system_personas ||= {
+ General => -1,
+ SqlHelper => -2,
+ Artist => -3,
+ SettingsExplorer => -4,
+ Researcher => -5,
+ Creative => -6,
+ DallE3 => -7,
+ DiscourseHelper => -8,
+ GithubHelper => -9,
+ WebArtifactCreator => -10,
+ }
+ end
+
+ def system_personas_by_id
+ @system_personas_by_id ||= system_personas.invert
+ end
+
+ def all(user:)
+ # listing tools has to be dynamic cause site settings may change
+ AiPersona.all_personas.filter do |persona|
+ next false if !user.in_any_groups?(persona.allowed_group_ids)
+
+ if persona.system
+ instance = persona.new
+ (
+ instance.required_tools == [] ||
+ (instance.required_tools - all_available_tools).empty?
+ )
+ else
+ true
+ end
+ end
+ end
+
+ def find_by(id: nil, name: nil, user:)
+ all(user: user).find { |persona| persona.id == id || persona.name == name }
+ end
+
+ def name
+ I18n.t("discourse_ai.ai_bot.personas.#{to_s.demodulize.underscore}.name")
+ end
+
+ def description
+ I18n.t("discourse_ai.ai_bot.personas.#{to_s.demodulize.underscore}.description")
+ end
+
+ def all_available_tools
+ tools = [
+ Tools::ListCategories,
+ Tools::Time,
+ Tools::Search,
+ Tools::Read,
+ Tools::DbSchema,
+ Tools::SearchSettings,
+ Tools::SettingContext,
+ Tools::RandomPicker,
+ Tools::DiscourseMetaSearch,
+ Tools::GithubFileContent,
+ Tools::GithubPullRequestDiff,
+ Tools::GithubSearchFiles,
+ Tools::WebBrowser,
+ Tools::JavascriptEvaluator,
+ ]
+
+ if SiteSetting.ai_artifact_security.in?(%w[lax strict])
+ tools << Tools::CreateArtifact
+ tools << Tools::UpdateArtifact
+ tools << Tools::ReadArtifact
+ end
+
+ tools << Tools::GithubSearchCode if SiteSetting.ai_bot_github_access_token.present?
+
+ tools << Tools::ListTags if SiteSetting.tagging_enabled
+ tools << Tools::Image if SiteSetting.ai_stability_api_key.present?
+
+ tools << Tools::DallE if SiteSetting.ai_openai_api_key.present?
+ if SiteSetting.ai_google_custom_search_api_key.present? &&
+ SiteSetting.ai_google_custom_search_cx.present?
+ tools << Tools::Google
+ end
+
+ tools
+ end
+ end
+
+ def id
+ @ai_persona&.id || self.class.system_personas[self.class]
+ end
+
+ def tools
+ []
+ end
+
+ def force_tool_use
+ []
+ end
+
+ def forced_tool_count
+ -1
+ end
+
+ def required_tools
+ []
+ end
+
+ def temperature
+ nil
+ end
+
+ def top_p
+ nil
+ end
+
+ def options
+ {}
+ end
+
+ def available_tools
+ self
+ .class
+ .all_available_tools
+ .filter { |tool| tools.include?(tool) }
+ .concat(tools.filter(&:custom?))
+ end
+
+ def craft_prompt(context, llm: nil)
+ system_insts =
+ system_prompt.gsub(/\{(\w+)\}/) do |match|
+ found = context.lookup_template_param(match[1..-2])
+ found.nil? ? match : found.to_s
+ end
+
+ prompt_insts = <<~TEXT.strip
+ #{system_insts}
+ #{available_tools.map(&:custom_system_message).compact_blank.join("\n")}
+ TEXT
+
+ question_consolidator_llm = llm
+ if self.class.question_consolidator_llm_id.present?
+ question_consolidator_llm ||=
+ DiscourseAi::Completions::Llm.proxy(
+ LlmModel.find_by(id: self.class.question_consolidator_llm_id),
+ )
+ end
+
+ if context.custom_instructions.present?
+ prompt_insts << "\n"
+ prompt_insts << context.custom_instructions
+ end
+
+ fragments_guidance =
+ rag_fragments_prompt(
+ context.messages,
+ llm: question_consolidator_llm,
+ user: context.user,
+ )&.strip
+
+ prompt_insts << fragments_guidance if fragments_guidance.present?
+
+ prompt =
+ DiscourseAi::Completions::Prompt.new(
+ prompt_insts,
+ messages: context.messages,
+ topic_id: context.topic_id,
+ post_id: context.post_id,
+ )
+
+ prompt.max_pixels = self.class.vision_max_pixels if self.class.vision_enabled
+ prompt.tools = available_tools.map(&:signature) if available_tools
+ available_tools.each do |tool|
+ tool.inject_prompt(prompt: prompt, context: context, persona: self)
+ end
+ prompt
+ end
+
+ def find_tool(partial, bot_user:, llm:, context:, existing_tools: [])
+ return nil if !partial.is_a?(DiscourseAi::Completions::ToolCall)
+ tool_instance(
+ partial,
+ bot_user: bot_user,
+ llm: llm,
+ context: context,
+ existing_tools: existing_tools,
+ )
+ end
+
+ def allow_partial_tool_calls?
+ available_tools.any? { |tool| tool.allow_partial_tool_calls? }
+ end
+
+ protected
+
+ def tool_instance(tool_call, bot_user:, llm:, context:, existing_tools:)
+ function_id = tool_call.id
+ function_name = tool_call.name
+ return nil if function_name.nil?
+
+ tool_klass = available_tools.find { |c| c.signature.dig(:name) == function_name }
+ return nil if tool_klass.nil?
+
+ arguments = {}
+ tool_klass.signature[:parameters].to_a.each do |param|
+ name = param[:name]
+ value = tool_call.parameters[name.to_sym]
+
+ if param[:type] == "array" && value
+ value =
+ begin
+ JSON.parse(value)
+ rescue JSON::ParserError
+ [value.to_s]
+ end
+ elsif param[:type] == "string" && value
+ value = strip_quotes(value).to_s
+ elsif param[:type] == "integer" && value
+ value = strip_quotes(value).to_i
+ end
+
+ if param[:enum] && value && !param[:enum].include?(value)
+ # invalid enum value
+ value = nil
+ end
+
+ arguments[name.to_sym] = value if value
+ end
+
+ tool_instance =
+ existing_tools.find { |t| t.name == function_name && t.tool_call_id == function_id }
+
+ if tool_instance
+ tool_instance.parameters = arguments
+ tool_instance
+ else
+ tool_klass.new(
+ arguments,
+ tool_call_id: function_id || function_name,
+ persona_options: options[tool_klass].to_h,
+ bot_user: bot_user,
+ llm: llm,
+ context: context,
+ )
+ end
+ end
+
+ def strip_quotes(value)
+ if value.is_a?(String)
+ if value.start_with?('"') && value.end_with?('"')
+ value = value[1..-2]
+ elsif value.start_with?("'") && value.end_with?("'")
+ value = value[1..-2]
+ else
+ value
+ end
+ else
+ value
+ end
+ end
+
+ def rag_fragments_prompt(conversation_context, llm:, user:)
+ upload_refs =
+ UploadReference.where(target_id: id, target_type: "AiPersona").pluck(:upload_id)
+
+ return nil if !DiscourseAi::Embeddings.enabled?
+ return nil if conversation_context.blank? || upload_refs.blank?
+
+ latest_interactions =
+ conversation_context.select { |ctx| %i[model user].include?(ctx[:type]) }.last(10)
+
+ return nil if latest_interactions.empty?
+
+ # first response
+ if latest_interactions.length == 1
+ consolidated_question = latest_interactions[0][:content]
+ else
+ consolidated_question =
+ DiscourseAi::Personas::QuestionConsolidator.consolidate_question(
+ llm,
+ latest_interactions,
+ user,
+ )
+ end
+
+ return nil if !consolidated_question
+
+ vector = DiscourseAi::Embeddings::Vector.instance
+ reranker = DiscourseAi::Inference::HuggingFaceTextEmbeddings
+
+ interactions_vector = vector.vector_from(consolidated_question)
+
+ rag_conversation_chunks = self.class.rag_conversation_chunks
+ search_limit =
+ if reranker.reranker_configured?
+ rag_conversation_chunks * 5
+ else
+ rag_conversation_chunks
+ end
+
+ schema = DiscourseAi::Embeddings::Schema.for(RagDocumentFragment)
+
+ candidate_fragment_ids =
+ schema
+ .asymmetric_similarity_search(
+ interactions_vector,
+ limit: search_limit,
+ offset: 0,
+ ) { |builder| builder.join(<<~SQL, target_id: id, target_type: "AiPersona") }
+ rag_document_fragments ON
+ rag_document_fragments.id = rag_document_fragment_id AND
+ rag_document_fragments.target_id = :target_id AND
+ rag_document_fragments.target_type = :target_type
+ SQL
+ .map(&:rag_document_fragment_id)
+
+ fragments =
+ RagDocumentFragment.where(upload_id: upload_refs, id: candidate_fragment_ids).pluck(
+ :fragment,
+ :metadata,
+ )
+
+ if reranker.reranker_configured?
+ guidance = fragments.map { |fragment, _metadata| fragment }
+ ranks =
+ DiscourseAi::Inference::HuggingFaceTextEmbeddings
+ .rerank(conversation_context.last[:content], guidance)
+ .to_a
+ .take(rag_conversation_chunks)
+ .map { _1[:index] }
+
+ if ranks.empty?
+ fragments = fragments.take(rag_conversation_chunks)
+ else
+ fragments = ranks.map { |idx| fragments[idx] }
+ end
+ end
+
+ <<~TEXT
+
+ The following texts will give you additional guidance for your response.
+ We included them because we believe they are relevant to this conversation topic.
+
+ Texts:
+
+ #{
+ fragments
+ .map do |fragment, metadata|
+ if metadata.present?
+ ["# #{metadata}", fragment].join("\n")
+ else
+ fragment
+ end
+ end
+ .join("\n")
+ }
+
+ TEXT
+ end
+ end
+ end
+end
diff --git a/lib/ai_bot/question_consolidator.rb b/lib/personas/question_consolidator.rb
similarity index 99%
rename from lib/ai_bot/question_consolidator.rb
rename to lib/personas/question_consolidator.rb
index 59159148..f1e0c476 100644
--- a/lib/ai_bot/question_consolidator.rb
+++ b/lib/personas/question_consolidator.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
class QuestionConsolidator
attr_reader :llm, :messages, :user, :max_tokens
diff --git a/lib/ai_bot/personas/researcher.rb b/lib/personas/researcher.rb
similarity index 88%
rename from lib/ai_bot/personas/researcher.rb
rename to lib/personas/researcher.rb
index 983d4b22..c79e8ee4 100644
--- a/lib/ai_bot/personas/researcher.rb
+++ b/lib/personas/researcher.rb
@@ -1,19 +1,18 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class Researcher < Persona
- def tools
- [Tools::Google, Tools::WebBrowser]
- end
+ module Personas
+ class Researcher < Persona
+ def tools
+ [Tools::Google, Tools::WebBrowser]
+ end
- def required_tools
- [Tools::Google]
- end
+ def required_tools
+ [Tools::Google]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are a research assistant with access to two powerful tools:
1. Google search - for finding relevant information across the internet.
@@ -45,7 +44,6 @@ module DiscourseAi
Remember, efficient use of your tools not only saves time but also ensures the high quality and relevance of the information provided.
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/personas/settings_explorer.rb b/lib/personas/settings_explorer.rb
similarity index 71%
rename from lib/ai_bot/personas/settings_explorer.rb
rename to lib/personas/settings_explorer.rb
index 018df156..77ae45e3 100644
--- a/lib/ai_bot/personas/settings_explorer.rb
+++ b/lib/personas/settings_explorer.rb
@@ -1,15 +1,14 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class SettingsExplorer < Persona
- def tools
- [Tools::SettingContext, Tools::SearchSettings]
- end
+ module Personas
+ class SettingsExplorer < Persona
+ def tools
+ [Tools::SettingContext, Tools::SearchSettings]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are Discourse Site settings bot.
- You are able to find information about all the site settings.
@@ -19,7 +18,6 @@ module DiscourseAi
Current time is: {time}
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/personas/sql_helper.rb b/lib/personas/sql_helper.rb
similarity index 72%
rename from lib/ai_bot/personas/sql_helper.rb
rename to lib/personas/sql_helper.rb
index 7d602192..720bc145 100644
--- a/lib/ai_bot/personas/sql_helper.rb
+++ b/lib/personas/sql_helper.rb
@@ -1,52 +1,50 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class SqlHelper < Persona
- def self.schema
- return @schema if defined?(@schema)
+ module Personas
+ class SqlHelper < Persona
+ def self.schema
+ return @schema if defined?(@schema)
- tables = Hash.new
- priority_tables = %w[
- posts
- topics
- notifications
- users
- user_actions
- user_emails
- categories
- groups
- ]
+ tables = Hash.new
+ priority_tables = %w[
+ posts
+ topics
+ notifications
+ users
+ user_actions
+ user_emails
+ categories
+ groups
+ ]
- DB.query(<<~SQL).each { |row| (tables[row.table_name] ||= []) << row.column_name }
+ DB.query(<<~SQL).each { |row| (tables[row.table_name] ||= []) << row.column_name }
select table_name, column_name from information_schema.columns
where table_schema = 'public'
order by table_name
SQL
- priority =
- +(priority_tables.map { |name| "#{name}(#{tables[name].join(",")})" }.join("\n"))
+ priority = +(priority_tables.map { |name| "#{name}(#{tables[name].join(",")})" }.join("\n"))
- other_tables = +""
- tables.each do |table_name, _|
- next if priority_tables.include?(table_name)
- other_tables << "#{table_name} "
- end
-
- @schema = { priority_tables: priority, other_tables: other_tables }
+ other_tables = +""
+ tables.each do |table_name, _|
+ next if priority_tables.include?(table_name)
+ other_tables << "#{table_name} "
end
- def tools
- [Tools::DbSchema]
- end
+ @schema = { priority_tables: priority, other_tables: other_tables }
+ end
- def temperature
- 0.2
- end
+ def tools
+ [Tools::DbSchema]
+ end
- def system_prompt
- <<~PROMPT
+ def temperature
+ 0.2
+ end
+
+ def system_prompt
+ <<~PROMPT
You are a PostgreSQL expert.
- Avoid returning any text to the user prior to a tool call.
- You understand and generate Discourse Markdown but specialize in creating queries.
@@ -100,7 +98,6 @@ module DiscourseAi
NEVER look up schema for the tables listed above, as their full schema is already provided.
PROMPT
- end
end
end
end
diff --git a/lib/ai_bot/tool_runner.rb b/lib/personas/tool_runner.rb
similarity index 97%
rename from lib/ai_bot/tool_runner.rb
rename to lib/personas/tool_runner.rb
index 8a42a494..33a5a657 100644
--- a/lib/ai_bot/tool_runner.rb
+++ b/lib/personas/tool_runner.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
class ToolRunner
attr_reader :tool, :parameters, :llm
attr_accessor :running_attached_function, :timeout, :custom_raw
@@ -14,11 +14,11 @@ module DiscourseAi
MAX_HTTP_REQUESTS = 20
def initialize(parameters:, llm:, bot_user:, context: nil, tool:, timeout: nil)
- if context && !context.is_a?(DiscourseAi::AiBot::BotContext)
+ if context && !context.is_a?(DiscourseAi::Personas::BotContext)
raise ArgumentError, "context must be a BotContext object"
end
- context ||= DiscourseAi::AiBot::BotContext.new
+ context ||= DiscourseAi::Personas::BotContext.new
@parameters = parameters
@llm = llm
@@ -339,7 +339,7 @@ module DiscourseAi
return { error: "Persona not found" } if persona_class.nil?
persona = persona_class.new
- bot = DiscourseAi::AiBot::Bot.as(@bot_user || persona.user, persona: persona)
+ bot = DiscourseAi::Personas::Bot.as(@bot_user || persona.user, persona: persona)
playground = DiscourseAi::AiBot::Playground.new(bot)
if @context.post_id
@@ -488,7 +488,7 @@ module DiscourseAi
headers = (options && options["headers"]) || {}
result = {}
- DiscourseAi::AiBot::Tools::Tool.send_http_request(
+ DiscourseAi::Personas::Tools::Tool.send_http_request(
url,
headers: headers,
) do |response|
@@ -517,7 +517,7 @@ module DiscourseAi
body = options && options["body"]
result = {}
- DiscourseAi::AiBot::Tools::Tool.send_http_request(
+ DiscourseAi::Personas::Tools::Tool.send_http_request(
url,
method: method,
headers: headers,
diff --git a/lib/ai_bot/tools/create_artifact.rb b/lib/personas/tools/create_artifact.rb
similarity index 99%
rename from lib/ai_bot/tools/create_artifact.rb
rename to lib/personas/tools/create_artifact.rb
index 54221b40..c12577ff 100644
--- a/lib/ai_bot/tools/create_artifact.rb
+++ b/lib/personas/tools/create_artifact.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class CreateArtifact < Tool
def self.name
diff --git a/lib/ai_bot/tools/custom.rb b/lib/personas/tools/custom.rb
similarity index 98%
rename from lib/ai_bot/tools/custom.rb
rename to lib/personas/tools/custom.rb
index 8a4fbc99..505b051e 100644
--- a/lib/ai_bot/tools/custom.rb
+++ b/lib/personas/tools/custom.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Custom < Tool
def self.class_instance(tool_id)
diff --git a/lib/ai_bot/tools/dall_e.rb b/lib/personas/tools/dall_e.rb
similarity index 99%
rename from lib/ai_bot/tools/dall_e.rb
rename to lib/personas/tools/dall_e.rb
index 4564cfbb..e8957b51 100644
--- a/lib/ai_bot/tools/dall_e.rb
+++ b/lib/personas/tools/dall_e.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class DallE < Tool
def self.signature
diff --git a/lib/ai_bot/tools/db_schema.rb b/lib/personas/tools/db_schema.rb
similarity index 98%
rename from lib/ai_bot/tools/db_schema.rb
rename to lib/personas/tools/db_schema.rb
index 1c11fb68..b0a6f296 100644
--- a/lib/ai_bot/tools/db_schema.rb
+++ b/lib/personas/tools/db_schema.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class DbSchema < Tool
def self.signature
diff --git a/lib/ai_bot/tools/discourse_meta_search.rb b/lib/personas/tools/discourse_meta_search.rb
similarity index 99%
rename from lib/ai_bot/tools/discourse_meta_search.rb
rename to lib/personas/tools/discourse_meta_search.rb
index d787eb79..5fdfb76e 100644
--- a/lib/ai_bot/tools/discourse_meta_search.rb
+++ b/lib/personas/tools/discourse_meta_search.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class DiscourseMetaSearch < Tool
class << self
diff --git a/lib/ai_bot/tools/github_file_content.rb b/lib/personas/tools/github_file_content.rb
similarity index 99%
rename from lib/ai_bot/tools/github_file_content.rb
rename to lib/personas/tools/github_file_content.rb
index c3cde356..aef00c1e 100644
--- a/lib/ai_bot/tools/github_file_content.rb
+++ b/lib/personas/tools/github_file_content.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class GithubFileContent < Tool
def self.signature
diff --git a/lib/ai_bot/tools/github_pull_request_diff.rb b/lib/personas/tools/github_pull_request_diff.rb
similarity index 99%
rename from lib/ai_bot/tools/github_pull_request_diff.rb
rename to lib/personas/tools/github_pull_request_diff.rb
index 21bb71cf..afbe51f9 100644
--- a/lib/ai_bot/tools/github_pull_request_diff.rb
+++ b/lib/personas/tools/github_pull_request_diff.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class GithubPullRequestDiff < Tool
LARGE_OBJECT_THRESHOLD = 30_000
diff --git a/lib/ai_bot/tools/github_search_code.rb b/lib/personas/tools/github_search_code.rb
similarity index 99%
rename from lib/ai_bot/tools/github_search_code.rb
rename to lib/personas/tools/github_search_code.rb
index a0e1acbd..3bb93d02 100644
--- a/lib/ai_bot/tools/github_search_code.rb
+++ b/lib/personas/tools/github_search_code.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class GithubSearchCode < Tool
def self.signature
diff --git a/lib/ai_bot/tools/github_search_files.rb b/lib/personas/tools/github_search_files.rb
similarity index 99%
rename from lib/ai_bot/tools/github_search_files.rb
rename to lib/personas/tools/github_search_files.rb
index 97af3bdf..c97cbd7c 100644
--- a/lib/ai_bot/tools/github_search_files.rb
+++ b/lib/personas/tools/github_search_files.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class GithubSearchFiles < Tool
def self.signature
diff --git a/lib/ai_bot/tools/google.rb b/lib/personas/tools/google.rb
similarity index 99%
rename from lib/ai_bot/tools/google.rb
rename to lib/personas/tools/google.rb
index 77158882..bf90fcdb 100644
--- a/lib/ai_bot/tools/google.rb
+++ b/lib/personas/tools/google.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Google < Tool
def self.signature
diff --git a/lib/ai_bot/tools/image.rb b/lib/personas/tools/image.rb
similarity index 99%
rename from lib/ai_bot/tools/image.rb
rename to lib/personas/tools/image.rb
index 34e5e3f2..3ab2b705 100644
--- a/lib/ai_bot/tools/image.rb
+++ b/lib/personas/tools/image.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Image < Tool
def self.signature
diff --git a/lib/ai_bot/tools/javascript_evaluator.rb b/lib/personas/tools/javascript_evaluator.rb
similarity index 99%
rename from lib/ai_bot/tools/javascript_evaluator.rb
rename to lib/personas/tools/javascript_evaluator.rb
index 77aadd04..23d7c1b1 100644
--- a/lib/ai_bot/tools/javascript_evaluator.rb
+++ b/lib/personas/tools/javascript_evaluator.rb
@@ -4,7 +4,7 @@ require "mini_racer"
require "json"
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class JavascriptEvaluator < Tool
TIMEOUT = 500
diff --git a/lib/ai_bot/tools/list_categories.rb b/lib/personas/tools/list_categories.rb
similarity index 98%
rename from lib/ai_bot/tools/list_categories.rb
rename to lib/personas/tools/list_categories.rb
index 4a32ce13..895eaae5 100644
--- a/lib/ai_bot/tools/list_categories.rb
+++ b/lib/personas/tools/list_categories.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class ListCategories < Tool
def self.signature
diff --git a/lib/ai_bot/tools/list_tags.rb b/lib/personas/tools/list_tags.rb
similarity index 97%
rename from lib/ai_bot/tools/list_tags.rb
rename to lib/personas/tools/list_tags.rb
index 6ff702bf..852c9abc 100644
--- a/lib/ai_bot/tools/list_tags.rb
+++ b/lib/personas/tools/list_tags.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class ListTags < Tool
def self.signature
diff --git a/lib/ai_bot/tools/option.rb b/lib/personas/tools/option.rb
similarity index 97%
rename from lib/ai_bot/tools/option.rb
rename to lib/personas/tools/option.rb
index b772ab8c..777475b8 100644
--- a/lib/ai_bot/tools/option.rb
+++ b/lib/personas/tools/option.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Option
attr_reader :tool, :name, :type, :values, :default
diff --git a/lib/ai_bot/tools/random_picker.rb b/lib/personas/tools/random_picker.rb
similarity index 99%
rename from lib/ai_bot/tools/random_picker.rb
rename to lib/personas/tools/random_picker.rb
index c1ed16f9..1abd537f 100644
--- a/lib/ai_bot/tools/random_picker.rb
+++ b/lib/personas/tools/random_picker.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class RandomPicker < Tool
def self.signature
diff --git a/lib/ai_bot/tools/read.rb b/lib/personas/tools/read.rb
similarity index 99%
rename from lib/ai_bot/tools/read.rb
rename to lib/personas/tools/read.rb
index d7a0186f..3077de47 100644
--- a/lib/ai_bot/tools/read.rb
+++ b/lib/personas/tools/read.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
MAX_POSTS = 100
module Tools
diff --git a/lib/ai_bot/tools/read_artifact.rb b/lib/personas/tools/read_artifact.rb
similarity index 99%
rename from lib/ai_bot/tools/read_artifact.rb
rename to lib/personas/tools/read_artifact.rb
index 98b7944f..e3074d71 100644
--- a/lib/ai_bot/tools/read_artifact.rb
+++ b/lib/personas/tools/read_artifact.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class ReadArtifact < Tool
MAX_HTML_SIZE = 30.kilobytes
diff --git a/lib/ai_bot/tools/search.rb b/lib/personas/tools/search.rb
similarity index 99%
rename from lib/ai_bot/tools/search.rb
rename to lib/personas/tools/search.rb
index 402eca05..869cff58 100644
--- a/lib/ai_bot/tools/search.rb
+++ b/lib/personas/tools/search.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Search < Tool
attr_reader :last_query
diff --git a/lib/ai_bot/tools/search_settings.rb b/lib/personas/tools/search_settings.rb
similarity index 99%
rename from lib/ai_bot/tools/search_settings.rb
rename to lib/personas/tools/search_settings.rb
index ad0af7fa..fc66c926 100644
--- a/lib/ai_bot/tools/search_settings.rb
+++ b/lib/personas/tools/search_settings.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class SearchSettings < Tool
INCLUDE_DESCRIPTIONS_MAX_LENGTH = 10
diff --git a/lib/ai_bot/tools/setting_context.rb b/lib/personas/tools/setting_context.rb
similarity index 99%
rename from lib/ai_bot/tools/setting_context.rb
rename to lib/personas/tools/setting_context.rb
index c8acf5aa..7fb7c6b7 100644
--- a/lib/ai_bot/tools/setting_context.rb
+++ b/lib/personas/tools/setting_context.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class SettingContext < Tool
MAX_CONTEXT_TOKENS = 2000
diff --git a/lib/ai_bot/tools/summarize.rb b/lib/personas/tools/summarize.rb
similarity index 99%
rename from lib/ai_bot/tools/summarize.rb
rename to lib/personas/tools/summarize.rb
index 5076635f..94f6cf49 100644
--- a/lib/ai_bot/tools/summarize.rb
+++ b/lib/personas/tools/summarize.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Summarize < Tool
def self.signature
diff --git a/lib/ai_bot/tools/time.rb b/lib/personas/tools/time.rb
similarity index 98%
rename from lib/ai_bot/tools/time.rb
rename to lib/personas/tools/time.rb
index bd88eeed..da3d4f43 100644
--- a/lib/ai_bot/tools/time.rb
+++ b/lib/personas/tools/time.rb
@@ -1,7 +1,7 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Time < Tool
def self.signature
diff --git a/lib/ai_bot/tools/tool.rb b/lib/personas/tools/tool.rb
similarity index 97%
rename from lib/ai_bot/tools/tool.rb
rename to lib/personas/tools/tool.rb
index ba0bc69c..4bafe0af 100644
--- a/lib/ai_bot/tools/tool.rb
+++ b/lib/personas/tools/tool.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class Tool
# Why 30 mega bytes?
@@ -63,9 +63,9 @@ module DiscourseAi
@persona_options = persona_options
@bot_user = bot_user
@llm = llm
- @context = context.nil? ? DiscourseAi::AiBot::BotContext.new(messages: []) : context
- if !@context.is_a?(DiscourseAi::AiBot::BotContext)
- raise ArgumentError, "context must be a DiscourseAi::AiBot::Context"
+ @context = context.nil? ? DiscourseAi::Personas::BotContext.new(messages: []) : context
+ if !@context.is_a?(DiscourseAi::Personas::BotContext)
+ raise ArgumentError, "context must be a DiscourseAi::Personas::Context"
end
end
diff --git a/lib/ai_bot/tools/update_artifact.rb b/lib/personas/tools/update_artifact.rb
similarity index 99%
rename from lib/ai_bot/tools/update_artifact.rb
rename to lib/personas/tools/update_artifact.rb
index 2c9e544b..ccf39a8d 100644
--- a/lib/ai_bot/tools/update_artifact.rb
+++ b/lib/personas/tools/update_artifact.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class UpdateArtifact < Tool
def self.name
diff --git a/lib/ai_bot/tools/web_browser.rb b/lib/personas/tools/web_browser.rb
similarity index 99%
rename from lib/ai_bot/tools/web_browser.rb
rename to lib/personas/tools/web_browser.rb
index eb4cf020..3e917cb3 100644
--- a/lib/ai_bot/tools/web_browser.rb
+++ b/lib/personas/tools/web_browser.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module DiscourseAi
- module AiBot
+ module Personas
module Tools
class WebBrowser < Tool
def self.signature
diff --git a/lib/ai_bot/personas/web_artifact_creator.rb b/lib/personas/web_artifact_creator.rb
similarity index 84%
rename from lib/ai_bot/personas/web_artifact_creator.rb
rename to lib/personas/web_artifact_creator.rb
index ec99a778..8fe5ef1c 100644
--- a/lib/ai_bot/personas/web_artifact_creator.rb
+++ b/lib/personas/web_artifact_creator.rb
@@ -1,19 +1,18 @@
#frozen_string_literal: true
module DiscourseAi
- module AiBot
- module Personas
- class WebArtifactCreator < Persona
- def tools
- [Tools::CreateArtifact, Tools::UpdateArtifact, Tools::ReadArtifact]
- end
+ module Personas
+ class WebArtifactCreator < Persona
+ def tools
+ [Tools::CreateArtifact, Tools::UpdateArtifact, Tools::ReadArtifact]
+ end
- def required_tools
- [Tools::CreateArtifact, Tools::UpdateArtifact, Tools::ReadArtifact]
- end
+ def required_tools
+ [Tools::CreateArtifact, Tools::UpdateArtifact, Tools::ReadArtifact]
+ end
- def system_prompt
- <<~PROMPT
+ def system_prompt
+ <<~PROMPT
You are the Web Creator, an AI assistant specializing in building interactive web components. You create engaging and functional web experiences using HTML, CSS, and JavaScript. You live in a Discourse PM and communicate using Markdown.
Core Principles:
@@ -49,7 +48,6 @@ module DiscourseAi
Remember: Great components combine structure (HTML), presentation (CSS), and behavior (JavaScript) to create memorable user experiences.
PROMPT
- end
end
end
end
diff --git a/plugin.rb b/plugin.rb
index 7f6e1389..77bdde7b 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -83,6 +83,8 @@ after_initialize do
add_admin_route("discourse_ai.title", "discourse-ai", { use_new_show_route: true })
+ register_seedfu_fixtures(Rails.root.join("plugins", "discourse-ai", "db", "fixtures", "personas"))
+
[
DiscourseAi::Embeddings::EntryPoint.new,
DiscourseAi::Sentiment::EntryPoint.new,
diff --git a/spec/lib/discord/bot/persona_replier_spec.rb b/spec/lib/discord/bot/persona_replier_spec.rb
index 00bb4859..9228e1bf 100644
--- a/spec/lib/discord/bot/persona_replier_spec.rb
+++ b/spec/lib/discord/bot/persona_replier_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe DiscourseAi::Discord::Bot::PersonaReplier do
before do
SiteSetting.ai_discord_search_persona = persona.id.to_s
- allow_any_instance_of(DiscourseAi::AiBot::Bot).to receive(:reply).and_return(
+ allow_any_instance_of(DiscourseAi::Personas::Bot).to receive(:reply).and_return(
"This is a reply from bot!",
)
allow(persona_replier).to receive(:create_reply)
diff --git a/spec/lib/discord/bot/search_spec.rb b/spec/lib/discord/bot/search_spec.rb
index 7d4cebff..36233f60 100644
--- a/spec/lib/discord/bot/search_spec.rb
+++ b/spec/lib/discord/bot/search_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe DiscourseAi::Discord::Bot::Search do
describe "#handle_interaction!" do
it "creates a reply with search results" do
- allow_any_instance_of(DiscourseAi::AiBot::Tools::Search).to receive(:invoke).and_return(
+ allow_any_instance_of(DiscourseAi::Personas::Tools::Search).to receive(:invoke).and_return(
{ rows: [%w[Title /link]] },
)
search.handle_interaction!
diff --git a/spec/lib/modules/ai_bot/playground_spec.rb b/spec/lib/modules/ai_bot/playground_spec.rb
index 4df2ae5d..e825ebc2 100644
--- a/spec/lib/modules/ai_bot/playground_spec.rb
+++ b/spec/lib/modules/ai_bot/playground_spec.rb
@@ -22,14 +22,10 @@ RSpec.describe DiscourseAi::AiBot::Playground do
fab!(:bot) do
persona =
AiPersona
- .find(
- DiscourseAi::AiBot::Personas::Persona.system_personas[
- DiscourseAi::AiBot::Personas::General
- ],
- )
+ .find(DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General])
.class_instance
.new
- DiscourseAi::AiBot::Bot.as(bot_user, persona: persona)
+ DiscourseAi::Personas::Bot.as(bot_user, persona: persona)
end
fab!(:admin) { Fabricate(:admin, refresh_auto_groups: true) }
@@ -103,7 +99,7 @@ RSpec.describe DiscourseAi::AiBot::Playground do
)
end
- let(:bot) { DiscourseAi::AiBot::Bot.as(bot_user, persona: ai_persona.class_instance.new) }
+ let(:bot) { DiscourseAi::Personas::Bot.as(bot_user, persona: ai_persona.class_instance.new) }
let(:playground) { DiscourseAi::AiBot::Playground.new(bot) }
@@ -173,8 +169,8 @@ RSpec.describe DiscourseAi::AiBot::Playground do
it "uses custom tool in conversation" do
persona_klass = AiPersona.all_personas.find { |p| p.name == ai_persona.name }
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona_klass.new)
- playground = DiscourseAi::AiBot::Playground.new(bot)
+ bot = DiscourseAi::Personas::Bot.as(bot_user, persona: persona_klass.new)
+ playground = described_class.new(bot)
responses = [tool_call, "custom tool did stuff (maybe)"]
@@ -213,7 +209,7 @@ RSpec.describe DiscourseAi::AiBot::Playground do
custom_tool.update!(enabled: false)
# so we pick up new cache
persona_klass = AiPersona.all_personas.find { |p| p.name == ai_persona.name }
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona_klass.new)
+ bot = DiscourseAi::Personas::Bot.as(bot_user, persona: persona_klass.new)
playground = DiscourseAi::AiBot::Playground.new(bot)
responses = ["custom tool did stuff (maybe)", tool_call]
@@ -968,7 +964,7 @@ RSpec.describe DiscourseAi::AiBot::Playground do
it "supports disabling tool details" do
persona = Fabricate(:ai_persona, tool_details: false, tools: ["Search"])
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: persona.class_instance.new)
+ bot = DiscourseAi::Personas::Bot.as(bot_user, persona: persona.class_instance.new)
playground = described_class.new(bot)
response1 =
@@ -1021,13 +1017,11 @@ RSpec.describe DiscourseAi::AiBot::Playground do
let(:persona) do
AiPersona.find(
- DiscourseAi::AiBot::Personas::Persona.system_personas[
- DiscourseAi::AiBot::Personas::DallE3
- ],
+ DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::DallE3],
)
end
- let(:bot) { DiscourseAi::AiBot::Bot.as(bot_user, persona: persona.class_instance.new) }
+ let(:bot) { DiscourseAi::Personas::Bot.as(bot_user, persona: persona.class_instance.new) }
let(:data) do
image =
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
diff --git a/spec/lib/modules/ai_bot/artifact_update_strategies/diff_spec.rb b/spec/lib/personas/artifact_update_strategies/diff_spec.rb
similarity index 98%
rename from spec/lib/modules/ai_bot/artifact_update_strategies/diff_spec.rb
rename to spec/lib/personas/artifact_update_strategies/diff_spec.rb
index 689984cf..d07813ff 100644
--- a/spec/lib/modules/ai_bot/artifact_update_strategies/diff_spec.rb
+++ b/spec/lib/personas/artifact_update_strategies/diff_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::ArtifactUpdateStrategies::Diff do
+RSpec.describe DiscourseAi::Personas::ArtifactUpdateStrategies::Diff do
fab!(:user)
fab!(:post)
fab!(:artifact) { Fabricate(:ai_artifact) }
diff --git a/spec/lib/modules/ai_bot/bot_spec.rb b/spec/lib/personas/bot_spec.rb
similarity index 84%
rename from spec/lib/modules/ai_bot/bot_spec.rb
rename to spec/lib/personas/bot_spec.rb
index 025a37f9..03619957 100644
--- a/spec/lib/modules/ai_bot/bot_spec.rb
+++ b/spec/lib/personas/bot_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Bot do
+RSpec.describe DiscourseAi::Personas::Bot do
subject(:bot) { described_class.as(bot_user) }
fab!(:admin)
@@ -48,11 +48,11 @@ RSpec.describe DiscourseAi::AiBot::Bot do
allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_0]],
)
- personaClass = DiscourseAi::AiBot::Personas::Persona.find_by(user: admin, name: "TestPersona")
+ personaClass = DiscourseAi::Personas::Persona.find_by(user: admin, name: "TestPersona")
- bot = DiscourseAi::AiBot::Bot.as(bot_user, persona: personaClass.new)
+ bot = described_class.as(bot_user, persona: personaClass.new)
bot.reply(
- DiscourseAi::AiBot::BotContext.new(messages: [{ type: :user, content: "test" }]),
+ DiscourseAi::Personas::BotContext.new(messages: [{ type: :user, content: "test" }]),
) do |_partial, _cancel, _placeholder|
# we just need the block so bot has something to call with results
end
@@ -64,7 +64,7 @@ RSpec.describe DiscourseAi::AiBot::Bot do
context "when using function chaining" do
it "yields a loading placeholder while proceeds to invoke the command" do
- tool = DiscourseAi::AiBot::Tools::ListCategories.new({}, bot_user: nil, llm: nil)
+ tool = DiscourseAi::Personas::Tools::ListCategories.new({}, bot_user: nil, llm: nil)
partial_placeholder = +(<<~HTML)
#{tool.summary}
@@ -75,7 +75,7 @@ RSpec.describe DiscourseAi::AiBot::Bot do
HTML
context =
- DiscourseAi::AiBot::BotContext.new(
+ DiscourseAi::Personas::BotContext.new(
messages: [{ type: :user, content: "Does my site has tags?" }],
)
diff --git a/spec/lib/modules/ai_bot/personas/persona_spec.rb b/spec/lib/personas/persona_spec.rb
similarity index 76%
rename from spec/lib/modules/ai_bot/personas/persona_spec.rb
rename to spec/lib/personas/persona_spec.rb
index 8bd6634d..70f4c327 100644
--- a/spec/lib/modules/ai_bot/personas/persona_spec.rb
+++ b/spec/lib/personas/persona_spec.rb
@@ -1,11 +1,11 @@
#frozen_string_literal: true
-class TestPersona < DiscourseAi::AiBot::Personas::Persona
+class TestPersona < DiscourseAi::Personas::Persona
def tools
[
- DiscourseAi::AiBot::Tools::ListTags,
- DiscourseAi::AiBot::Tools::Search,
- DiscourseAi::AiBot::Tools::Image,
+ DiscourseAi::Personas::Tools::ListTags,
+ DiscourseAi::Personas::Tools::Search,
+ DiscourseAi::Personas::Tools::Image,
]
end
def system_prompt
@@ -19,7 +19,7 @@ class TestPersona < DiscourseAi::AiBot::Personas::Persona
end
end
-RSpec.describe DiscourseAi::AiBot::Personas::Persona do
+RSpec.describe DiscourseAi::Personas::Persona do
let :persona do
TestPersona.new
end
@@ -36,7 +36,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
end
let(:context) do
- DiscourseAi::AiBot::BotContext.new(
+ DiscourseAi::Personas::BotContext.new(
site_url: Discourse.base_url,
site_title: "test site title",
site_description: "test site description",
@@ -84,12 +84,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
)
tool_instance =
- DiscourseAi::AiBot::Personas::Artist.new.find_tool(
- tool_call,
- bot_user: nil,
- llm: nil,
- context: nil,
- )
+ DiscourseAi::Personas::Artist.new.find_tool(tool_call, bot_user: nil, llm: nil, context: nil)
expect(tool_instance.parameters[:prompts]).to eq(["cat oil painting", "big car"])
expect(tool_instance.parameters[:aspect_ratio]).to eq("16:9")
@@ -108,12 +103,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
)
tool_instance =
- DiscourseAi::AiBot::Personas::General.new.find_tool(
- tool_call,
- bot_user: nil,
- llm: nil,
- context: nil,
- )
+ DiscourseAi::Personas::General.new.find_tool(tool_call, bot_user: nil, llm: nil, context: nil)
expect(tool_instance.parameters.key?(:status)).to eq(false)
@@ -129,12 +119,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
)
tool_instance =
- DiscourseAi::AiBot::Personas::General.new.find_tool(
- tool_call,
- bot_user: nil,
- llm: nil,
- context: nil,
- )
+ DiscourseAi::Personas::General.new.find_tool(tool_call, bot_user: nil, llm: nil, context: nil)
expect(tool_instance.parameters[:status]).to eq("open")
end
@@ -152,12 +137,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
)
search =
- DiscourseAi::AiBot::Personas::General.new.find_tool(
- tool_call,
- bot_user: nil,
- llm: nil,
- context: nil,
- )
+ DiscourseAi::Personas::General.new.find_tool(tool_call, bot_user: nil, llm: nil, context: nil)
expect(search.parameters[:max_posts]).to eq(3)
expect(search.parameters[:search_query]).to eq("hello world")
@@ -177,12 +157,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
)
tool_instance =
- DiscourseAi::AiBot::Personas::DallE3.new.find_tool(
- tool_call,
- bot_user: nil,
- llm: nil,
- context: nil,
- )
+ DiscourseAi::Personas::DallE3.new.find_tool(tool_call, bot_user: nil, llm: nil, context: nil)
expect(tool_instance.parameters[:prompts]).to eq(["cat oil painting", "big car"])
end
@@ -200,29 +175,29 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_0]],
)
- custom_persona = DiscourseAi::AiBot::Personas::Persona.all(user: user).last
+ custom_persona = DiscourseAi::Personas::Persona.all(user: user).last
expect(custom_persona.name).to eq("zzzpun_bot")
expect(custom_persona.description).to eq("you write puns")
instance = custom_persona.new
- expect(instance.tools).to eq([DiscourseAi::AiBot::Tools::Image])
+ expect(instance.tools).to eq([DiscourseAi::Personas::Tools::Image])
expect(instance.craft_prompt(context).messages.first[:content]).to eq("you are pun bot")
# should update
persona.update!(name: "zzzpun_bot2")
- custom_persona = DiscourseAi::AiBot::Personas::Persona.all(user: user).last
+ custom_persona = DiscourseAi::Personas::Persona.all(user: user).last
expect(custom_persona.name).to eq("zzzpun_bot2")
# can be disabled
persona.update!(enabled: false)
- last_persona = DiscourseAi::AiBot::Personas::Persona.all(user: user).last
+ last_persona = DiscourseAi::Personas::Persona.all(user: user).last
expect(last_persona.name).not_to eq("zzzpun_bot2")
persona.update!(enabled: true)
# no groups have access
persona.update!(allowed_group_ids: [])
- last_persona = DiscourseAi::AiBot::Personas::Persona.all(user: user).last
+ last_persona = DiscourseAi::Personas::Persona.all(user: user).last
expect(last_persona.name).not_to eq("zzzpun_bot2")
end
end
@@ -237,31 +212,31 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
SiteSetting.ai_google_custom_search_cx = "abc123"
# should be ordered by priority and then alpha
- expect(DiscourseAi::AiBot::Personas::Persona.all(user: user)).to eq(
+ expect(DiscourseAi::Personas::Persona.all(user: user)).to eq(
[
- DiscourseAi::AiBot::Personas::General,
- DiscourseAi::AiBot::Personas::Artist,
- DiscourseAi::AiBot::Personas::Creative,
- DiscourseAi::AiBot::Personas::DiscourseHelper,
- DiscourseAi::AiBot::Personas::GithubHelper,
- DiscourseAi::AiBot::Personas::Researcher,
- DiscourseAi::AiBot::Personas::SettingsExplorer,
- DiscourseAi::AiBot::Personas::SqlHelper,
+ DiscourseAi::Personas::General,
+ DiscourseAi::Personas::Artist,
+ DiscourseAi::Personas::Creative,
+ DiscourseAi::Personas::DiscourseHelper,
+ DiscourseAi::Personas::GithubHelper,
+ DiscourseAi::Personas::Researcher,
+ DiscourseAi::Personas::SettingsExplorer,
+ DiscourseAi::Personas::SqlHelper,
],
)
# it should allow staff access to WebArtifactCreator
- expect(DiscourseAi::AiBot::Personas::Persona.all(user: admin)).to eq(
+ expect(DiscourseAi::Personas::Persona.all(user: admin)).to eq(
[
- DiscourseAi::AiBot::Personas::General,
- DiscourseAi::AiBot::Personas::Artist,
- DiscourseAi::AiBot::Personas::Creative,
- DiscourseAi::AiBot::Personas::DiscourseHelper,
- DiscourseAi::AiBot::Personas::GithubHelper,
- DiscourseAi::AiBot::Personas::Researcher,
- DiscourseAi::AiBot::Personas::SettingsExplorer,
- DiscourseAi::AiBot::Personas::SqlHelper,
- DiscourseAi::AiBot::Personas::WebArtifactCreator,
+ DiscourseAi::Personas::General,
+ DiscourseAi::Personas::Artist,
+ DiscourseAi::Personas::Creative,
+ DiscourseAi::Personas::DiscourseHelper,
+ DiscourseAi::Personas::GithubHelper,
+ DiscourseAi::Personas::Researcher,
+ DiscourseAi::Personas::SettingsExplorer,
+ DiscourseAi::Personas::SqlHelper,
+ DiscourseAi::Personas::WebArtifactCreator,
],
)
@@ -270,27 +245,25 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
SiteSetting.ai_google_custom_search_api_key = ""
SiteSetting.ai_artifact_security = "disabled"
- expect(DiscourseAi::AiBot::Personas::Persona.all(user: admin)).to contain_exactly(
- DiscourseAi::AiBot::Personas::General,
- DiscourseAi::AiBot::Personas::SqlHelper,
- DiscourseAi::AiBot::Personas::SettingsExplorer,
- DiscourseAi::AiBot::Personas::Creative,
- DiscourseAi::AiBot::Personas::DiscourseHelper,
- DiscourseAi::AiBot::Personas::GithubHelper,
+ expect(DiscourseAi::Personas::Persona.all(user: admin)).to contain_exactly(
+ DiscourseAi::Personas::General,
+ DiscourseAi::Personas::SqlHelper,
+ DiscourseAi::Personas::SettingsExplorer,
+ DiscourseAi::Personas::Creative,
+ DiscourseAi::Personas::DiscourseHelper,
+ DiscourseAi::Personas::GithubHelper,
)
AiPersona.find(
- DiscourseAi::AiBot::Personas::Persona.system_personas[
- DiscourseAi::AiBot::Personas::General
- ],
+ DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General],
).update!(enabled: false)
- expect(DiscourseAi::AiBot::Personas::Persona.all(user: user)).to contain_exactly(
- DiscourseAi::AiBot::Personas::SqlHelper,
- DiscourseAi::AiBot::Personas::SettingsExplorer,
- DiscourseAi::AiBot::Personas::Creative,
- DiscourseAi::AiBot::Personas::DiscourseHelper,
- DiscourseAi::AiBot::Personas::GithubHelper,
+ expect(DiscourseAi::Personas::Persona.all(user: user)).to contain_exactly(
+ DiscourseAi::Personas::SqlHelper,
+ DiscourseAi::Personas::SettingsExplorer,
+ DiscourseAi::Personas::Creative,
+ DiscourseAi::Personas::DiscourseHelper,
+ DiscourseAi::Personas::GithubHelper,
)
end
end
@@ -304,7 +277,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
SiteSetting.ai_embeddings_enabled = true
end
- let(:ai_persona) { DiscourseAi::AiBot::Personas::Persona.all(user: user).first.new }
+ let(:ai_persona) { DiscourseAi::Personas::Persona.all(user: user).first.new }
let(:with_cc) do
context.messages = [{ content: "Tell me the time", type: :user }]
@@ -343,7 +316,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
UploadReference.ensure_exist!(target: custom_ai_persona, upload_ids: [upload.id])
custom_persona =
- DiscourseAi::AiBot::Personas::Persona.find_by(id: custom_ai_persona.id, user: user).new
+ DiscourseAi::Personas::Persona.find_by(id: custom_ai_persona.id, user: user).new
# this means that we will consolidate
context.messages = [
@@ -415,7 +388,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
UploadReference.ensure_exist!(target: custom_ai_persona, upload_ids: [upload.id])
custom_persona =
- DiscourseAi::AiBot::Personas::Persona.find_by(id: custom_ai_persona.id, user: user).new
+ DiscourseAi::Personas::Persona.find_by(id: custom_ai_persona.id, user: user).new
expect(custom_persona.class.rag_conversation_chunks).to eq(3)
diff --git a/spec/lib/modules/ai_bot/question_consolidator_spec.rb b/spec/lib/personas/question_consolidator_spec.rb
similarity index 94%
rename from spec/lib/modules/ai_bot/question_consolidator_spec.rb
rename to spec/lib/personas/question_consolidator_spec.rb
index ece7c973..7fe54399 100644
--- a/spec/lib/modules/ai_bot/question_consolidator_spec.rb
+++ b/spec/lib/personas/question_consolidator_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::QuestionConsolidator do
+RSpec.describe DiscourseAi::Personas::QuestionConsolidator do
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{Fabricate(:fake_model).id}") }
let(:fake_endpoint) { DiscourseAi::Completions::Endpoints::Fake }
diff --git a/spec/lib/modules/ai_bot/personas/researcher_spec.rb b/spec/lib/personas/researcher_spec.rb
similarity index 51%
rename from spec/lib/modules/ai_bot/personas/researcher_spec.rb
rename to spec/lib/personas/researcher_spec.rb
index c3c65888..d216d6c0 100644
--- a/spec/lib/modules/ai_bot/personas/researcher_spec.rb
+++ b/spec/lib/personas/researcher_spec.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Personas::Researcher do
+RSpec.describe DiscourseAi::Personas::Researcher do
let :researcher do
subject
end
it "renders schema" do
expect(researcher.tools).to eq(
- [DiscourseAi::AiBot::Tools::Google, DiscourseAi::AiBot::Tools::WebBrowser],
+ [DiscourseAi::Personas::Tools::Google, DiscourseAi::Personas::Tools::WebBrowser],
)
end
end
diff --git a/spec/lib/modules/ai_bot/personas/settings_explorer_spec.rb b/spec/lib/personas/settings_explorer_spec.rb
similarity index 69%
rename from spec/lib/modules/ai_bot/personas/settings_explorer_spec.rb
rename to spec/lib/personas/settings_explorer_spec.rb
index d7a60cd1..24f15224 100644
--- a/spec/lib/modules/ai_bot/personas/settings_explorer_spec.rb
+++ b/spec/lib/personas/settings_explorer_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Personas::SettingsExplorer do
+RSpec.describe DiscourseAi::Personas::SettingsExplorer do
let :settings_explorer do
subject
end
@@ -14,7 +14,7 @@ RSpec.describe DiscourseAi::AiBot::Personas::SettingsExplorer do
expect(prompt).to include("site_description")
expect(settings_explorer.tools).to eq(
- [DiscourseAi::AiBot::Tools::SettingContext, DiscourseAi::AiBot::Tools::SearchSettings],
+ [DiscourseAi::Personas::Tools::SettingContext, DiscourseAi::Personas::Tools::SearchSettings],
)
end
end
diff --git a/spec/lib/modules/ai_bot/personas/sql_helper_spec.rb b/spec/lib/personas/sql_helper_spec.rb
similarity index 73%
rename from spec/lib/modules/ai_bot/personas/sql_helper_spec.rb
rename to spec/lib/personas/sql_helper_spec.rb
index 37d645bc..d2f1614e 100644
--- a/spec/lib/modules/ai_bot/personas/sql_helper_spec.rb
+++ b/spec/lib/personas/sql_helper_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Personas::SqlHelper do
+RSpec.describe DiscourseAi::Personas::SqlHelper do
let :sql_helper do
subject
end
@@ -12,6 +12,6 @@ RSpec.describe DiscourseAi::AiBot::Personas::SqlHelper do
expect(prompt).not_to include("translation_key") # not a priority table
expect(prompt).to include("user_api_keys") # not a priority table
- expect(sql_helper.tools).to eq([DiscourseAi::AiBot::Tools::DbSchema])
+ expect(sql_helper.tools).to eq([DiscourseAi::Personas::Tools::DbSchema])
end
end
diff --git a/spec/lib/modules/ai_bot/tools/create_artifact_spec.rb b/spec/lib/personas/tools/create_artifact_spec.rb
similarity index 92%
rename from spec/lib/modules/ai_bot/tools/create_artifact_spec.rb
rename to spec/lib/personas/tools/create_artifact_spec.rb
index 26d47528..929e54ef 100644
--- a/spec/lib/modules/ai_bot/tools/create_artifact_spec.rb
+++ b/spec/lib/personas/tools/create_artifact_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::CreateArtifact do
+RSpec.describe DiscourseAi::Personas::Tools::CreateArtifact do
fab!(:llm_model)
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
fab!(:post)
@@ -34,7 +34,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::CreateArtifact do
{ html_body: "hello" },
bot_user: Fabricate(:user),
llm: llm,
- context: DiscourseAi::AiBot::BotContext.new(post: post),
+ context: DiscourseAi::Personas::BotContext.new(post: post),
)
tool.parameters = { name: "hello", specification: "hello spec" }
diff --git a/spec/lib/modules/ai_bot/tools/dall_e_spec.rb b/spec/lib/personas/tools/dall_e_spec.rb
similarity index 98%
rename from spec/lib/modules/ai_bot/tools/dall_e_spec.rb
rename to spec/lib/personas/tools/dall_e_spec.rb
index dfb4e9d3..fff8ee61 100644
--- a/spec/lib/modules/ai_bot/tools/dall_e_spec.rb
+++ b/spec/lib/personas/tools/dall_e_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::DallE do
+RSpec.describe DiscourseAi::Personas::Tools::DallE do
let(:prompts) { ["a pink cow", "a red cow"] }
fab!(:gpt_35_turbo) { Fabricate(:llm_model, name: "gpt-3.5-turbo") }
diff --git a/spec/lib/modules/ai_bot/tools/db_schema_spec.rb b/spec/lib/personas/tools/db_schema_spec.rb
similarity index 92%
rename from spec/lib/modules/ai_bot/tools/db_schema_spec.rb
rename to spec/lib/personas/tools/db_schema_spec.rb
index f0f3ae29..643e3fe7 100644
--- a/spec/lib/modules/ai_bot/tools/db_schema_spec.rb
+++ b/spec/lib/personas/tools/db_schema_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::DbSchema do
+RSpec.describe DiscourseAi::Personas::Tools::DbSchema do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/discourse_meta_search_spec.rb b/spec/lib/personas/tools/discourse_meta_search_spec.rb
similarity index 97%
rename from spec/lib/modules/ai_bot/tools/discourse_meta_search_spec.rb
rename to spec/lib/personas/tools/discourse_meta_search_spec.rb
index 375f6d0c..1ccc4d4d 100644
--- a/spec/lib/modules/ai_bot/tools/discourse_meta_search_spec.rb
+++ b/spec/lib/personas/tools/discourse_meta_search_spec.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::DiscourseMetaSearch do
+RSpec.describe DiscourseAi::Personas::Tools::DiscourseMetaSearch do
before { SiteSetting.ai_bot_enabled = true }
fab!(:llm_model) { Fabricate(:llm_model, max_prompt_tokens: 8192) }
diff --git a/spec/lib/modules/ai_bot/tools/github_file_content_spec.rb b/spec/lib/personas/tools/github_file_content_spec.rb
similarity index 97%
rename from spec/lib/modules/ai_bot/tools/github_file_content_spec.rb
rename to spec/lib/personas/tools/github_file_content_spec.rb
index 8018813b..4186dd01 100644
--- a/spec/lib/modules/ai_bot/tools/github_file_content_spec.rb
+++ b/spec/lib/personas/tools/github_file_content_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe DiscourseAi::AiBot::Tools::GithubFileContent do
+RSpec.describe DiscourseAi::Personas::Tools::GithubFileContent do
fab!(:llm_model)
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/github_pull_request_diff_spec.rb b/spec/lib/personas/tools/github_pull_request_diff_spec.rb
similarity index 98%
rename from spec/lib/modules/ai_bot/tools/github_pull_request_diff_spec.rb
rename to spec/lib/personas/tools/github_pull_request_diff_spec.rb
index 428bd72b..e8b3d226 100644
--- a/spec/lib/modules/ai_bot/tools/github_pull_request_diff_spec.rb
+++ b/spec/lib/personas/tools/github_pull_request_diff_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe DiscourseAi::AiBot::Tools::GithubPullRequestDiff do
+RSpec.describe DiscourseAi::Personas::Tools::GithubPullRequestDiff do
let(:bot_user) { Fabricate(:user) }
fab!(:llm_model)
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/github_search_code_spec.rb b/spec/lib/personas/tools/github_search_code_spec.rb
similarity index 97%
rename from spec/lib/modules/ai_bot/tools/github_search_code_spec.rb
rename to spec/lib/personas/tools/github_search_code_spec.rb
index b9cebe36..b8fbca27 100644
--- a/spec/lib/modules/ai_bot/tools/github_search_code_spec.rb
+++ b/spec/lib/personas/tools/github_search_code_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe DiscourseAi::AiBot::Tools::GithubSearchCode do
+RSpec.describe DiscourseAi::Personas::Tools::GithubSearchCode do
let(:bot_user) { Fabricate(:user) }
fab!(:llm_model)
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/github_search_files_spec.rb b/spec/lib/personas/tools/github_search_files_spec.rb
similarity index 97%
rename from spec/lib/modules/ai_bot/tools/github_search_files_spec.rb
rename to spec/lib/personas/tools/github_search_files_spec.rb
index a0352a38..cc6926fd 100644
--- a/spec/lib/modules/ai_bot/tools/github_search_files_spec.rb
+++ b/spec/lib/personas/tools/github_search_files_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe DiscourseAi::AiBot::Tools::GithubSearchFiles do
+RSpec.describe DiscourseAi::Personas::Tools::GithubSearchFiles do
fab!(:llm_model)
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/google_spec.rb b/spec/lib/personas/tools/google_spec.rb
similarity index 98%
rename from spec/lib/modules/ai_bot/tools/google_spec.rb
rename to spec/lib/personas/tools/google_spec.rb
index c39f94b0..5062cea9 100644
--- a/spec/lib/modules/ai_bot/tools/google_spec.rb
+++ b/spec/lib/personas/tools/google_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Google do
+RSpec.describe DiscourseAi::Personas::Tools::Google do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/image_spec.rb b/spec/lib/personas/tools/image_spec.rb
similarity index 94%
rename from spec/lib/modules/ai_bot/tools/image_spec.rb
rename to spec/lib/personas/tools/image_spec.rb
index aea98dd9..342c9f67 100644
--- a/spec/lib/modules/ai_bot/tools/image_spec.rb
+++ b/spec/lib/personas/tools/image_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Image do
+RSpec.describe DiscourseAi::Personas::Tools::Image do
let(:progress_blk) { Proc.new {} }
let(:prompts) { ["a pink cow", "a red cow"] }
@@ -9,7 +9,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::Image do
{ prompts: prompts, seeds: [99, 32] },
bot_user: bot_user,
llm: llm,
- context: DiscourseAi::AiBot::BotContext.new,
+ context: DiscourseAi::Personas::BotContext.new,
)
end
diff --git a/spec/lib/modules/ai_bot/tools/javascript_evaluator_spec.rb b/spec/lib/personas/tools/javascript_evaluator_spec.rb
similarity index 97%
rename from spec/lib/modules/ai_bot/tools/javascript_evaluator_spec.rb
rename to spec/lib/personas/tools/javascript_evaluator_spec.rb
index 8b2a544c..cae05ee9 100644
--- a/spec/lib/modules/ai_bot/tools/javascript_evaluator_spec.rb
+++ b/spec/lib/personas/tools/javascript_evaluator_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::JavascriptEvaluator do
+RSpec.describe DiscourseAi::Personas::Tools::JavascriptEvaluator do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/list_categories_spec.rb b/spec/lib/personas/tools/list_categories_spec.rb
similarity index 90%
rename from spec/lib/modules/ai_bot/tools/list_categories_spec.rb
rename to spec/lib/personas/tools/list_categories_spec.rb
index a2e92b86..bcda2123 100644
--- a/spec/lib/modules/ai_bot/tools/list_categories_spec.rb
+++ b/spec/lib/personas/tools/list_categories_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::ListCategories do
+RSpec.describe DiscourseAi::Personas::Tools::ListCategories do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/list_tags_spec.rb b/spec/lib/personas/tools/list_tags_spec.rb
similarity index 92%
rename from spec/lib/modules/ai_bot/tools/list_tags_spec.rb
rename to spec/lib/personas/tools/list_tags_spec.rb
index 0019a884..b8f4ed5c 100644
--- a/spec/lib/modules/ai_bot/tools/list_tags_spec.rb
+++ b/spec/lib/personas/tools/list_tags_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::ListTags do
+RSpec.describe DiscourseAi::Personas::Tools::ListTags do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/random_picker_spec.rb b/spec/lib/personas/tools/random_picker_spec.rb
similarity index 96%
rename from spec/lib/modules/ai_bot/tools/random_picker_spec.rb
rename to spec/lib/personas/tools/random_picker_spec.rb
index 6e5930bf..65f7c7f2 100644
--- a/spec/lib/modules/ai_bot/tools/random_picker_spec.rb
+++ b/spec/lib/personas/tools/random_picker_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe DiscourseAi::AiBot::Tools::RandomPicker do
+RSpec.describe DiscourseAi::Personas::Tools::RandomPicker do
describe "#invoke" do
subject { described_class.new({ options: options }, bot_user: nil, llm: nil).invoke }
diff --git a/spec/lib/modules/ai_bot/tools/read_artifact_spec.rb b/spec/lib/personas/tools/read_artifact_spec.rb
similarity index 90%
rename from spec/lib/modules/ai_bot/tools/read_artifact_spec.rb
rename to spec/lib/personas/tools/read_artifact_spec.rb
index 8247c528..279dd18e 100644
--- a/spec/lib/modules/ai_bot/tools/read_artifact_spec.rb
+++ b/spec/lib/personas/tools/read_artifact_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::ReadArtifact do
+RSpec.describe DiscourseAi::Personas::Tools::ReadArtifact do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
fab!(:post)
@@ -25,7 +25,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::ReadArtifact do
{ url: "#{Discourse.base_url}/discourse-ai/ai-bot/artifacts/#{artifact.id}" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(post: post),
+ context: DiscourseAi::Personas::BotContext.new(post: post),
)
result = tool.invoke {}
@@ -44,7 +44,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::ReadArtifact do
{ url: "invalid-url" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(post: post),
+ context: DiscourseAi::Personas::BotContext.new(post: post),
)
result = tool.invoke {}
@@ -58,7 +58,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::ReadArtifact do
{ url: "#{Discourse.base_url}/discourse-ai/ai-bot/artifacts/99999" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(post: post),
+ context: DiscourseAi::Personas::BotContext.new(post: post),
)
result = tool.invoke {}
@@ -91,7 +91,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::ReadArtifact do
{ url: "https://example.com" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(post: post),
+ context: DiscourseAi::Personas::BotContext.new(post: post),
)
result = tool.invoke {}
@@ -120,7 +120,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::ReadArtifact do
{ url: "https://example.com" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(post: post),
+ context: DiscourseAi::Personas::BotContext.new(post: post),
)
result = tool.invoke {}
diff --git a/spec/lib/modules/ai_bot/tools/read_spec.rb b/spec/lib/personas/tools/read_spec.rb
similarity index 94%
rename from spec/lib/modules/ai_bot/tools/read_spec.rb
rename to spec/lib/personas/tools/read_spec.rb
index 88dc7906..2affc1f4 100644
--- a/spec/lib/modules/ai_bot/tools/read_spec.rb
+++ b/spec/lib/personas/tools/read_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Read do
+RSpec.describe DiscourseAi::Personas::Tools::Read do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
@@ -56,7 +56,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::Read do
persona_options: {
"read_private" => true,
},
- context: DiscourseAi::AiBot::BotContext.new(user: admin),
+ context: DiscourseAi::Personas::BotContext.new(user: admin),
)
results = tool.invoke
expect(results[:content]).to include("hello there")
@@ -66,7 +66,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::Read do
{ topic_id: topic_with_tags.id, post_numbers: [post1.post_number] },
bot_user: bot_user,
llm: llm,
- context: DiscourseAi::AiBot::BotContext.new(user: admin),
+ context: DiscourseAi::Personas::BotContext.new(user: admin),
)
results = tool.invoke
diff --git a/spec/lib/modules/ai_bot/tools/search_settings_spec.rb b/spec/lib/personas/tools/search_settings_spec.rb
similarity index 97%
rename from spec/lib/modules/ai_bot/tools/search_settings_spec.rb
rename to spec/lib/personas/tools/search_settings_spec.rb
index 0796e89a..f3cd4356 100644
--- a/spec/lib/modules/ai_bot/tools/search_settings_spec.rb
+++ b/spec/lib/personas/tools/search_settings_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::SearchSettings do
+RSpec.describe DiscourseAi::Personas::Tools::SearchSettings do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/search_spec.rb b/spec/lib/personas/tools/search_spec.rb
similarity index 98%
rename from spec/lib/modules/ai_bot/tools/search_spec.rb
rename to spec/lib/personas/tools/search_spec.rb
index c7be7522..c28696f9 100644
--- a/spec/lib/modules/ai_bot/tools/search_spec.rb
+++ b/spec/lib/personas/tools/search_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Search do
+RSpec.describe DiscourseAi::Personas::Tools::Search do
before { SearchIndexer.enable }
after { SearchIndexer.disable }
@@ -60,7 +60,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::Search do
persona_options: persona_options,
bot_user: bot_user,
llm: llm,
- context: DiscourseAi::AiBot::BotContext.new(user: user),
+ context: DiscourseAi::Personas::BotContext.new(user: user),
)
expect(search.options[:base_query]).to eq("#funny")
diff --git a/spec/lib/modules/ai_bot/tools/setting_context_spec.rb b/spec/lib/personas/tools/setting_context_spec.rb
similarity index 95%
rename from spec/lib/modules/ai_bot/tools/setting_context_spec.rb
rename to spec/lib/personas/tools/setting_context_spec.rb
index 36240ffb..20e26b64 100644
--- a/spec/lib/modules/ai_bot/tools/setting_context_spec.rb
+++ b/spec/lib/personas/tools/setting_context_spec.rb
@@ -8,7 +8,7 @@ def has_rg?
end
end
-RSpec.describe DiscourseAi::AiBot::Tools::SettingContext, if: has_rg? do
+RSpec.describe DiscourseAi::Personas::Tools::SettingContext, if: has_rg? do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
diff --git a/spec/lib/modules/ai_bot/tools/summarize_spec.rb b/spec/lib/personas/tools/summarize_spec.rb
similarity index 96%
rename from spec/lib/modules/ai_bot/tools/summarize_spec.rb
rename to spec/lib/personas/tools/summarize_spec.rb
index 2e48b196..2bda3cd3 100644
--- a/spec/lib/modules/ai_bot/tools/summarize_spec.rb
+++ b/spec/lib/personas/tools/summarize_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Summarize do
+RSpec.describe DiscourseAi::Personas::Tools::Summarize do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/time_spec.rb b/spec/lib/personas/tools/time_spec.rb
similarity index 92%
rename from spec/lib/modules/ai_bot/tools/time_spec.rb
rename to spec/lib/personas/tools/time_spec.rb
index e389ea99..e92a32ad 100644
--- a/spec/lib/modules/ai_bot/tools/time_spec.rb
+++ b/spec/lib/personas/tools/time_spec.rb
@@ -1,6 +1,6 @@
#frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Time do
+RSpec.describe DiscourseAi::Personas::Tools::Time do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/lib/modules/ai_bot/tools/tool_spec.rb b/spec/lib/personas/tools/tool_spec.rb
similarity index 95%
rename from spec/lib/modules/ai_bot/tools/tool_spec.rb
rename to spec/lib/personas/tools/tool_spec.rb
index e7eca272..5896d8e3 100644
--- a/spec/lib/modules/ai_bot/tools/tool_spec.rb
+++ b/spec/lib/personas/tools/tool_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::Tool do
+RSpec.describe DiscourseAi::Personas::Tools::Tool do
let :tool_class do
described_class
end
diff --git a/spec/lib/modules/ai_bot/tools/update_artifact_spec.rb b/spec/lib/personas/tools/update_artifact_spec.rb
similarity index 92%
rename from spec/lib/modules/ai_bot/tools/update_artifact_spec.rb
rename to spec/lib/personas/tools/update_artifact_spec.rb
index f3d2a28f..3f8b7f06 100644
--- a/spec/lib/modules/ai_bot/tools/update_artifact_spec.rb
+++ b/spec/lib/personas/tools/update_artifact_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
+RSpec.describe DiscourseAi::Personas::Tools::UpdateArtifact do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
fab!(:post)
@@ -47,7 +47,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
persona_options: {
"update_algorithm" => "full",
},
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
result = tool.invoke {}
@@ -91,7 +91,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
persona_options: {
"update_algorithm" => "full",
},
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
result = tool.invoke {}
@@ -115,7 +115,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
{ artifact_id: artifact.id, instructions: "Invalid update" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
result = tool.invoke {}
@@ -129,7 +129,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
{ artifact_id: -1, instructions: "Update something" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
result = tool.invoke {}
@@ -155,7 +155,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
persona_options: {
"update_algorithm" => "full",
},
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
tool.invoke {}
@@ -186,7 +186,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
persona_options: {
"update_algorithm" => "full",
},
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
.invoke {}
end
@@ -212,7 +212,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
persona_options: {
"update_algorithm" => "full",
},
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
)
result = tool.invoke {}
@@ -262,7 +262,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
{ artifact_id: artifact.id, instructions: "Change the text to Updated and color to red" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
persona_options: {
"update_algorithm" => "diff",
},
@@ -330,7 +330,7 @@ RSpec.describe DiscourseAi::AiBot::Tools::UpdateArtifact do
{ artifact_id: artifact.id, instructions: "Change the text to Updated and color to red" },
bot_user: bot_user,
llm: llm_model.to_llm,
- context: DiscourseAi::AiBot::BotContext.new(messages: [], post: post),
+ context: DiscourseAi::Personas::BotContext.new(messages: [], post: post),
persona_options: {
"update_algorithm" => "diff",
},
diff --git a/spec/lib/modules/ai_bot/tools/web_browser_spec.rb b/spec/lib/personas/tools/web_browser_spec.rb
similarity index 98%
rename from spec/lib/modules/ai_bot/tools/web_browser_spec.rb
rename to spec/lib/personas/tools/web_browser_spec.rb
index 40e17c8c..aebd4e66 100644
--- a/spec/lib/modules/ai_bot/tools/web_browser_spec.rb
+++ b/spec/lib/personas/tools/web_browser_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe DiscourseAi::AiBot::Tools::WebBrowser do
+RSpec.describe DiscourseAi::Personas::Tools::WebBrowser do
fab!(:llm_model)
let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) }
let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
diff --git a/spec/models/ai_tool_spec.rb b/spec/models/ai_tool_spec.rb
index 45ec3175..30aa8a23 100644
--- a/spec/models/ai_tool_spec.rb
+++ b/spec/models/ai_tool_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe AiTool do
},
)
- expect { runner.invoke }.to raise_error(DiscourseAi::AiBot::ToolRunner::TooManyRequestsError)
+ expect { runner.invoke }.to raise_error(DiscourseAi::Personas::ToolRunner::TooManyRequestsError)
end
it "can perform GET HTTP requests" do
diff --git a/spec/requests/admin/ai_personas_controller_spec.rb b/spec/requests/admin/ai_personas_controller_spec.rb
index c9c036c0..c7989e28 100644
--- a/spec/requests/admin/ai_personas_controller_spec.rb
+++ b/spec/requests/admin/ai_personas_controller_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
expect(response.parsed_body["ai_personas"].length).to eq(AiPersona.count)
expect(response.parsed_body["meta"]["tools"].length).to eq(
- DiscourseAi::AiBot::Personas::Persona.all_available_tools.length,
+ DiscourseAi::Personas::Persona.all_available_tools.length,
)
end
@@ -136,10 +136,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
it "returns localized persona names and descriptions" do
get "/admin/plugins/discourse-ai/ai-personas.json"
- id =
- DiscourseAi::AiBot::Personas::Persona.system_personas[
- DiscourseAi::AiBot::Personas::General
- ]
+ id = DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General]
persona = response.parsed_body["ai_personas"].find { |p| p["id"] == id }
expect(persona["name"]).to eq("Général")
@@ -301,7 +298,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
end
it "does not allow temperature and top p changes on stock personas" do
- put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}.json",
+ put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}.json",
params: {
ai_persona: {
top_p: 0.5,
@@ -335,7 +332,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
context "with system personas" do
it "does not allow editing of system prompts" do
- put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}.json",
+ put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}.json",
params: {
ai_persona: {
system_prompt: "you are not a helpful bot",
@@ -348,7 +345,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
end
it "does not allow editing of tools" do
- put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}.json",
+ put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}.json",
params: {
ai_persona: {
tools: %w[SearchCommand ImageCommand],
@@ -361,7 +358,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
end
it "does not allow editing of name and description cause it is localized" do
- put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}.json",
+ put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}.json",
params: {
ai_persona: {
name: "bob",
@@ -375,7 +372,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
end
it "does allow some actions" do
- put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}.json",
+ put "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}.json",
params: {
ai_persona: {
allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_1]],
@@ -413,7 +410,7 @@ RSpec.describe DiscourseAi::Admin::AiPersonasController do
it "is not allowed to delete system personas" do
expect {
- delete "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}.json"
+ delete "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}.json"
expect(response).to have_http_status(:unprocessable_entity)
expect(response.parsed_body["errors"].join).not_to be_blank
# let's make sure this is translated
diff --git a/spec/system/admin_ai_persona_spec.rb b/spec/system/admin_ai_persona_spec.rb
index 79fd57e0..1fc48508 100644
--- a/spec/system/admin_ai_persona_spec.rb
+++ b/spec/system/admin_ai_persona_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe "Admin AI persona configuration", type: :system, js: true do
end
it "will not allow deletion or editing of system personas" do
- visit "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::AiBot::Personas::Persona.system_personas.values.first}/edit"
+ visit "/admin/plugins/discourse-ai/ai-personas/#{DiscourseAi::Personas::Persona.system_personas.values.first}/edit"
expect(page).not_to have_selector(".ai-persona-editor__delete")
expect(form.field("system_prompt")).to be_disabled
end
diff --git a/spec/system/ai_bot/persona_spec.rb b/spec/system/ai_bot/persona_spec.rb
index 6d1edf4b..1cf5e231 100644
--- a/spec/system/ai_bot/persona_spec.rb
+++ b/spec/system/ai_bot/persona_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe "AI personas", type: :system, js: true do
persona_selector =
PageObjects::Components::SelectKit.new(".persona-llm-selector__persona-dropdown")
- id = DiscourseAi::AiBot::Personas::Persona.all(user: admin).first.id
+ id = DiscourseAi::Personas::Persona.all(user: admin).first.id
expect(persona_selector).to have_selected_value(id)