Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 5c4fb04

Browse files
committed
Move more rag stuff into reusable components
1 parent 2f2b771 commit 5c4fb04

File tree

11 files changed

+80
-52
lines changed

11 files changed

+80
-52
lines changed

app/controllers/discourse_ai/admin/ai_personas_controller.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class AiPersonasController < ::Admin::AdminController
66
requires_plugin ::DiscourseAi::PLUGIN_NAME
77

88
before_action :find_ai_persona,
9-
only: %i[show update destroy create_user indexing_status_check]
9+
only: %i[show update destroy create_user]
1010

1111
def index
1212
ai_personas =
@@ -76,10 +76,6 @@ def destroy
7676
end
7777

7878

79-
def indexing_status_check
80-
render json: RagDocumentFragment.indexing_status(@ai_persona, @ai_persona.uploads)
81-
end
82-
8379
private
8480

8581
def find_ai_persona

app/controllers/discourse_ai/admin/rag_document_fragments_controller.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ module Admin
55
class RagDocumentFragmentsController < ::Admin::AdminController
66
requires_plugin ::DiscourseAi::PLUGIN_NAME
77

8+
def indexing_status_check
9+
if params[:target_type] == "AiPersona"
10+
@target = AiPersona.find(params[:target_id])
11+
elsif params[:target_type] == "AiTool"
12+
@target = AiTool.find(params[:target_id])
13+
else
14+
raise Discourse::InvalidParameters.new("Invalid target type")
15+
end
16+
17+
render json: RagDocumentFragment.indexing_status(@target, @target.uploads)
18+
end
19+
820
def upload_file
921
file = params[:file] || params[:files].first
1022

app/models/rag_document_fragment.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def indexing_status(persona, uploads)
7373

7474
def publish_status(upload, status)
7575
MessageBus.publish(
76-
"/discourse-ai/ai-persona-rag/#{upload.id}",
76+
"/discourse-ai/rag/#{upload.id}",
7777
status,
7878
user_ids: [upload.user_id],
7979
)

assets/javascripts/discourse/components/ai-persona-editor.gjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ export default class PersonaEditor extends Component {
488488
{{#if this.siteSettings.ai_embeddings_enabled}}
489489
<div class="control-group">
490490
<RagUploader
491-
@persona={{this.editingModel}}
491+
@target={{this.editingModel}}
492492
@updateUploads={{this.updateUploads}}
493493
@onRemove={{this.removeUpload}}
494494
/>

assets/javascripts/discourse/components/rag-upload-progress.gjs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,19 @@ import I18n from "discourse-i18n";
99

1010
export default class RagUploadProgress extends Component {
1111
@service messageBus;
12-
1312
@tracked updatedProgress = null;
1413

1514
willDestroy() {
1615
super.willDestroy(...arguments);
1716
this.messageBus.unsubscribe(
18-
`/discourse-ai/ai-persona-rag/${this.args.upload.id}`
17+
`/discourse-ai/rag/${this.args.upload.id}`
1918
);
2019
}
2120

2221
@action
2322
trackProgress() {
2423
this.messageBus.subscribe(
25-
`/discourse-ai/ai-persona-rag/${this.args.upload.id}`,
24+
`/discourse-ai/rag/${this.args.upload.id}`,
2625
this.onIndexingUpdate
2726
);
2827
}
@@ -72,18 +71,18 @@ export default class RagUploadProgress extends Component {
7271
{{#if this.fullyIndexed}}
7372
<span class="indexed">
7473
{{icon "check"}}
75-
{{I18n.t "discourse_ai.ai_persona.uploads.indexed"}}
74+
{{I18n.t "discourse_ai.rag.uploads.indexed"}}
7675
</span>
7776
{{else}}
7877
<span class="indexing">
7978
{{icon "robot"}}
80-
{{I18n.t "discourse_ai.ai_persona.uploads.indexing"}}
79+
{{I18n.t "discourse_ai.rag.uploads.indexing"}}
8180
{{this.calculateProgress}}%
8281
</span>
8382
{{/if}}
8483
{{else}}
8584
<span class="uploaded">{{I18n.t
86-
"discourse_ai.ai_persona.uploads.uploaded"
85+
"discourse_ai.rag.uploads.uploaded"
8786
}}</span>
8887
{{/if}}
8988
</td>

assets/javascripts/discourse/components/rag-uploader.gjs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import discourseDebounce from "discourse-common/lib/debounce";
1212
import I18n from "discourse-i18n";
1313
import RagUploadProgress from "./rag-upload-progress";
1414

15-
export default class RagUploader extends Component.extend(
16-
UppyUploadMixin
17-
) {
15+
export default class RagUploader extends Component.extend(UppyUploadMixin) {
1816
@service appEvents;
1917

2018
@tracked term = null;
@@ -33,12 +31,14 @@ export default class RagUploader extends Component.extend(
3331
this._uppyInstance?.cancelAll();
3432
}
3533

36-
this.ragUploads = this.persona?.rag_uploads || [];
34+
this.ragUploads = this.target?.rag_uploads || [];
3735
this.filteredUploads = this.ragUploads;
3836

39-
if (this.ragUploads?.length && this.persona?.id) {
37+
const targetName = this.target?.constructor?.name;
38+
39+
if (this.ragUploads?.length && this.target?.id) {
4040
ajax(
41-
`/admin/plugins/discourse-ai/ai-personas/${this.persona.id}/files/status.json`
41+
`/admin/plugins/discourse-ai/rag-document-fragments/files/status.json?target_type=${targetName}&target_id=${this.target.id}`
4242
).then((statuses) => {
4343
this.set("ragIndexingStatuses", statuses);
4444
});
@@ -47,7 +47,7 @@ export default class RagUploader extends Component.extend(
4747
this.appEvents.on(
4848
`upload-mixin:${this.id}:all-uploads-complete`,
4949
this,
50-
"_updatePersonaWithUploads"
50+
"_updateTargetWithUploads"
5151
);
5252
}
5353

@@ -56,18 +56,18 @@ export default class RagUploader extends Component.extend(
5656
this.appEvents.off(
5757
`upload-mixin:${this.id}:all-uploads-complete`,
5858
this,
59-
"_updatePersonaWithUploads"
59+
"_updateTargetWithUploads"
6060
);
6161
}
6262

63-
_updatePersonaWithUploads() {
63+
_updateTargetWithUploads() {
6464
this.updateUploads(this.ragUploads);
6565
}
6666

6767
uploadDone(uploadedFile) {
6868
const newUpload = uploadedFile.upload;
6969
newUpload.status = "uploaded";
70-
newUpload.statusText = I18n.t("discourse_ai.ai_persona.uploads.uploaded");
70+
newUpload.statusText = I18n.t("discourse_ai.rag.uploads.uploaded");
7171
this.ragUploads.pushObject(newUpload);
7272
this.debouncedSearch();
7373
}
@@ -113,19 +113,16 @@ export default class RagUploader extends Component.extend(
113113

114114
<template>
115115
<div class="rag-uploader">
116-
<h3>{{I18n.t "discourse_ai.ai_persona.uploads.title"}}</h3>
117-
<p>{{I18n.t "discourse_ai.ai_persona.uploads.description"}}</p>
116+
<h3>{{I18n.t "discourse_ai.rag.uploads.title"}}</h3>
117+
<p>{{I18n.t "discourse_ai.rag.uploads.description"}}</p>
118118

119119
{{#if this.ragUploads}}
120120
<div class="rag-uploader__search-input-container">
121121
<div class="rag-uploader__search-input">
122-
{{icon
123-
"search"
124-
class="rag-uploader__search-input__search-icon"
125-
}}
122+
{{icon "search" class="rag-uploader__search-input__search-icon"}}
126123
<Input
127124
class="rag-uploader__search-input__input"
128-
placeholder={{I18n.t "discourse_ai.ai_persona.uploads.filter"}}
125+
placeholder={{I18n.t "discourse_ai.rag.uploads.filter"}}
129126
@value={{this.term}}
130127
{{on "keyup" this.debouncedSearch}}
131128
/>
@@ -138,9 +135,7 @@ export default class RagUploader extends Component.extend(
138135
{{#each this.filteredUploads as |upload|}}
139136
<tr>
140137
<td>
141-
<span class="rag-uploader__rag-file-icon">{{icon
142-
"file"
143-
}}</span>
138+
<span class="rag-uploader__rag-file-icon">{{icon "file"}}</span>
144139
{{upload.original_filename}}
145140
</td>
146141
<RagUploadProgress
@@ -150,7 +145,7 @@ export default class RagUploader extends Component.extend(
150145
<td class="rag-uploader__remove-file">
151146
<DButton
152147
@icon="times"
153-
@title="discourse_ai.ai_persona.uploads.remove"
148+
@title="discourse_ai.rag.uploads.remove"
154149
@action={{fn this.removeUpload upload}}
155150
@class="btn-flat"
156151
/>
@@ -165,13 +160,13 @@ export default class RagUploader extends Component.extend(
165160
{{upload.original_filename}}</td>
166161
<td class="rag-uploader__upload-status">
167162
<div class="spinner small"></div>
168-
<span>{{I18n.t "discourse_ai.ai_persona.uploads.uploading"}}
163+
<span>{{I18n.t "discourse_ai.rag.uploads.uploading"}}
169164
{{upload.uploadProgress}}%</span>
170165
</td>
171166
<td class="rag-uploader__remove-file">
172167
<DButton
173168
@icon="times"
174-
@title="discourse_ai.ai_persona.uploads.remove"
169+
@title="discourse_ai.rag.uploads.remove"
175170
@action={{fn this.cancelUploading upload}}
176171
@class="btn-flat"
177172
/>
@@ -189,9 +184,9 @@ export default class RagUploader extends Component.extend(
189184
accept=".txt,.md"
190185
/>
191186
<DButton
192-
@label="discourse_ai.ai_persona.uploads.button"
187+
@label="discourse_ai.rag.uploads.button"
193188
@icon="plus"
194-
@title="discourse_ai.ai_persona.uploads.button"
189+
@title="discourse_ai.rag.uploads.button"
195190
@action={{this.submitFiles}}
196191
class="btn-default"
197192
/>

config/locales/client.en.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,10 @@ en:
178178
179179
Moreover, you can set it up so that certain user groups have access to specific personas. This means you can have different AI behaviors for different sections of your forum, further enhancing the diversity and richness of your community's interactions.
180180
181+
rag:
181182
uploads:
182183
title: "Uploads"
183-
description: "Your AI persona will be able to search and reference the content of included files. Uploaded files should be formatted as plaintext (.txt) or markdown (.md)."
184+
description: "Uploaded files should be formatted as plaintext (.txt) or markdown (.md)."
184185
button: "Add Files"
185186
filter: "Filter uploads"
186187
indexed: "Indexed"

config/routes.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,13 @@
5454
) { post :test, on: :collection }
5555

5656
post "/ai-personas/:id/create-user", to: "discourse_ai/admin/ai_personas#create_user"
57-
post "/rag-document-fragments/files/upload", to: "discourse_ai/admin/rag_document_fragments#upload_file"
57+
5858
put "/ai-personas/:id/files/remove", to: "discourse_ai/admin/ai_personas#remove_file"
5959
get "/ai-personas/:id/files/status", to: "discourse_ai/admin/ai_personas#indexing_status_check"
6060

61+
post "/rag-document-fragments/files/upload", to: "discourse_ai/admin/rag_document_fragments#upload_file"
62+
get "/rag-document-fragments/files/status", to: "discourse_ai/admin/rag_document_fragments#indexing_status_check"
63+
6164
resources :ai_llms,
6265
only: %i[index create show update destroy],
6366
path: "ai-llms",

spec/jobs/regular/generate_rag_embeddings_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
it "sends an update through mb after a batch finishes" do
4040
updates =
4141
MessageBus.track_publish(
42-
"/discourse-ai/ai-persona-rag/#{rag_document_fragment_1.upload_id}",
42+
"/discourse-ai/rag/#{rag_document_fragment_1.upload_id}",
4343
) { subject.execute(fragment_ids: [rag_document_fragment_1.id]) }
4444

4545
upload_index_stats = updates.last.data

spec/requests/admin/ai_personas_controller_spec.rb

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -369,17 +369,6 @@
369369
end
370370
end
371371

372-
describe "POST #upload_file" do
373-
it "works" do
374-
post "/admin/plugins/discourse-ai/ai-personas/files/upload.json",
375-
params: {
376-
file: Rack::Test::UploadedFile.new(file_from_fixtures("spec.txt", "md")),
377-
}
378-
379-
expect(response.status).to eq(200)
380-
end
381-
end
382-
383372
describe "DELETE #destroy" do
384373
it "destroys the requested ai_persona" do
385374
expect {

0 commit comments

Comments
 (0)