OpenRAG 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openrag-0.3.0/src/openrag.egg-info → openrag-0.3.2}/PKG-INFO +6 -6
- {openrag-0.3.0 → openrag-0.3.2}/README.md +5 -5
- {openrag-0.3.0 → openrag-0.3.2}/pyproject.toml +1 -1
- {openrag-0.3.0 → openrag-0.3.2}/src/api/documents.py +94 -39
- {openrag-0.3.0 → openrag-0.3.2}/src/api/search.py +3 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/settings.py +114 -39
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/documents.py +8 -28
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/search.py +4 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/config/config_manager.py +4 -1
- {openrag-0.3.0 → openrag-0.3.2}/src/config/settings.py +14 -0
- openrag-0.3.2/src/main.py +1933 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/models/processors.py +21 -4
- openrag-0.3.2/src/models/url.py +157 -0
- {openrag-0.3.0 → openrag-0.3.2/src/openrag.egg-info}/PKG-INFO +6 -6
- {openrag-0.3.0 → openrag-0.3.2}/src/openrag.egg-info/SOURCES.txt +1 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/auth_service.py +3 -2
- {openrag-0.3.0 → openrag-0.3.2}/src/services/chat_service.py +8 -3
- {openrag-0.3.0 → openrag-0.3.2}/src/services/flows_service.py +299 -471
- {openrag-0.3.0 → openrag-0.3.2}/src/services/langflow_file_service.py +236 -3
- {openrag-0.3.0 → openrag-0.3.2}/src/services/models_service.py +0 -1
- {openrag-0.3.0 → openrag-0.3.2}/src/services/search_service.py +25 -4
- {openrag-0.3.0 → openrag-0.3.2}/src/services/task_service.py +32 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/docker-compose.yml +5 -5
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/ingestion_flow.json +2 -2
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/openrag_agent.json +2 -2
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/openrag_nudges.json +5 -5
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/openrag_url_mcp.json +2 -2
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/container_utils.py +18 -28
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/embedding_fields.py +15 -2
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/langflow_headers.py +14 -6
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/opensearch_queries.py +1 -1
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/opensearch_utils.py +41 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/telemetry/message_id.py +14 -0
- openrag-0.3.0/src/main.py +0 -988
- {openrag-0.3.0 → openrag-0.3.2}/LICENSE +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/MANIFEST.in +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/setup.cfg +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/agent.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/auth.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/chat.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/connector_router.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/connectors.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/docling.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/flows.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/keys.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/knowledge_filter.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/langflow_files.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/models.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/nudges.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/oidc.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/provider_health.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/provider_validation.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/router.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/tasks.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/upload.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/chat.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/knowledge_filters.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/models.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/api/v1/settings.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/auth_context.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/config/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/config/model_constants.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/base.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/connection_manager.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/google_drive/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/google_drive/connector.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/google_drive/oauth.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/langflow_connector_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/onedrive/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/onedrive/connector.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/onedrive/oauth.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/sharepoint/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/sharepoint/connector.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/sharepoint/oauth.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/connectors/sharepoint/utils.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/dependencies.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/models/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/models/tasks.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/openrag.egg-info/dependency_links.txt +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/openrag.egg-info/entry_points.txt +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/openrag.egg-info/requires.txt +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/openrag.egg-info/top_level.txt +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/api_key_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/conversation_persistence_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/document_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/knowledge_filter_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/langflow_history_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/langflow_mcp_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/monitor_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/services/session_ownership_service.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/session_manager.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/docker-compose.gpu.yml +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/openrag-documents/openrag-documentation.pdf +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/cli.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/config_fields.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/main.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/managers/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/managers/container_manager.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/managers/docling_manager.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/managers/env_manager.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/screens/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/screens/config.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/screens/diagnostics.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/screens/logs.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/screens/monitor.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/screens/welcome.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/utils/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/utils/clipboard.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/utils/platform.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/utils/startup_checks.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/utils/validation.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/utils/version_check.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/command_modal.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/diagnostics_notification.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/error_notification.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/flow_backup_warning_modal.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/prune_options_modal.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/version_mismatch_warning_modal.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/tui/widgets/waves.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/acl_utils.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/docling_client.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/document_processing.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/embeddings.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/env_utils.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/file_utils.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/gpu_detection.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/hash_utils.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/langflow_utils.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/logging_config.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/paths.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/telemetry/__init__.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/telemetry/category.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/telemetry/client.py +0 -0
- {openrag-0.3.0 → openrag-0.3.2}/src/utils/version_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
|
|
5
5
|
Classifier: Development Status :: 4 - Beta
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -40,7 +40,7 @@ Dynamic: license-file
|
|
|
40
40
|
|
|
41
41
|
<div align="center">
|
|
42
42
|
|
|
43
|
-
<img src="./docs/static/img/openrag-logo-dog.svg" alt="
|
|
43
|
+
<img src="./docs/static/img/openrag-logo-dog.svg" alt="" width="120"/>
|
|
44
44
|
|
|
45
45
|
# OpenRAG
|
|
46
46
|
|
|
@@ -49,7 +49,7 @@ Dynamic: license-file
|
|
|
49
49
|
</h3>
|
|
50
50
|
|
|
51
51
|
<!-- Badges -->
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
[](https://github.com/langflow-ai/langflow)
|
|
54
54
|
[](https://github.com/opensearch-project/OpenSearch)
|
|
55
55
|
[](https://github.com/docling-project/docling)
|
|
@@ -66,11 +66,11 @@ Dynamic: license-file
|
|
|
66
66
|
|
|
67
67
|
OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
|
|
68
68
|
|
|
69
|
-
Users can upload, process, and query documents through a chat interface backed by large language models and semantic search capabilities. The system utilizes Langflow for document ingestion, retrieval workflows, and intelligent nudges, providing a seamless RAG experience.
|
|
69
|
+
Users can upload, process, and query documents through a chat interface backed by large language models and semantic search capabilities. The system utilizes Langflow for document ingestion, retrieval workflows, and intelligent nudges, providing a seamless RAG experience.
|
|
70
70
|
|
|
71
71
|
Check out the [documentation](https://docs.openr.ag/) or get started with the [quickstart](https://docs.openr.ag/quickstart).
|
|
72
72
|
|
|
73
|
-
Built with [
|
|
73
|
+
Built with [FastAPI](https://fastapi.tiangolo.com/) and [Next.js](https://github.com/vercel/next.js).
|
|
74
74
|
Powered by [OpenSearch](https://github.com/opensearch-project/OpenSearch), [Langflow](https://github.com/langflow-ai/langflow), and [Docling](https://github.com/docling-project/docling).
|
|
75
75
|
|
|
76
76
|
---
|
|
@@ -201,7 +201,7 @@ The MCP server provides tools for RAG-enhanced chat, semantic search, and settin
|
|
|
201
201
|
|
|
202
202
|
For developers who want to [contribute to OpenRAG](https://docs.openr.ag/support/contribute) or set up a development environment, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
203
203
|
|
|
204
|
-
##
|
|
204
|
+
## 🛟 Troubleshooting
|
|
205
205
|
|
|
206
206
|
For assistance with OpenRAG, see [Troubleshoot OpenRAG](https://docs.openr.ag/support/troubleshoot) and visit the [Discussions page](https://github.com/langflow-ai/openrag/discussions).
|
|
207
207
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="./docs/static/img/openrag-logo-dog.svg" alt="
|
|
3
|
+
<img src="./docs/static/img/openrag-logo-dog.svg" alt="" width="120"/>
|
|
4
4
|
|
|
5
5
|
# OpenRAG
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</h3>
|
|
10
10
|
|
|
11
11
|
<!-- Badges -->
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
[](https://github.com/langflow-ai/langflow)
|
|
14
14
|
[](https://github.com/opensearch-project/OpenSearch)
|
|
15
15
|
[](https://github.com/docling-project/docling)
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
|
|
27
27
|
OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
|
|
28
28
|
|
|
29
|
-
Users can upload, process, and query documents through a chat interface backed by large language models and semantic search capabilities. The system utilizes Langflow for document ingestion, retrieval workflows, and intelligent nudges, providing a seamless RAG experience.
|
|
29
|
+
Users can upload, process, and query documents through a chat interface backed by large language models and semantic search capabilities. The system utilizes Langflow for document ingestion, retrieval workflows, and intelligent nudges, providing a seamless RAG experience.
|
|
30
30
|
|
|
31
31
|
Check out the [documentation](https://docs.openr.ag/) or get started with the [quickstart](https://docs.openr.ag/quickstart).
|
|
32
32
|
|
|
33
|
-
Built with [
|
|
33
|
+
Built with [FastAPI](https://fastapi.tiangolo.com/) and [Next.js](https://github.com/vercel/next.js).
|
|
34
34
|
Powered by [OpenSearch](https://github.com/opensearch-project/OpenSearch), [Langflow](https://github.com/langflow-ai/langflow), and [Docling](https://github.com/docling-project/docling).
|
|
35
35
|
|
|
36
36
|
---
|
|
@@ -161,7 +161,7 @@ The MCP server provides tools for RAG-enhanced chat, semantic search, and settin
|
|
|
161
161
|
|
|
162
162
|
For developers who want to [contribute to OpenRAG](https://docs.openr.ag/support/contribute) or set up a development environment, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
163
163
|
|
|
164
|
-
##
|
|
164
|
+
## 🛟 Troubleshooting
|
|
165
165
|
|
|
166
166
|
For assistance with OpenRAG, see [Troubleshoot OpenRAG](https://docs.openr.ag/support/troubleshoot) and visit the [Discussions page](https://github.com/langflow-ai/openrag/discussions).
|
|
167
167
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openrag"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -13,6 +13,92 @@ class DeleteDocumentBody(BaseModel):
|
|
|
13
13
|
filename: str
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
async def delete_documents_by_filename_core(
|
|
17
|
+
filename: str,
|
|
18
|
+
session_manager,
|
|
19
|
+
user_id: str,
|
|
20
|
+
jwt_token: str | None,
|
|
21
|
+
):
|
|
22
|
+
"""Shared delete-by-filename logic for v1 and non-v1 endpoints."""
|
|
23
|
+
from config.settings import get_index_name
|
|
24
|
+
from utils.opensearch_queries import build_filename_delete_body
|
|
25
|
+
|
|
26
|
+
normalized_filename = (filename or "").strip()
|
|
27
|
+
if not normalized_filename:
|
|
28
|
+
return (
|
|
29
|
+
{
|
|
30
|
+
"success": False,
|
|
31
|
+
"deleted_chunks": 0,
|
|
32
|
+
"filename": normalized_filename,
|
|
33
|
+
"message": None,
|
|
34
|
+
"error": "Filename is required",
|
|
35
|
+
},
|
|
36
|
+
400,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
opensearch_client = session_manager.get_user_opensearch_client(
|
|
41
|
+
user_id, jwt_token
|
|
42
|
+
)
|
|
43
|
+
delete_query = build_filename_delete_body(normalized_filename)
|
|
44
|
+
result = await opensearch_client.delete_by_query(
|
|
45
|
+
index=get_index_name(),
|
|
46
|
+
body=delete_query,
|
|
47
|
+
conflicts="proceed",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
deleted_count = result.get("deleted", 0)
|
|
51
|
+
logger.info(
|
|
52
|
+
f"Deleted {deleted_count} chunks for filename {normalized_filename}",
|
|
53
|
+
user_id=user_id,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if deleted_count == 0:
|
|
57
|
+
return (
|
|
58
|
+
{
|
|
59
|
+
"success": False,
|
|
60
|
+
"deleted_chunks": 0,
|
|
61
|
+
"filename": normalized_filename,
|
|
62
|
+
"message": None,
|
|
63
|
+
"error": "No matching document chunks were deleted. The file may be missing or not deletable in the current user context.",
|
|
64
|
+
},
|
|
65
|
+
404,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
{
|
|
70
|
+
"success": True,
|
|
71
|
+
"deleted_chunks": deleted_count,
|
|
72
|
+
"filename": normalized_filename,
|
|
73
|
+
"message": f"All documents with filename '{normalized_filename}' deleted successfully",
|
|
74
|
+
"error": None,
|
|
75
|
+
},
|
|
76
|
+
200,
|
|
77
|
+
)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.error(
|
|
80
|
+
"Error deleting documents by filename",
|
|
81
|
+
filename=normalized_filename,
|
|
82
|
+
error=str(e),
|
|
83
|
+
)
|
|
84
|
+
error_str = str(e)
|
|
85
|
+
status_code = 403 if "AuthenticationException" in error_str else 500
|
|
86
|
+
return (
|
|
87
|
+
{
|
|
88
|
+
"success": False,
|
|
89
|
+
"deleted_chunks": 0,
|
|
90
|
+
"filename": normalized_filename,
|
|
91
|
+
"message": None,
|
|
92
|
+
"error": (
|
|
93
|
+
"Access denied: insufficient permissions"
|
|
94
|
+
if status_code == 403
|
|
95
|
+
else "An internal error has occurred while deleting documents"
|
|
96
|
+
),
|
|
97
|
+
},
|
|
98
|
+
status_code,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
16
102
|
async def _ensure_index_exists():
|
|
17
103
|
"""Create the OpenSearch index if it doesn't exist yet."""
|
|
18
104
|
from main import init_index
|
|
@@ -70,43 +156,12 @@ async def delete_documents_by_filename(
|
|
|
70
156
|
body: DeleteDocumentBody,
|
|
71
157
|
session_manager=Depends(get_session_manager),
|
|
72
158
|
user: User = Depends(get_current_user),
|
|
73
|
-
):
|
|
159
|
+
):
|
|
74
160
|
"""Delete all documents with a specific filename"""
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
from utils.opensearch_queries import build_filename_delete_body
|
|
85
|
-
|
|
86
|
-
delete_query = build_filename_delete_body(body.filename)
|
|
87
|
-
|
|
88
|
-
logger.debug(f"Deleting documents with filename: {body.filename}")
|
|
89
|
-
|
|
90
|
-
result = await opensearch_client.delete_by_query(
|
|
91
|
-
index=get_index_name(),
|
|
92
|
-
body=delete_query,
|
|
93
|
-
conflicts="proceed"
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
deleted_count = result.get("deleted", 0)
|
|
97
|
-
logger.info(f"Deleted {deleted_count} chunks for filename {body.filename}", user_id=user.user_id)
|
|
98
|
-
|
|
99
|
-
return JSONResponse({
|
|
100
|
-
"success": True,
|
|
101
|
-
"deleted_chunks": deleted_count,
|
|
102
|
-
"filename": body.filename,
|
|
103
|
-
"message": f"All documents with filename '{body.filename}' deleted successfully"
|
|
104
|
-
}, status_code=200)
|
|
105
|
-
|
|
106
|
-
except Exception as e:
|
|
107
|
-
logger.error("Error deleting documents by filename", filename=body.filename, error=str(e))
|
|
108
|
-
error_str = str(e)
|
|
109
|
-
if "AuthenticationException" in error_str:
|
|
110
|
-
return JSONResponse({"error": "Access denied: insufficient permissions"}, status_code=403)
|
|
111
|
-
else:
|
|
112
|
-
return JSONResponse({"error": str(e)}, status_code=500)
|
|
161
|
+
payload, status_code =await delete_documents_by_filename_core(
|
|
162
|
+
filename=body.filename,
|
|
163
|
+
session_manager=session_manager,
|
|
164
|
+
user_id=user.user_id,
|
|
165
|
+
jwt_token=user.jwt_token,
|
|
166
|
+
)
|
|
167
|
+
return JSONResponse(payload, status_code=status_code)
|
|
@@ -4,6 +4,7 @@ from fastapi import Depends
|
|
|
4
4
|
from pydantic import BaseModel, Field
|
|
5
5
|
from fastapi.responses import JSONResponse
|
|
6
6
|
from utils.logging_config import get_logger
|
|
7
|
+
from utils.opensearch_utils import OpenSearchDiskSpaceError, DISK_SPACE_ERROR_MESSAGE
|
|
7
8
|
|
|
8
9
|
from dependencies import get_search_service, get_session_manager, get_current_user
|
|
9
10
|
from session_manager import User
|
|
@@ -50,6 +51,8 @@ async def search(
|
|
|
50
51
|
score_threshold=body.scoreThreshold,
|
|
51
52
|
)
|
|
52
53
|
return JSONResponse(result, status_code=200)
|
|
54
|
+
except OpenSearchDiskSpaceError:
|
|
55
|
+
return JSONResponse({"error": DISK_SPACE_ERROR_MESSAGE}, status_code=507)
|
|
53
56
|
except Exception as e:
|
|
54
57
|
error_msg = str(e)
|
|
55
58
|
if (
|
|
@@ -3,10 +3,11 @@ import platform
|
|
|
3
3
|
from fastapi import Depends, Request, HTTPException
|
|
4
4
|
from fastapi.responses import JSONResponse
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
|
-
from utils.container_utils import transform_localhost_url
|
|
7
6
|
from utils.logging_config import get_logger
|
|
8
7
|
from utils.telemetry import TelemetryClient, Category, MessageId
|
|
8
|
+
from utils.version_utils import OPENRAG_VERSION
|
|
9
9
|
from config.settings import (
|
|
10
|
+
DEFAULT_DOCS_URL,
|
|
10
11
|
DISABLE_INGEST_WITH_LANGFLOW,
|
|
11
12
|
INGEST_SAMPLE_DATA,
|
|
12
13
|
LANGFLOW_URL,
|
|
@@ -88,6 +89,8 @@ class OnboardingStateBody(BaseModel):
|
|
|
88
89
|
upload_steps: Optional[Dict[str, Any]] = None
|
|
89
90
|
openrag_docs_filter_id: Optional[str] = None
|
|
90
91
|
user_doc_filter_id: Optional[str] = None
|
|
92
|
+
openrag_docs_ingested_version: Optional[str] = None
|
|
93
|
+
openrag_docs_remote_signature: Optional[str] = None
|
|
91
94
|
|
|
92
95
|
|
|
93
96
|
class DoclingPresetBody(BaseModel):
|
|
@@ -105,6 +108,8 @@ class OnboardingStateConfig(BaseModel):
|
|
|
105
108
|
upload_steps: Optional[Dict[str, Any]]
|
|
106
109
|
openrag_docs_filter_id: Optional[str]
|
|
107
110
|
user_doc_filter_id: Optional[str]
|
|
111
|
+
openrag_docs_ingested_version: Optional[str]
|
|
112
|
+
openrag_docs_remote_signature: Optional[str]
|
|
108
113
|
|
|
109
114
|
class OpenAIProviderConfig(BaseModel):
|
|
110
115
|
has_api_key: bool
|
|
@@ -174,6 +179,11 @@ class OnboardingResponse(BaseModel):
|
|
|
174
179
|
openrag_docs_filter_id: Optional[str] = None
|
|
175
180
|
task_id: Optional[str] = None
|
|
176
181
|
|
|
182
|
+
|
|
183
|
+
class RefreshOpenRAGDocsResponse(BaseModel):
|
|
184
|
+
message: str
|
|
185
|
+
refreshed: bool
|
|
186
|
+
|
|
177
187
|
class DoclingConfig(BaseModel):
|
|
178
188
|
do_ocr: bool
|
|
179
189
|
ocr_engine: str
|
|
@@ -316,6 +326,8 @@ async def get_settings(
|
|
|
316
326
|
upload_steps=openrag_config.onboarding.upload_steps,
|
|
317
327
|
openrag_docs_filter_id=openrag_config.onboarding.openrag_docs_filter_id,
|
|
318
328
|
user_doc_filter_id=openrag_config.onboarding.user_doc_filter_id,
|
|
329
|
+
openrag_docs_ingested_version=openrag_config.onboarding.openrag_docs_ingested_version,
|
|
330
|
+
openrag_docs_remote_signature=openrag_config.onboarding.openrag_docs_remote_signature,
|
|
319
331
|
),
|
|
320
332
|
providers=ProvidersConfig(
|
|
321
333
|
openai=OpenAIProviderConfig(
|
|
@@ -811,12 +823,12 @@ async def update_settings(
|
|
|
811
823
|
flows_service = _get_flows_service()
|
|
812
824
|
|
|
813
825
|
# Update global variables
|
|
814
|
-
await _update_langflow_global_variables(current_config)
|
|
826
|
+
await _update_langflow_global_variables(current_config, flows_service=flows_service)
|
|
815
827
|
|
|
816
828
|
# Update LLM client credentials when embedding selection changes
|
|
817
829
|
if body.embedding_provider is not None or body.embedding_model is not None:
|
|
818
830
|
await _update_mcp_servers_with_provider_credentials(
|
|
819
|
-
current_config, session_manager
|
|
831
|
+
current_config, session_manager, flows_service=flows_service
|
|
820
832
|
)
|
|
821
833
|
|
|
822
834
|
# Update model values if provider or model changed (including removals that trigger fallback)
|
|
@@ -1072,11 +1084,12 @@ async def onboarding(
|
|
|
1072
1084
|
# or if existing config has values (for OpenAI/Anthropic that might already be set)
|
|
1073
1085
|
if (provider_fields_provided or
|
|
1074
1086
|
current_config.providers.openai.api_key != "" or
|
|
1075
|
-
current_config.providers.anthropic.api_key != ""
|
|
1076
|
-
|
|
1087
|
+
current_config.providers.anthropic.api_key != "" or
|
|
1088
|
+
current_config.providers.any_configured()):
|
|
1089
|
+
await _update_langflow_global_variables(current_config, flows_service=flows_service)
|
|
1077
1090
|
|
|
1078
1091
|
if body.embedding_provider or body.embedding_model:
|
|
1079
|
-
await _update_mcp_servers_with_provider_credentials(current_config, session_manager)
|
|
1092
|
+
await _update_mcp_servers_with_provider_credentials(current_config, session_manager=session_manager, flows_service=flows_service)
|
|
1080
1093
|
|
|
1081
1094
|
# Update model values if provider or model fields were provided
|
|
1082
1095
|
if body.llm_provider or body.llm_model or body.embedding_provider or body.embedding_model:
|
|
@@ -1126,6 +1139,18 @@ async def onboarding(
|
|
|
1126
1139
|
langflow_file_service,
|
|
1127
1140
|
session_manager,
|
|
1128
1141
|
)
|
|
1142
|
+
current_config.onboarding.openrag_docs_ingested_version = OPENRAG_VERSION
|
|
1143
|
+
from main import (
|
|
1144
|
+
_get_remote_docs_signature,
|
|
1145
|
+
_should_use_url_default_docs_ingest,
|
|
1146
|
+
)
|
|
1147
|
+
|
|
1148
|
+
if _should_use_url_default_docs_ingest():
|
|
1149
|
+
current_config.onboarding.openrag_docs_remote_signature = (
|
|
1150
|
+
await _get_remote_docs_signature(DEFAULT_DOCS_URL)
|
|
1151
|
+
)
|
|
1152
|
+
else:
|
|
1153
|
+
current_config.onboarding.openrag_docs_remote_signature = None
|
|
1129
1154
|
logger.info("Sample data ingestion completed successfully")
|
|
1130
1155
|
|
|
1131
1156
|
except Exception as e:
|
|
@@ -1252,10 +1277,12 @@ async def _create_openrag_docs_filter(
|
|
|
1252
1277
|
query_data = json.dumps({
|
|
1253
1278
|
"query": "",
|
|
1254
1279
|
"filters": {
|
|
1255
|
-
|
|
1280
|
+
# URL-based docs ingestion produces many source URLs.
|
|
1281
|
+
# Filter by connector type to target OpenRAG docs only.
|
|
1282
|
+
"data_sources": ["*"],
|
|
1256
1283
|
"document_types": ["*"],
|
|
1257
1284
|
"owners": ["*"],
|
|
1258
|
-
"connector_types": ["
|
|
1285
|
+
"connector_types": ["openrag_docs"],
|
|
1259
1286
|
},
|
|
1260
1287
|
"limit": 10,
|
|
1261
1288
|
"scoreThreshold": 0,
|
|
@@ -1293,15 +1320,15 @@ def _get_flows_service():
|
|
|
1293
1320
|
return FlowsService()
|
|
1294
1321
|
|
|
1295
1322
|
|
|
1296
|
-
async def _update_langflow_global_variables(config):
|
|
1323
|
+
async def _update_langflow_global_variables(config, flows_service=None):
|
|
1297
1324
|
"""Update Langflow global variables for all configured providers"""
|
|
1298
1325
|
try:
|
|
1299
1326
|
# WatsonX global variables
|
|
1300
1327
|
if config.providers.watsonx.api_key:
|
|
1301
1328
|
await clients._create_langflow_global_variable(
|
|
1302
|
-
"
|
|
1329
|
+
"WATSONX_APIKEY", config.providers.watsonx.api_key, modify=True
|
|
1303
1330
|
)
|
|
1304
|
-
logger.info("Set
|
|
1331
|
+
logger.info("Set WATSONX_APIKEY global variable in Langflow")
|
|
1305
1332
|
|
|
1306
1333
|
if config.providers.watsonx.project_id:
|
|
1307
1334
|
await clients._create_langflow_global_variable(
|
|
@@ -1331,19 +1358,14 @@ async def _update_langflow_global_variables(config):
|
|
|
1331
1358
|
|
|
1332
1359
|
# Ollama global variables
|
|
1333
1360
|
if config.providers.ollama.endpoint:
|
|
1361
|
+
if not flows_service:
|
|
1362
|
+
flows_service = _get_flows_service()
|
|
1334
1363
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
logger.info("Set OLLAMA_BASE_URL global variable in Langflow (Podman)")
|
|
1341
|
-
except Exception:
|
|
1342
|
-
endpoint = transform_localhost_url(config.providers.ollama.endpoint, is_langflow=True, is_podman=False)
|
|
1343
|
-
await clients._create_langflow_global_variable(
|
|
1344
|
-
"OLLAMA_BASE_URL", endpoint, modify=True
|
|
1345
|
-
)
|
|
1346
|
-
logger.info("Set OLLAMA_BASE_URL global variable in Langflow (Docker)")
|
|
1364
|
+
endpoint = await flows_service.resolve_ollama_url(config.providers.ollama.endpoint, force_refresh=True)
|
|
1365
|
+
await clients._create_langflow_global_variable(
|
|
1366
|
+
"OLLAMA_BASE_URL", endpoint, modify=True
|
|
1367
|
+
)
|
|
1368
|
+
logger.info("Set OLLAMA_BASE_URL global variable in Langflow")
|
|
1347
1369
|
|
|
1348
1370
|
if config.knowledge.embedding_model:
|
|
1349
1371
|
await clients._create_langflow_global_variable(
|
|
@@ -1358,7 +1380,7 @@ async def _update_langflow_global_variables(config):
|
|
|
1358
1380
|
raise
|
|
1359
1381
|
|
|
1360
1382
|
|
|
1361
|
-
async def _update_mcp_servers_with_provider_credentials(config, session_manager = None):
|
|
1383
|
+
async def _update_mcp_servers_with_provider_credentials(config, session_manager = None, flows_service=None):
|
|
1362
1384
|
# Update MCP servers with provider credentials
|
|
1363
1385
|
try:
|
|
1364
1386
|
from services.langflow_mcp_service import LangflowMCPService
|
|
@@ -1367,7 +1389,7 @@ async def _update_mcp_servers_with_provider_credentials(config, session_manager
|
|
|
1367
1389
|
mcp_service = LangflowMCPService()
|
|
1368
1390
|
|
|
1369
1391
|
# Build global vars using utility function
|
|
1370
|
-
mcp_global_vars = build_mcp_global_vars_from_config(config)
|
|
1392
|
+
mcp_global_vars = await build_mcp_global_vars_from_config(config, flows_service=flows_service)
|
|
1371
1393
|
|
|
1372
1394
|
# In no-auth mode, add the anonymous JWT token and user details
|
|
1373
1395
|
if is_no_auth_mode() and session_manager:
|
|
@@ -1396,29 +1418,45 @@ async def _update_mcp_servers_with_provider_credentials(config, session_manager
|
|
|
1396
1418
|
|
|
1397
1419
|
|
|
1398
1420
|
async def _update_langflow_model_values(config, flows_service):
|
|
1399
|
-
"""Update model values across Langflow flows"""
|
|
1421
|
+
"""Update model values across Langflow flows for all configured providers"""
|
|
1400
1422
|
try:
|
|
1401
|
-
# Update LLM
|
|
1423
|
+
# 1. Update ONLY the current LLM provider
|
|
1402
1424
|
llm_provider = config.agent.llm_provider.lower()
|
|
1403
|
-
|
|
1404
1425
|
await flows_service.change_langflow_model_value(
|
|
1405
1426
|
llm_provider,
|
|
1406
1427
|
llm_model=config.agent.llm_model,
|
|
1428
|
+
force_llm_update=True
|
|
1407
1429
|
)
|
|
1408
1430
|
logger.info(
|
|
1409
1431
|
f"Successfully updated Langflow flows for LLM provider {llm_provider}"
|
|
1410
1432
|
)
|
|
1411
1433
|
|
|
1412
|
-
# Update embedding
|
|
1413
|
-
|
|
1434
|
+
# 2. Update ALL configured embedding providers
|
|
1435
|
+
embedding_providers = []
|
|
1436
|
+
if config.providers.openai.configured:
|
|
1437
|
+
embedding_providers.append("openai")
|
|
1438
|
+
if config.providers.watsonx.configured:
|
|
1439
|
+
embedding_providers.append("watsonx")
|
|
1440
|
+
if config.providers.ollama.configured:
|
|
1441
|
+
embedding_providers.append("ollama")
|
|
1442
|
+
|
|
1443
|
+
current_embedding_provider = config.knowledge.embedding_provider.lower()
|
|
1444
|
+
for provider in embedding_providers:
|
|
1445
|
+
# Use configured model for current provider, or None (first available) for others
|
|
1446
|
+
embedding_model = (
|
|
1447
|
+
config.knowledge.embedding_model
|
|
1448
|
+
if provider == current_embedding_provider
|
|
1449
|
+
else None
|
|
1450
|
+
)
|
|
1414
1451
|
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1452
|
+
await flows_service.change_langflow_model_value(
|
|
1453
|
+
provider,
|
|
1454
|
+
embedding_model=embedding_model,
|
|
1455
|
+
force_embedding_update=True
|
|
1456
|
+
)
|
|
1457
|
+
logger.info(
|
|
1458
|
+
f"Successfully updated Langflow flows for embedding provider {provider}"
|
|
1459
|
+
)
|
|
1422
1460
|
|
|
1423
1461
|
except Exception as e:
|
|
1424
1462
|
logger.error(f"Failed to update Langflow model values: {str(e)}")
|
|
@@ -1514,13 +1552,13 @@ async def reapply_all_settings(session_manager = None):
|
|
|
1514
1552
|
logger.info("Reapplying all settings to Langflow flows and global variables")
|
|
1515
1553
|
|
|
1516
1554
|
if config.knowledge.embedding_model or config.knowledge.embedding_provider:
|
|
1517
|
-
await _update_mcp_servers_with_provider_credentials(config, session_manager)
|
|
1555
|
+
await _update_mcp_servers_with_provider_credentials(config, session_manager, flows_service=flows_service)
|
|
1518
1556
|
else:
|
|
1519
1557
|
logger.info("No embedding model or provider configured, skipping MCP server update")
|
|
1520
1558
|
|
|
1521
1559
|
# Update all Langflow settings using helper functions
|
|
1522
1560
|
try:
|
|
1523
|
-
await _update_langflow_global_variables(config)
|
|
1561
|
+
await _update_langflow_global_variables(config, flows_service=flows_service)
|
|
1524
1562
|
except Exception as e:
|
|
1525
1563
|
logger.error(f"Failed to update Langflow global variables: {str(e)}")
|
|
1526
1564
|
# Continue with other updates even if global variables fail
|
|
@@ -1639,6 +1677,8 @@ async def rollback_onboarding(
|
|
|
1639
1677
|
# Clear embedding provider and model settings
|
|
1640
1678
|
current_config.knowledge.embedding_provider = "openai" # Reset to default
|
|
1641
1679
|
current_config.knowledge.embedding_model = ""
|
|
1680
|
+
current_config.onboarding.openrag_docs_ingested_version = None
|
|
1681
|
+
current_config.onboarding.openrag_docs_remote_signature = None
|
|
1642
1682
|
|
|
1643
1683
|
# Mark config as not edited so user can go through onboarding again
|
|
1644
1684
|
current_config.edited = False
|
|
@@ -1756,3 +1796,38 @@ async def update_docling_preset(
|
|
|
1756
1796
|
except Exception as e:
|
|
1757
1797
|
logger.error("Failed to update docling settings", error=str(e))
|
|
1758
1798
|
raise HTTPException(status_code=500, detail=f"Failed to update docling settings: {str(e)}")
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
async def refresh_openrag_docs(
|
|
1802
|
+
document_service=Depends(get_document_service),
|
|
1803
|
+
task_service=Depends(get_task_service),
|
|
1804
|
+
langflow_file_service=Depends(get_langflow_file_service),
|
|
1805
|
+
session_manager=Depends(get_session_manager),
|
|
1806
|
+
user: User = Depends(get_current_user),
|
|
1807
|
+
) -> RefreshOpenRAGDocsResponse:
|
|
1808
|
+
"""Manually refresh OpenRAG docs ingestion on demand."""
|
|
1809
|
+
try:
|
|
1810
|
+
from main import refresh_default_openrag_docs
|
|
1811
|
+
|
|
1812
|
+
refreshed = await refresh_default_openrag_docs(
|
|
1813
|
+
document_service=document_service,
|
|
1814
|
+
task_service=task_service,
|
|
1815
|
+
langflow_file_service=langflow_file_service,
|
|
1816
|
+
session_manager=session_manager,
|
|
1817
|
+
force=True,
|
|
1818
|
+
reason="manual",
|
|
1819
|
+
)
|
|
1820
|
+
return RefreshOpenRAGDocsResponse(
|
|
1821
|
+
message=(
|
|
1822
|
+
"OpenRAG docs were refreshed."
|
|
1823
|
+
if refreshed
|
|
1824
|
+
else "OpenRAG docs refresh was skipped by current configuration."
|
|
1825
|
+
),
|
|
1826
|
+
refreshed=refreshed,
|
|
1827
|
+
)
|
|
1828
|
+
except Exception as e:
|
|
1829
|
+
logger.error("Failed to refresh OpenRAG docs on demand", error=str(e))
|
|
1830
|
+
raise HTTPException(
|
|
1831
|
+
status_code=500,
|
|
1832
|
+
detail=f"Failed to refresh OpenRAG docs: {str(e)}",
|
|
1833
|
+
)
|
|
@@ -9,6 +9,7 @@ from typing import List, Optional
|
|
|
9
9
|
from fastapi import Depends, File, Form, UploadFile
|
|
10
10
|
from pydantic import BaseModel
|
|
11
11
|
from fastapi.responses import JSONResponse
|
|
12
|
+
from api.documents import delete_documents_by_filename_core
|
|
12
13
|
|
|
13
14
|
from api.router import upload_ingest_router
|
|
14
15
|
from utils.logging_config import get_logger
|
|
@@ -83,31 +84,10 @@ async def delete_document_endpoint(
|
|
|
83
84
|
user: User = Depends(get_api_key_user_async),
|
|
84
85
|
):
|
|
85
86
|
"""Delete a document from the knowledge base. DELETE /v1/documents"""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
opensearch_client = session_manager.get_user_opensearch_client(user.user_id, None)
|
|
95
|
-
delete_query = build_filename_delete_body(filename)
|
|
96
|
-
|
|
97
|
-
result = await opensearch_client.delete_by_query(
|
|
98
|
-
index=get_index_name(),
|
|
99
|
-
body=delete_query,
|
|
100
|
-
conflicts="proceed",
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
deleted_count = result.get("deleted", 0)
|
|
104
|
-
logger.info(f"Deleted {deleted_count} chunks for filename {filename}", user_id=user.user_id)
|
|
105
|
-
return JSONResponse({"success": True, "deleted_chunks": deleted_count})
|
|
106
|
-
|
|
107
|
-
except Exception as e:
|
|
108
|
-
error_msg = str(e)
|
|
109
|
-
logger.error("Document deletion failed", error=error_msg, filename=filename)
|
|
110
|
-
if "AuthenticationException" in error_msg or "access denied" in error_msg.lower():
|
|
111
|
-
return JSONResponse({"error": error_msg}, status_code=403)
|
|
112
|
-
else:
|
|
113
|
-
return JSONResponse({"error": error_msg}, status_code=500)
|
|
87
|
+
payload, status_code = await delete_documents_by_filename_core(
|
|
88
|
+
filename=body.filename,
|
|
89
|
+
session_manager=session_manager,
|
|
90
|
+
user_id=user.user_id,
|
|
91
|
+
jwt_token=None,
|
|
92
|
+
)
|
|
93
|
+
return JSONResponse(payload, status_code=status_code)
|
|
@@ -10,6 +10,7 @@ from fastapi import Depends
|
|
|
10
10
|
from pydantic import BaseModel
|
|
11
11
|
from fastapi.responses import JSONResponse
|
|
12
12
|
from utils.logging_config import get_logger
|
|
13
|
+
from utils.opensearch_utils import OpenSearchDiskSpaceError, DISK_SPACE_ERROR_MESSAGE
|
|
13
14
|
from dependencies import get_search_service, get_api_key_user_async
|
|
14
15
|
from session_manager import User
|
|
15
16
|
|
|
@@ -65,6 +66,9 @@ async def search_endpoint(
|
|
|
65
66
|
|
|
66
67
|
return JSONResponse({"results": results})
|
|
67
68
|
|
|
69
|
+
except OpenSearchDiskSpaceError as e:
|
|
70
|
+
logger.error("Search blocked by disk space constraint", error=str(e), user_id=user.user_id)
|
|
71
|
+
return JSONResponse({"error": DISK_SPACE_ERROR_MESSAGE}, status_code=507)
|
|
68
72
|
except Exception as e:
|
|
69
73
|
error_msg = str(e)
|
|
70
74
|
logger.error("Search failed", error=error_msg, user_id=user.user_id)
|
|
@@ -37,6 +37,7 @@ class WatsonXConfig:
|
|
|
37
37
|
class OllamaConfig:
|
|
38
38
|
"""Ollama provider configuration."""
|
|
39
39
|
endpoint: str = ""
|
|
40
|
+
resolved_endpoint: str = ""
|
|
40
41
|
configured: bool = False
|
|
41
42
|
|
|
42
43
|
|
|
@@ -97,6 +98,8 @@ class OnboardingState:
|
|
|
97
98
|
upload_steps: Optional[Dict[str, Any]] = field(default=None)
|
|
98
99
|
openrag_docs_filter_id: Optional[str] = field(default=None)
|
|
99
100
|
user_doc_filter_id: Optional[str] = field(default=None)
|
|
101
|
+
openrag_docs_ingested_version: Optional[str] = field(default=None)
|
|
102
|
+
openrag_docs_remote_signature: Optional[str] = field(default=None)
|
|
100
103
|
|
|
101
104
|
|
|
102
105
|
@dataclass
|
|
@@ -311,7 +314,7 @@ class ConfigManager:
|
|
|
311
314
|
return True
|
|
312
315
|
except Exception as e:
|
|
313
316
|
logger.error(f"Failed to save configuration to {self.config_file}: {e}")
|
|
314
|
-
|
|
317
|
+
raise e
|
|
315
318
|
|
|
316
319
|
def update_onboarding_state(self, **kwargs) -> bool:
|
|
317
320
|
"""Update onboarding state fields.
|