Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
822594f3e3 | ||
|
|
7dee59c97f | ||
|
|
fbbe01e576 | ||
|
|
f420261196 | ||
|
|
eb93e1736b | ||
|
|
cc34882074 | ||
|
|
4b03cdcc96 | ||
|
|
d9b53b4a3d | ||
|
|
a927fd2270 | ||
|
|
f077d58abf | ||
|
|
08d2f3ddf9 | ||
|
|
273a1fa618 | ||
|
|
7af3ce820d | ||
|
|
5841543bd9 | ||
|
|
5ae80645bb | ||
|
|
b675c4c39b | ||
|
|
0fadf1da1a | ||
|
|
c26d604072 | ||
|
|
7ae61ce877 | ||
|
|
f593ab6e1e | ||
|
|
b58f198ee8 | ||
|
|
88811f97bf | ||
|
|
2377b286dd | ||
|
|
8da4318021 | ||
|
|
b6a88ff03e | ||
|
|
f366ded03b | ||
|
|
87c42145d4 | ||
|
|
c49f1df2ba | ||
|
|
b46940fc66 | ||
|
|
249aab100c | ||
|
|
5a29074799 | ||
|
|
29d415755a | ||
|
|
5a590fddc1 | ||
|
|
cad39c1aa4 | ||
|
|
2592be65ff |
@@ -1,4 +1,3 @@
|
||||
< 3.5.0.beta8-dev: 5d80a34589d63e381d80273828072badc18955b1
|
||||
< 3.5.0.beta7-dev: cd14b0c0bee0cf63c59b64b6f7213e31a37f11a7
|
||||
< 3.5.0.beta6-dev: 3e74eea1e5e3143888d67a8d8a11206df214dc24
|
||||
< 3.5.0.beta3-dev: 09a68414804a1447f52e5d60691ba59742cda9ec
|
||||
|
||||
@@ -40,7 +40,7 @@ module Jobs
|
||||
return if locales.blank?
|
||||
|
||||
locales.each do |locale|
|
||||
next if LocaleNormalizer.is_same?(locale, detected_locale)
|
||||
next if DiscourseAi::Translation::LocaleNormalizer.is_same?(locale, detected_locale)
|
||||
regionless_locale = locale.split("_").first
|
||||
next if post.post_localizations.where("locale LIKE ?", "#{regionless_locale}%").exists?
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ module Jobs
|
||||
return if locales.blank?
|
||||
|
||||
locales.each do |locale|
|
||||
next if LocaleNormalizer.is_same?(locale, detected_locale)
|
||||
next if DiscourseAi::Translation::LocaleNormalizer.is_same?(locale, detected_locale)
|
||||
regionless_locale = locale.split("_").first
|
||||
next if topic.topic_localizations.where("locale LIKE ?", "#{regionless_locale}%").exists?
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ module Jobs
|
||||
missing_locales = locales - existing_locales - [category.locale]
|
||||
missing_locales.each do |locale|
|
||||
break if remaining_limit <= 0
|
||||
next if LocaleNormalizer.is_same?(locale, category.locale)
|
||||
next if DiscourseAi::Translation::LocaleNormalizer.is_same?(locale, category.locale)
|
||||
|
||||
begin
|
||||
DiscourseAi::Translation::CategoryLocalizer.localize(category, locale)
|
||||
|
||||
@@ -12,7 +12,6 @@ class AiPersona < ActiveRecord::Base
|
||||
validates :system_prompt, presence: true, length: { maximum: 10_000_000 }
|
||||
validate :system_persona_unchangeable, on: :update, if: :system
|
||||
validate :chat_preconditions
|
||||
validate :allowed_seeded_model, if: :default_llm_id
|
||||
validate :well_formated_examples
|
||||
validates :max_context_posts, numericality: { greater_than: 0 }, allow_nil: true
|
||||
# leaves some room for growth but sets a maximum to avoid memory issues
|
||||
@@ -365,17 +364,6 @@ class AiPersona < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def allowed_seeded_model
|
||||
return if default_llm_id.blank?
|
||||
|
||||
return if default_llm.nil?
|
||||
return if !default_llm.seeded?
|
||||
|
||||
return if SiteSetting.ai_bot_allowed_seeded_models_map.include?(default_llm.id.to_s)
|
||||
|
||||
errors.add(:default_llm, I18n.t("discourse_ai.llm.configuration.invalid_seeded_model"))
|
||||
end
|
||||
|
||||
def well_formated_examples
|
||||
return if examples.blank?
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ class LlmModel < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def identifier
|
||||
"custom:#{id}"
|
||||
"#{id}"
|
||||
end
|
||||
|
||||
def toggle_companion_user
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import SiteSettingComponent from "admin/components/site-setting";
|
||||
import SiteSetting from "admin/models/site-setting";
|
||||
|
||||
export default class AiDefaultLlmSelector extends Component {
|
||||
@tracked defaultLlmSetting = null;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.#loadDefaultLlmSetting();
|
||||
}
|
||||
|
||||
async #loadDefaultLlmSetting() {
|
||||
const { site_settings } = await ajax("/admin/config/site_settings.json", {
|
||||
data: {
|
||||
plugin: "discourse-ai",
|
||||
category: "discourse_ai",
|
||||
},
|
||||
});
|
||||
|
||||
const defaultLlmSetting = site_settings.find(
|
||||
(setting) => setting.setting === "ai_default_llm_model"
|
||||
);
|
||||
|
||||
this.defaultLlmSetting = SiteSetting.create(defaultLlmSetting);
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="ai-configure-default-llm">
|
||||
<div class="ai-configure-default-llm__header">
|
||||
<h3>{{i18n "discourse_ai.default_llm.title"}}</h3>
|
||||
<p>{{i18n "discourse_ai.default_llm.description"}}</p>
|
||||
</div>
|
||||
|
||||
{{#if this.defaultLlmSetting}}
|
||||
<SiteSettingComponent
|
||||
@setting={{this.defaultLlmSetting}}
|
||||
class="ai-configure-default-llm__setting"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import DPageSubheader from "discourse/components/d-page-subheader";
|
||||
import DSelect from "discourse/components/d-select";
|
||||
import FilterInput from "discourse/components/filter-input";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import AiDefaultLlmSelector from "./ai-default-llm-selector";
|
||||
import AiFeaturesList from "./ai-features-list";
|
||||
|
||||
const ALL = "all";
|
||||
@@ -202,6 +203,8 @@ export default class AiFeatures extends Component {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<AiDefaultLlmSelector />
|
||||
|
||||
{{#if this.filteredFeatures.length}}
|
||||
<AiFeaturesList @modules={{this.filteredFeatures}} />
|
||||
{{else}}
|
||||
|
||||
@@ -9,6 +9,7 @@ import I18n, { i18n } from "discourse-i18n";
|
||||
import AdminSectionLandingItem from "admin/components/admin-section-landing-item";
|
||||
import AdminSectionLandingWrapper from "admin/components/admin-section-landing-wrapper";
|
||||
import DTooltip from "float-kit/components/d-tooltip";
|
||||
import AiDefaultLlmSelector from "./ai-default-llm-selector";
|
||||
import AiLlmEditor from "./ai-llm-editor";
|
||||
|
||||
function isPreseeded(llm) {
|
||||
@@ -137,6 +138,9 @@ export default class AiLlmsListEditor extends Component {
|
||||
}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/discourse-ai-large-language-model-llm-settings-page/319903"
|
||||
/>
|
||||
|
||||
<AiDefaultLlmSelector />
|
||||
|
||||
{{#if this.hasLlmElements}}
|
||||
<section class="ai-llms-list-editor__configured">
|
||||
<DPageSubheader
|
||||
|
||||
@@ -90,7 +90,7 @@ export default class AiSpam extends Component {
|
||||
this.isEnabled = model.is_enabled;
|
||||
|
||||
if (model.llm_id) {
|
||||
this.selectedLLM = "custom:" + model.llm_id;
|
||||
this.selectedLLM = model.llm_id;
|
||||
} else {
|
||||
if (this.availableLLMs.length) {
|
||||
this.selectedLLM = this.availableLLMs[0].id;
|
||||
@@ -127,7 +127,7 @@ export default class AiSpam extends Component {
|
||||
}
|
||||
|
||||
get llmId() {
|
||||
return this.selectedLLM.toString().split(":")[1];
|
||||
return this.selectedLLM;
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@@ -158,3 +158,51 @@
|
||||
.ai-expanded-list__toggle-button {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ai-configure-default-llm {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
background: var(--primary-very-low);
|
||||
padding: 1rem;
|
||||
margin-block: 1rem;
|
||||
border-radius: var(--d-border-radius);
|
||||
|
||||
&__header {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
&__setting {
|
||||
flex: 2;
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.setting-controls__undo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: var(--primary);
|
||||
font-size: var(--font-0);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
font-size: var(--font-down-1);
|
||||
color: var(--primary-high-or-secondary-low);
|
||||
}
|
||||
|
||||
.select-kit,
|
||||
.btn {
|
||||
font-size: var(--font-down-1);
|
||||
}
|
||||
|
||||
.setting-label,
|
||||
.desc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,9 +110,6 @@ de:
|
||||
top_p:
|
||||
label: "Top P"
|
||||
description: "Top P für die LLM, erhöhen, um die Zufälligkeit zu erhöhen (leer lassen, um das Standardmodell zu verwenden)"
|
||||
persona_id:
|
||||
label: "Persona"
|
||||
description: "KI Persona zur Berichtserstellung"
|
||||
llm_tool_triage:
|
||||
fields:
|
||||
model:
|
||||
@@ -182,9 +179,6 @@ de:
|
||||
temperature:
|
||||
label: "Temperatur"
|
||||
description: "Temperatur, die für das LLM verwendet werden soll. Erhöhen, um die Zufälligkeit zu erhöhen (leer lassen, um das Standardmodell zu verwenden)"
|
||||
max_output_tokens:
|
||||
label: "Maximale Ausgabetoken"
|
||||
description: "Wenn angegeben, wird eine Obergrenze für die maximale Anzahl von Token festgelegt, die das Modell erzeugen kann. Beachtet die Obergrenze für die Anzahl der ausgegebenen Token des LLM"
|
||||
discourse_ai:
|
||||
title: "KI"
|
||||
features:
|
||||
@@ -842,7 +836,6 @@ de:
|
||||
last_7_days: "Letzte 7 Tage"
|
||||
last_30_days: "Letzte 30 Tage"
|
||||
upload_files: "Dateien hochladen"
|
||||
uploads_in_progress: "Absenden nicht möglich, solange Uploads nicht abgeschlossen sind"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "Stimmung"
|
||||
|
||||
@@ -180,13 +180,14 @@ en:
|
||||
temperature:
|
||||
label: "Temperature"
|
||||
description: "Temperature to use for the LLM. Increase to increase randomness (leave empty to use model default)"
|
||||
max_output_tokens:
|
||||
label: "Max output tokens"
|
||||
description: "When specified, sets an upper bound to the maximum number of tokens the model can generate. Respects LLM's max output tokens limit"
|
||||
|
||||
discourse_ai:
|
||||
title: "AI"
|
||||
|
||||
default_llm:
|
||||
title: "Default LLM model"
|
||||
description: "The default LLM model to use for all AI features. This will be used if no LLM is specified in the feature configuration or persona. If no default LLM is specified, the last created LLM will be used."
|
||||
|
||||
features:
|
||||
short_title: "Features"
|
||||
description: "These are the AI features available to visitors on your site. These can be configured to use specific personas and LLMs, and can be access controlled by groups."
|
||||
@@ -569,7 +570,7 @@ en:
|
||||
max_usages_required: "Must be set if max tokens is not set"
|
||||
usage:
|
||||
ai_bot: "AI bot"
|
||||
ai_helper: "Helper"
|
||||
ai_helper: "Helper (%{persona})"
|
||||
ai_helper_image_caption: "Image caption"
|
||||
ai_persona: "Persona (%{persona})"
|
||||
ai_summarization: "Summarize"
|
||||
|
||||
@@ -109,9 +109,6 @@ he:
|
||||
top_p:
|
||||
label: "ה־P המובילים"
|
||||
description: "ה־P המוביל לשימוש למודל השפה הגדול (LLM), הגדלה תגדיל את האקראיות (להשאיר ריק כדי להשתמש בברירת המחדל של הדגם)"
|
||||
persona_id:
|
||||
label: "דמות"
|
||||
description: "דמות בינה מלאכותית לשימוש להפקת דוחות"
|
||||
llm_tool_triage:
|
||||
fields:
|
||||
model:
|
||||
@@ -170,8 +167,6 @@ he:
|
||||
temperature:
|
||||
label: "טמפרטורה"
|
||||
description: "טמפרטורה לשימוש למודל השפה הגדול (LLM), הגדלה תגדיל את האקראיות (להשאיר ריק כדי להשתמש בברירת המחדל של הדגם)"
|
||||
max_output_tokens:
|
||||
label: "כמות אסימוני פלט מרבית"
|
||||
discourse_ai:
|
||||
title: "בינה מלאכותית"
|
||||
features:
|
||||
@@ -778,7 +773,6 @@ he:
|
||||
last_7_days: "7 הימים האחרונים"
|
||||
last_30_days: "30 הימים האחרונים"
|
||||
upload_files: "העלאת קבצים"
|
||||
uploads_in_progress: "לא ניתן להגיש תוך כדי שמתבצעות העלאות"
|
||||
sentiments:
|
||||
dashboard:
|
||||
title: "רגש"
|
||||
|
||||
@@ -110,8 +110,6 @@ lt:
|
||||
top_p:
|
||||
label: "Viršutinė P"
|
||||
description: "Viršutinė P, naudojama LLM, padidinkite, kad padidėtų atsitiktinumas (palikite tuščią, jei norite naudoti numatytuosius modelio parametrus)"
|
||||
persona_id:
|
||||
label: "Persona"
|
||||
llm_tool_triage:
|
||||
fields:
|
||||
model:
|
||||
|
||||
@@ -88,8 +88,6 @@ pl_PL:
|
||||
temperature:
|
||||
label: "Temperatura"
|
||||
description: "Temperatura używana dla LLM. Zwiększ, aby zwiększyć losowość (pozostaw puste, aby użyć domyślnego modelu)."
|
||||
persona_id:
|
||||
label: "Osobowość"
|
||||
llm_tool_triage:
|
||||
fields:
|
||||
model:
|
||||
|
||||
@@ -94,8 +94,6 @@ zh_CN:
|
||||
top_p:
|
||||
label: "Top P"
|
||||
description: "用于 LLM 的 Top P 值,增加该值会提高生成内容的随机性(留空则使用模型默认值)"
|
||||
persona_id:
|
||||
label: "角色模型"
|
||||
llm_tool_triage:
|
||||
fields:
|
||||
model:
|
||||
|
||||
@@ -384,9 +384,6 @@ de:
|
||||
content_creator:
|
||||
name: "Inhaltsersteller"
|
||||
description: "Standard-Persona für die HyDE-Suche"
|
||||
report_runner:
|
||||
name: "Berichtsausführer"
|
||||
description: "Standard-Persona, die im Automatisierungsskript für Berichte verwendet wird."
|
||||
topic_not_found: "Zusammenfassung nicht verfügbar, Thema nicht gefunden!"
|
||||
summarizing: "Thema zusammenfassen"
|
||||
searching: "Suche nach: „%{query}“"
|
||||
|
||||
@@ -25,6 +25,7 @@ en:
|
||||
description: "Periodic report based on a large language model"
|
||||
site_settings:
|
||||
discourse_ai_enabled: "Enable the discourse AI plugin."
|
||||
ai_default_llm_model: "The default LLM model to use for all AI features"
|
||||
ai_artifact_security: "The AI artifact system generates IFRAMEs with runnable code. Strict mode forces an extra click to run code. Lax mode runs code immediately. Hybrid mode allows user to supply data-ai-artifact-autorun to show right away. Disabled mode disables the artifact system."
|
||||
ai_toxicity_enabled: "Enable the toxicity module."
|
||||
ai_toxicity_inference_service_api_endpoint: "URL where the API is running for the toxicity module"
|
||||
@@ -582,7 +583,7 @@ en:
|
||||
llm:
|
||||
configuration:
|
||||
create_llm: "You need to setup an LLM before enabling this feature"
|
||||
disable_module_first: "You have to disable %{setting} first."
|
||||
disable_modules_first: "You must disable these modules first: %{settings}"
|
||||
set_llm_first: "Set %{setting} first"
|
||||
model_unreachable: "We couldn't get a response from this model. Check your settings first."
|
||||
invalid_seeded_model: "You can't use this model with this feature"
|
||||
|
||||
@@ -302,9 +302,6 @@ he:
|
||||
name: "בקשה מותאמת אישית"
|
||||
smart_dates:
|
||||
name: "תאריכים חכמים"
|
||||
report_runner:
|
||||
name: "אצן דוחות"
|
||||
description: "דמות ברירת המחדל שסקריפט אוטומציית הדוחות משתמש בה"
|
||||
topic_not_found: "תקציר לא זמין, לא נמצא נושא!"
|
||||
summarizing: "הנושא מסוכם"
|
||||
searching: "חיפוש אחר: ‚%{query}’"
|
||||
|
||||
+12
-10
@@ -11,6 +11,12 @@ discourse_ai:
|
||||
- "lax"
|
||||
- "hybrid"
|
||||
- "strict"
|
||||
ai_default_llm_model:
|
||||
default: ""
|
||||
type: enum
|
||||
allow_any: false
|
||||
enum: "DiscourseAi::Configuration::LlmEnumerator"
|
||||
validator: "DiscourseAi::Configuration::LlmValidator"
|
||||
|
||||
ai_sentiment_enabled:
|
||||
default: false
|
||||
@@ -103,7 +109,7 @@ discourse_ai:
|
||||
default: false
|
||||
client: true
|
||||
area: "ai-features/ai_helper"
|
||||
ai_helper_model:
|
||||
ai_helper_model: # Deprecated. TODO(keegan): Remove 2025-09-01
|
||||
default: ""
|
||||
allow_any: false
|
||||
type: enum
|
||||
@@ -149,7 +155,7 @@ discourse_ai:
|
||||
- "context_menu"
|
||||
- "image_caption"
|
||||
area: "ai-features/ai_helper"
|
||||
ai_helper_image_caption_model:
|
||||
ai_helper_image_caption_model: # Deprecated. TODO(keegan): Remove 2025-09-01
|
||||
default: ""
|
||||
type: enum
|
||||
enum: "DiscourseAi::Configuration::LlmVisionEnumerator"
|
||||
@@ -260,12 +266,12 @@ discourse_ai:
|
||||
client: true
|
||||
validator: "DiscourseAi::Configuration::LlmDependencyValidator"
|
||||
area: "ai-features/embeddings"
|
||||
ai_embeddings_semantic_search_hyde_model:
|
||||
ai_embeddings_semantic_search_hyde_model: # Deprecated. TODO(keegan): Remove 2025-09-01
|
||||
hidden: true
|
||||
default: ""
|
||||
type: enum
|
||||
allow_any: false
|
||||
enum: "DiscourseAi::Configuration::LlmEnumerator"
|
||||
validator: "DiscourseAi::Configuration::LlmValidator"
|
||||
area: "ai-features/embeddings"
|
||||
ai_embeddings_semantic_search_hyde_model_allowed_seeded_models:
|
||||
default: ""
|
||||
@@ -316,12 +322,11 @@ discourse_ai:
|
||||
client: true
|
||||
validator: "DiscourseAi::Configuration::LlmDependencyValidator"
|
||||
area: "ai-features/summarization"
|
||||
ai_summarization_model:
|
||||
ai_summarization_model: # Deprecated. TODO(keegan): Remove 2025-09-01
|
||||
default: ""
|
||||
allow_any: false
|
||||
type: enum
|
||||
enum: "DiscourseAi::Configuration::LlmEnumerator"
|
||||
validator: "DiscourseAi::Configuration::LlmValidator"
|
||||
hidden: true
|
||||
ai_summarization_persona:
|
||||
default: "-11"
|
||||
@@ -483,12 +488,11 @@ discourse_ai:
|
||||
client: true
|
||||
validator: "DiscourseAi::Configuration::LlmDependencyValidator"
|
||||
area: "ai-features/translation"
|
||||
ai_translation_model:
|
||||
ai_translation_model: # Deprecated. TODO(keegan): Remove 2025-09-01
|
||||
default: ""
|
||||
type: enum
|
||||
allow_any: false
|
||||
enum: "DiscourseAi::Configuration::LlmEnumerator"
|
||||
validator: "DiscourseAi::Configuration::LlmValidator"
|
||||
area: "ai-features/translation"
|
||||
ai_translation_locale_detector_persona:
|
||||
default: "-27"
|
||||
@@ -527,8 +531,6 @@ discourse_ai:
|
||||
area: "ai-features/translation"
|
||||
ai_translation_backfill_max_age_days:
|
||||
default: 5
|
||||
min: 0
|
||||
max: 20000
|
||||
client: false
|
||||
area: "ai-features/translation"
|
||||
ai_translation_verbose_logs:
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
class SeedAiDefaultLlmModel < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
return if DB.query_single("SELECT 1 FROM llm_models LIMIT 1").empty?
|
||||
|
||||
last_model_id = DB.query_single("SELECT id FROM llm_models ORDER BY id DESC LIMIT 1").first
|
||||
|
||||
if last_model_id.present?
|
||||
execute "UPDATE site_settings SET value = '#{last_model_id}' WHERE name = 'ai_default_llm_model' AND (value IS NULL OR value = '');"
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
# frozen_string_literal: true
|
||||
class CopyAiSummarizationModelToPersonaDefault < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
ai_summarization_model =
|
||||
DB.query_single("SELECT value FROM site_settings WHERE name = 'ai_summarization_model'").first
|
||||
|
||||
if ai_summarization_model.present? && ai_summarization_model.start_with?("custom:")
|
||||
# Extract the model ID from the setting value (e.g., "custom:-5" -> "-5")
|
||||
model_id = ai_summarization_model.split(":").last
|
||||
|
||||
persona_settings = %w[ai_summarization_persona ai_summary_gists_persona]
|
||||
default_persona_ids = [-11, -12]
|
||||
|
||||
persona_ids_query =
|
||||
persona_settings
|
||||
.map { |setting| "SELECT value FROM site_settings WHERE name = '#{setting}'" }
|
||||
.join(" UNION ")
|
||||
persona_ids = DB.query_single(persona_ids_query).compact
|
||||
all_persona_ids = (default_persona_ids + persona_ids).map(&:to_i).uniq.join(",")
|
||||
|
||||
# Update the summarization personas with the extracted model ID
|
||||
execute(<<~SQL)
|
||||
UPDATE ai_personas
|
||||
SET default_llm_id = #{model_id}
|
||||
WHERE id IN (#{all_persona_ids}) AND default_llm_id IS NULL
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
class CopyAiHelperModelToPersonaDefault < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
ai_helper_model =
|
||||
DB.query_single("SELECT value FROM site_settings WHERE name = 'ai_helper_model'").first
|
||||
|
||||
if ai_helper_model.present? && ai_helper_model.start_with?("custom:")
|
||||
# Extract the model ID from the setting value (e.g., "custom:1" -> "1")
|
||||
model_id = ai_helper_model.split(":").last
|
||||
|
||||
# Get persona IDs from site settings
|
||||
persona_settings = %w[
|
||||
ai_helper_proofreader_persona
|
||||
ai_helper_title_suggestions_persona
|
||||
ai_helper_explain_persona
|
||||
ai_helper_smart_dates_persona
|
||||
ai_helper_translator_persona
|
||||
ai_helper_markdown_tables_persona
|
||||
ai_helper_custom_prompt_persona
|
||||
]
|
||||
|
||||
default_persona_ids = [-18, -19, -20, -22, -23, -24, -25]
|
||||
persona_ids_query =
|
||||
persona_settings
|
||||
.map { |setting| "SELECT value FROM site_settings WHERE name = '#{setting}'" }
|
||||
.join(" UNION ")
|
||||
persona_ids = DB.query_single(persona_ids_query).compact
|
||||
|
||||
all_persona_ids = (default_persona_ids + persona_ids).map(&:to_i).uniq.join(",")
|
||||
|
||||
# Update the helper personas with the extracted model ID
|
||||
execute(<<~SQL)
|
||||
UPDATE ai_personas
|
||||
SET default_llm_id = #{model_id}
|
||||
WHERE id IN (#{all_persona_ids}) AND default_llm_id IS NULL
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
class CopyHydeModelToPersona < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
hyde_model =
|
||||
DB.query_single(
|
||||
"SELECT value FROM site_settings WHERE name = 'ai_embeddings_semantic_search_hyde_model'",
|
||||
).first
|
||||
|
||||
if hyde_model.present? && hyde_model.start_with?("custom:")
|
||||
# Extract the model ID from the setting value (e.g., "custom:1" -> "1")
|
||||
model_id = hyde_model.split(":").last
|
||||
|
||||
persona_settings = %w[ai_embeddings_semantic_search_hyde_persona]
|
||||
default_persona_ids = [-32]
|
||||
persona_ids_query =
|
||||
persona_settings
|
||||
.map { |setting| "SELECT value FROM site_settings WHERE name = '#{setting}'" }
|
||||
.join(" UNION ")
|
||||
persona_ids = DB.query_single(persona_ids_query).compact
|
||||
|
||||
all_persona_ids = (default_persona_ids + persona_ids).map(&:to_i).uniq.join(",")
|
||||
|
||||
# Update the hyde persona with the extracted model ID
|
||||
execute(<<~SQL)
|
||||
UPDATE ai_personas
|
||||
SET default_llm_id = #{model_id}
|
||||
WHERE id IN (#{all_persona_ids}) AND default_llm_id IS NULL
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
class CopyTranslationModelToPersona < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
ai_translation_model =
|
||||
DB.query_single("SELECT value FROM site_settings WHERE name = 'ai_translation_model'").first
|
||||
|
||||
if ai_translation_model.present? && ai_translation_model.start_with?("custom:")
|
||||
# Extract the model ID from the setting value (e.g., "custom:-5" -> "-5")
|
||||
model_id = ai_translation_model.split(":").last
|
||||
|
||||
persona_settings = %w[
|
||||
ai_translation_locale_detector_persona
|
||||
ai_translation_post_raw_translator_persona
|
||||
ai_translation_topic_title_translator_persona
|
||||
ai_translation_short_text_translator_persona
|
||||
]
|
||||
default_persona_ids = [-27, -28, -29, -30]
|
||||
|
||||
persona_ids_query =
|
||||
persona_settings
|
||||
.map { |setting| "SELECT value FROM site_settings WHERE name = '#{setting}'" }
|
||||
.join(" UNION ")
|
||||
persona_ids = DB.query_single(persona_ids_query).compact
|
||||
|
||||
all_persona_ids = (default_persona_ids + persona_ids).map(&:to_i).uniq.join(",")
|
||||
|
||||
# Update the translation personas (IDs -27, -28, -29, -30) with the extracted model ID
|
||||
execute(<<~SQL)
|
||||
UPDATE ai_personas
|
||||
SET default_llm_id = #{model_id}
|
||||
WHERE id IN (#{all_persona_ids}) AND default_llm_id IS NULL
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
class CopyAiImageCaptionModelToPersonaDefault < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
ai_helper_image_caption_model =
|
||||
DB.query_single(
|
||||
"SELECT value FROM site_settings WHERE name = 'ai_helper_image_caption_model'",
|
||||
).first
|
||||
|
||||
if ai_helper_image_caption_model.present? &&
|
||||
ai_helper_image_caption_model.start_with?("custom:")
|
||||
# Extract the model ID from the setting value (e.g., "custom:1" -> "1")
|
||||
model_id = ai_helper_image_caption_model.split(":").last
|
||||
|
||||
persona_settings = %w[ai_helper_post_illustrator_persona ai_helper_image_caption_persona]
|
||||
default_persona_ids = [-21, -26]
|
||||
|
||||
persona_ids_query =
|
||||
persona_settings
|
||||
.map { |setting| "SELECT value FROM site_settings WHERE name = '#{setting}'" }
|
||||
.join(" UNION ")
|
||||
persona_ids = DB.query_single(persona_ids_query).compact
|
||||
|
||||
all_persona_ids = (default_persona_ids + persona_ids).map(&:to_i).uniq.join(",")
|
||||
|
||||
# Update the helper personas with the extracted model ID
|
||||
execute(<<~SQL)
|
||||
UPDATE ai_personas
|
||||
SET default_llm_id = #{model_id}
|
||||
WHERE id IN (#{all_persona_ids}) AND default_llm_id IS NULL
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
class SetTranslationBackfillMaxAge < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
execute <<~SQL
|
||||
UPDATE site_settings
|
||||
SET value = '20000'
|
||||
WHERE name = 'ai_translation_backfill_max_age_days'
|
||||
AND value::integer > 20000;
|
||||
SQL
|
||||
|
||||
execute <<~SQL
|
||||
UPDATE site_settings
|
||||
SET value = '0'
|
||||
WHERE name = 'ai_translation_backfill_max_age_days'
|
||||
AND value::integer < 0;
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexToAiTopicsEmbeddings < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
add_index :ai_topics_embeddings, %i[topic_id model_id]
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -24,7 +24,6 @@ if defined?(DiscourseAutomation)
|
||||
field :max_post_tokens, component: :text
|
||||
field :stop_sequences, component: :text_list, required: false
|
||||
field :temperature, component: :text
|
||||
field :max_output_tokens, component: :text
|
||||
|
||||
# Actions
|
||||
field :category, component: :category
|
||||
@@ -86,9 +85,6 @@ if defined?(DiscourseAutomation)
|
||||
temperature = temperature.to_f
|
||||
end
|
||||
|
||||
max_output_tokens = fields.dig("max_output_tokens", "value").to_i
|
||||
max_output_tokens = nil if max_output_tokens <= 0
|
||||
|
||||
max_post_tokens = nil if max_post_tokens <= 0
|
||||
|
||||
stop_sequences = fields.dig("stop_sequences", "value")
|
||||
@@ -126,7 +122,6 @@ if defined?(DiscourseAutomation)
|
||||
stop_sequences: stop_sequences,
|
||||
automation: self.automation,
|
||||
temperature: temperature,
|
||||
max_output_tokens: max_output_tokens,
|
||||
action: context["action"],
|
||||
)
|
||||
rescue => e
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user