diff --git a/src/public/app/widgets/type_widgets/options/ai_settings.ts b/src/public/app/widgets/type_widgets/options/ai_settings.ts
index 3563ff07c..de76f5de3 100644
--- a/src/public/app/widgets/type_widgets/options/ai_settings.ts
+++ b/src/public/app/widgets/type_widgets/options/ai_settings.ts
@@ -238,6 +238,13 @@ export default class AiSettingsWidget extends OptionsWidget {
@@ -461,6 +468,25 @@ export default class AiSettingsWidget extends OptionsWidget {
}
});
+ const $reprocessIndex = this.$widget.find('.reprocess-index');
+ $reprocessIndex.on('click', async () => {
+ $reprocessIndex.prop('disabled', true);
+ $reprocessIndex.text(t("ai_llm.reprocessing_index"));
+
+ try {
+ await server.post('embeddings/rebuild-index');
+ toastService.showMessage(t("ai_llm.reprocess_index_started"));
+ // Refresh stats after reprocessing starts
+ await this.refreshEmbeddingStats();
+ } catch (error) {
+ console.error("Error rebuilding index:", error);
+ toastService.showError(t("ai_llm.reprocess_index_error"));
+ } finally {
+ $reprocessIndex.prop('disabled', false);
+ $reprocessIndex.text(t("ai_llm.reprocess_index"));
+ }
+ });
+
const $embeddingRefreshStats = this.$widget.find('.embedding-refresh-stats');
$embeddingRefreshStats.on('click', async () => {
await this.refreshEmbeddingStats();
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 9d675a234..b68881c1c 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1161,6 +1161,7 @@
"enable_auto_update_embeddings_description": "Automatically update embeddings when notes are modified",
"auto_update_embeddings": "Auto-update Embeddings",
"auto_update_embeddings_desc": "Automatically update embeddings when notes are modified",
+ "no_failed_embeddings": "No failed embeddings",
"enable_automatic_indexing": "Automatic Indexing",
"enable_automatic_indexing_description": "Periodically run indexing jobs in the background to maintain the knowledge base",
"similarity_threshold": "Similarity Threshold",
@@ -1179,6 +1180,12 @@
"reprocess_started": "Embedding reprocessing started in the background",
"reprocess_error": "Error starting embedding reprocessing",
+ "reprocess_index": "Rebuild Search Index",
+ "reprocess_index_description": "Rebuild the semantic search index structure for better query performance. This doesn't regenerate embeddings.",
+ "reprocessing_index": "Rebuilding...",
+ "reprocess_index_started": "Index rebuilding started in the background",
+ "reprocess_index_error": "Error rebuilding search index",
+
"embedding_statistics": "Embedding Statistics",
"total_notes": "Total Notes",
"processed_notes": "Processed Notes",
diff --git a/src/routes/api/embeddings.ts b/src/routes/api/embeddings.ts
index 061bfecd6..d1194a1ec 100644
--- a/src/routes/api/embeddings.ts
+++ b/src/routes/api/embeddings.ts
@@ -1,6 +1,7 @@
import options from "../../services/options.js";
import vectorStore from "../../services/llm/embeddings/vector_store.js";
import providerManager from "../../services/llm/embeddings/providers.js";
+import indexService from "../../services/llm/index_service.js";
import becca from "../../becca/becca.js";
import type { Request, Response } from "express";
import log from "../../services/log.js";
@@ -257,6 +258,27 @@ async function retryAllFailedNotes(req: Request, res: Response) {
};
}
+/**
+ * Manually trigger a rebuild of the search index
+ */
+async function rebuildIndex(req: Request, res: Response) {
+ // Start the index rebuilding operation in the background
+ setTimeout(async () => {
+ try {
+ await indexService.startFullIndexing(true);
+ log.info("Index rebuilding completed successfully");
+ } catch (error: any) {
+ log.error(`Error during background index rebuilding: ${error.message || "Unknown error"}`);
+ }
+ }, 0);
+
+ // Return the response data
+ return {
+ success: true,
+ message: "Index rebuilding started in the background"
+ };
+}
+
export default {
findSimilarNotes,
searchByText,
@@ -267,5 +289,6 @@ export default {
getEmbeddingStats,
getFailedNotes,
retryFailedNote,
- retryAllFailedNotes
+ retryAllFailedNotes,
+ rebuildIndex
};
diff --git a/src/routes/routes.ts b/src/routes/routes.ts
index 88bb02d9b..251544817 100644
--- a/src/routes/routes.ts
+++ b/src/routes/routes.ts
@@ -383,6 +383,7 @@ function register(app: express.Application) {
apiRoute(GET, "/api/embeddings/failed", embeddingsRoute.getFailedNotes);
apiRoute(PST, "/api/embeddings/retry/:noteId", embeddingsRoute.retryFailedNote);
apiRoute(PST, "/api/embeddings/retry-all-failed", embeddingsRoute.retryAllFailedNotes);
+ apiRoute(PST, "/api/embeddings/rebuild-index", embeddingsRoute.rebuildIndex);
// LLM chat session management endpoints
apiRoute(PST, "/api/llm/sessions", llmRoute.createSession);
@@ -392,7 +393,7 @@ function register(app: express.Application) {
apiRoute(DEL, "/api/llm/sessions/:sessionId", llmRoute.deleteSession);
apiRoute(PST, "/api/llm/sessions/:sessionId/messages", llmRoute.sendMessage);
route(GET, "/api/llm/sessions/:sessionId/messages", [auth.checkApiAuth, csrfMiddleware], llmRoute.sendMessage, apiResultHandler);
-
+
// LLM index management endpoints
apiRoute(GET, "/api/llm/index/stats", llmRoute.getIndexStats);
apiRoute(PST, "/api/llm/index/start", llmRoute.startIndexing);