openrag 0.4.0.dev9__tar.gz → 0.4.1__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.4.0.dev9/src/openrag.egg-info → openrag-0.4.1}/PKG-INFO +6 -2
- {openrag-0.4.0.dev9 → openrag-0.4.1}/pyproject.toml +7 -3
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/agent.py +69 -21
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/settings.py +10 -5
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/upload.py +17 -29
- openrag-0.4.1/src/config/embedding_constants.py +4 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/config/model_constants.py +0 -2
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/config/settings.py +48 -44
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/service.py +7 -7
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/main.py +99 -44
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/models/processors.py +37 -20
- {openrag-0.4.0.dev9 → openrag-0.4.1/src/openrag.egg-info}/PKG-INFO +6 -2
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/openrag.egg-info/SOURCES.txt +1 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/openrag.egg-info/requires.txt +5 -1
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/document_service.py +15 -9
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/models_service.py +150 -13
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/search_service.py +61 -26
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/task_service.py +15 -1
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/session_manager.py +2 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/docker-compose.yml +22 -19
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/config_fields.py +0 -6
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/main.py +3 -6
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/managers/container_manager.py +27 -13
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/managers/env_manager.py +2 -7
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/screens/config.py +0 -78
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/screens/monitor.py +0 -17
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/utils/startup_checks.py +86 -19
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/embedding_fields.py +4 -2
- openrag-0.4.1/src/utils/embeddings.py +39 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/opensearch_utils.py +37 -0
- openrag-0.4.0.dev9/src/utils/embeddings.py +0 -196
- {openrag-0.4.0.dev9 → openrag-0.4.1}/LICENSE +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/MANIFEST.in +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/README.md +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/setup.cfg +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/auth.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/chat.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/connector_router.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/connectors.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/docling.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/documents.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/flows.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/keys.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/knowledge_filter.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/langflow_files.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/models.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/nudges.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/oidc.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/provider_health.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/provider_validation.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/router.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/search.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/tasks.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/chat.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/documents.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/knowledge_filters.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/models.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/search.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/api/v1/settings.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/auth_context.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/config/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/config/config_manager.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/aws_s3/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/aws_s3/api.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/aws_s3/auth.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/aws_s3/connector.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/aws_s3/models.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/aws_s3/support.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/base.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/connection_manager.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/google_drive/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/google_drive/connector.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/google_drive/oauth.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/ibm_cos/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/ibm_cos/api.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/ibm_cos/auth.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/ibm_cos/connector.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/ibm_cos/models.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/ibm_cos/support.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/langflow_connector_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/onedrive/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/onedrive/connector.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/onedrive/oauth.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/sharepoint/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/sharepoint/connector.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/sharepoint/oauth.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/connectors/sharepoint/utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/dependencies.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/models/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/models/tasks.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/models/url.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/openrag.egg-info/dependency_links.txt +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/openrag.egg-info/entry_points.txt +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/openrag.egg-info/top_level.txt +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/api_key_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/auth_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/chat_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/conversation_persistence_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/flows_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/knowledge_filter_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/langflow_file_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/langflow_history_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/langflow_mcp_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/monitor_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/services/session_ownership_service.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/docker-compose.gpu.yml +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/ingestion_flow.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/openrag_agent.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/openrag_nudges.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/flows/openrag_url_mcp.json +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/openrag-documents/openrag-documentation.pdf +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/cli.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/managers/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/managers/docling_manager.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/screens/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/screens/diagnostics.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/screens/logs.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/screens/welcome.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/utils/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/utils/clipboard.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/utils/platform.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/utils/validation.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/utils/version_check.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/command_modal.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/diagnostics_notification.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/error_notification.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/flow_backup_warning_modal.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/prune_options_modal.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/version_mismatch_warning_modal.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/tui/widgets/waves.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/acl_utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/container_utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/docling_client.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/document_processing.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/env_utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/file_utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/gpu_detection.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/hash_utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/langflow_headers.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/langflow_utils.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/logging_config.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/opensearch_queries.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/paths.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/telemetry/__init__.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/telemetry/category.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/telemetry/client.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/telemetry/message_id.py +0 -0
- {openrag-0.4.0.dev9 → openrag-0.4.1}/src/utils/version_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
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
|
|
@@ -15,7 +15,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
15
15
|
Requires-Python: >=3.13
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: agentd>=0.
|
|
18
|
+
Requires-Dist: agentd>=0.8.1
|
|
19
19
|
Requires-Dist: aiofiles>=24.1.0
|
|
20
20
|
Requires-Dist: cryptography>=45.0.6
|
|
21
21
|
Requires-Dist: google-api-python-client>=2.143.0
|
|
@@ -37,6 +37,10 @@ Requires-Dist: python-dotenv>=1.0.0
|
|
|
37
37
|
Requires-Dist: textual-fspicker>=0.6.0
|
|
38
38
|
Requires-Dist: structlog>=25.4.0
|
|
39
39
|
Requires-Dist: zxcvbn>=4.5.0
|
|
40
|
+
Requires-Dist: litellm==1.83.3
|
|
41
|
+
Requires-Dist: pyyaml>=6.0
|
|
42
|
+
Requires-Dist: tiktoken>=0.7.0
|
|
43
|
+
Requires-Dist: openai>=2.30.0
|
|
40
44
|
Dynamic: license-file
|
|
41
45
|
|
|
42
46
|
<div align="center">
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openrag"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.1"
|
|
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"
|
|
@@ -21,7 +21,7 @@ classifiers = [
|
|
|
21
21
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
22
|
]
|
|
23
23
|
dependencies = [
|
|
24
|
-
"agentd>=0.
|
|
24
|
+
"agentd>=0.8.1",
|
|
25
25
|
"aiofiles>=24.1.0",
|
|
26
26
|
"cryptography>=45.0.6",
|
|
27
27
|
"google-api-python-client>=2.143.0",
|
|
@@ -42,7 +42,11 @@ dependencies = [
|
|
|
42
42
|
"python-dotenv>=1.0.0",
|
|
43
43
|
"textual-fspicker>=0.6.0",
|
|
44
44
|
"structlog>=25.4.0",
|
|
45
|
-
"zxcvbn>=4.5.0"
|
|
45
|
+
"zxcvbn>=4.5.0",
|
|
46
|
+
"litellm==1.83.3",
|
|
47
|
+
"pyyaml>=6.0",
|
|
48
|
+
"tiktoken>=0.7.0",
|
|
49
|
+
"openai>=2.30.0",
|
|
46
50
|
]
|
|
47
51
|
|
|
48
52
|
[dependency-groups]
|
|
@@ -158,7 +158,7 @@ async def async_response_stream(
|
|
|
158
158
|
else:
|
|
159
159
|
delta_text = str(chunk.delta)
|
|
160
160
|
full_response += delta_text
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
# Enhanced logging for tool call detection (Granite 3.3 8b investigation)
|
|
163
163
|
chunk_attrs = dir(chunk) if hasattr(chunk, '__dict__') else []
|
|
164
164
|
tool_related_attrs = [attr for attr in chunk_attrs if 'tool' in attr.lower() or 'call' in attr.lower() or 'retrieval' in attr.lower()]
|
|
@@ -180,7 +180,7 @@ async def async_response_stream(
|
|
|
180
180
|
chunk_data = chunk.__dict__
|
|
181
181
|
else:
|
|
182
182
|
chunk_data = str(chunk)
|
|
183
|
-
|
|
183
|
+
|
|
184
184
|
# Log detailed chunk structure for investigation (especially for Granite 3.3 8b)
|
|
185
185
|
if isinstance(chunk_data, dict):
|
|
186
186
|
# Check for any fields that might indicate tool usage
|
|
@@ -218,7 +218,7 @@ async def async_response_stream(
|
|
|
218
218
|
'retrieved_documents' in chunk_data,
|
|
219
219
|
'retrieval_results' in chunk_data,
|
|
220
220
|
])
|
|
221
|
-
|
|
221
|
+
|
|
222
222
|
if has_results:
|
|
223
223
|
logger.info(
|
|
224
224
|
"Detected implicit tool call in backend, injecting synthetic event",
|
|
@@ -242,7 +242,7 @@ async def async_response_stream(
|
|
|
242
242
|
# Send the synthetic event first
|
|
243
243
|
yield (json.dumps(synthetic_event, default=str) + "\n").encode("utf-8")
|
|
244
244
|
detected_tool_call = True # Mark that we've injected a tool call
|
|
245
|
-
|
|
245
|
+
|
|
246
246
|
yield (json.dumps(chunk_data, default=str) + "\n").encode("utf-8")
|
|
247
247
|
except Exception as e:
|
|
248
248
|
# Fallback to string representation
|
|
@@ -626,20 +626,68 @@ async def async_langflow_chat(
|
|
|
626
626
|
|
|
627
627
|
# Extract sources from retrieval tool calls in the response
|
|
628
628
|
sources = []
|
|
629
|
+
|
|
630
|
+
# Layer 1: Structured output items (OpenAI Responses API format).
|
|
631
|
+
# Relaxed: check for any output item with a non-empty `results` field,
|
|
632
|
+
# regardless of `type` string (Langflow may use different type names).
|
|
629
633
|
if hasattr(response_obj, "output") and response_obj.output:
|
|
630
634
|
for output_item in response_obj.output:
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
635
|
+
for result in getattr(output_item, "results", None) or []:
|
|
636
|
+
rd = (
|
|
637
|
+
result.model_dump()
|
|
638
|
+
if hasattr(result, "model_dump")
|
|
639
|
+
else (result if isinstance(result, dict) else {})
|
|
640
|
+
)
|
|
641
|
+
if "text" in rd:
|
|
642
|
+
sources.append({
|
|
643
|
+
"filename": rd.get("filename", ""),
|
|
644
|
+
"text": rd.get("text", ""),
|
|
645
|
+
"score": rd.get("score", 0),
|
|
646
|
+
"page": rd.get("page"),
|
|
647
|
+
"mimetype": rd.get("mimetype"),
|
|
648
|
+
})
|
|
649
|
+
|
|
650
|
+
# Layer 2: Top-level dict inspection (mirrors streaming middleware in async_response_stream).
|
|
651
|
+
# Langflow may embed retrieval results directly in the response dict rather than
|
|
652
|
+
# inside typed output items.
|
|
653
|
+
if not sources:
|
|
654
|
+
resp_dict = (
|
|
655
|
+
response_obj.model_dump()
|
|
656
|
+
if hasattr(response_obj, "model_dump")
|
|
657
|
+
else getattr(response_obj, "__dict__", {})
|
|
658
|
+
)
|
|
659
|
+
implicit_results = (
|
|
660
|
+
resp_dict.get("results")
|
|
661
|
+
or resp_dict.get("outputs")
|
|
662
|
+
or resp_dict.get("retrieved_documents")
|
|
663
|
+
or resp_dict.get("retrieval_results")
|
|
664
|
+
or []
|
|
665
|
+
)
|
|
666
|
+
if isinstance(implicit_results, list):
|
|
667
|
+
for result in implicit_results:
|
|
668
|
+
if isinstance(result, dict) and "text" in result:
|
|
669
|
+
sources.append({
|
|
670
|
+
"filename": result.get("filename", ""),
|
|
671
|
+
"text": result.get("text", ""),
|
|
672
|
+
"score": result.get("score", 0),
|
|
673
|
+
"page": result.get("page"),
|
|
674
|
+
"mimetype": result.get("mimetype"),
|
|
675
|
+
})
|
|
676
|
+
|
|
677
|
+
# Layer 3: Citation-text fallback.
|
|
678
|
+
# Parse "(Source: filename)" patterns emitted by the LLM when it cites documents.
|
|
679
|
+
# This is the last-resort fallback when Langflow's response object carries no
|
|
680
|
+
# structured retrieval data.
|
|
681
|
+
if not sources:
|
|
682
|
+
import re
|
|
683
|
+
for match in re.finditer(r"\(Source:\s*([^\)]+)\)", response_text):
|
|
684
|
+
sources.append({
|
|
685
|
+
"filename": match.group(1).strip(),
|
|
686
|
+
"text": "",
|
|
687
|
+
"score": 0,
|
|
688
|
+
"page": None,
|
|
689
|
+
"mimetype": None,
|
|
690
|
+
})
|
|
643
691
|
|
|
644
692
|
if not store_conversation:
|
|
645
693
|
return response_text, response_id, sources
|
|
@@ -739,7 +787,7 @@ async def async_langflow_chat_stream(
|
|
|
739
787
|
response_id = chunk_data["id"]
|
|
740
788
|
elif "response_id" in chunk_data:
|
|
741
789
|
response_id = chunk_data["response_id"]
|
|
742
|
-
|
|
790
|
+
|
|
743
791
|
# Check for error status
|
|
744
792
|
if chunk_data.get("finish_reason") == "error" or chunk_data.get("status") == "failed":
|
|
745
793
|
error_occurred = True
|
|
@@ -788,7 +836,7 @@ async def async_langflow_chat_stream(
|
|
|
788
836
|
# Log the error
|
|
789
837
|
logger.error(f"Error in langflow chat stream: {e}", exc_info=True)
|
|
790
838
|
error_occurred = True
|
|
791
|
-
|
|
839
|
+
|
|
792
840
|
# Store error message in conversation history so it persists
|
|
793
841
|
error_message = {
|
|
794
842
|
"role": "assistant",
|
|
@@ -797,19 +845,19 @@ async def async_langflow_chat_stream(
|
|
|
797
845
|
"error": True,
|
|
798
846
|
}
|
|
799
847
|
conversation_state["messages"].append(error_message)
|
|
800
|
-
|
|
848
|
+
|
|
801
849
|
# Try to store the conversation with error message
|
|
802
850
|
# Use a temporary response_id if we don't have one
|
|
803
851
|
if not response_id:
|
|
804
852
|
response_id = f"error_{user_id}_{int(datetime.now().timestamp())}"
|
|
805
|
-
|
|
853
|
+
|
|
806
854
|
try:
|
|
807
855
|
conversation_state["last_activity"] = datetime.now()
|
|
808
856
|
await store_conversation_thread(user_id, response_id, conversation_state)
|
|
809
857
|
logger.debug(f"Stored conversation with error for user {user_id}")
|
|
810
858
|
except Exception as store_error:
|
|
811
859
|
logger.error(f"Failed to store error conversation: {store_error}")
|
|
812
|
-
|
|
860
|
+
|
|
813
861
|
# Re-raise the exception so it propagates to the API layer
|
|
814
862
|
raise
|
|
815
863
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from dependencies import get_models_service
|
|
1
2
|
import asyncio
|
|
2
3
|
import json
|
|
3
4
|
import platform
|
|
@@ -9,7 +10,6 @@ from utils.telemetry import TelemetryClient, Category, MessageId
|
|
|
9
10
|
from utils.version_utils import OPENRAG_VERSION
|
|
10
11
|
from config.settings import (
|
|
11
12
|
DEFAULT_DOCS_URL,
|
|
12
|
-
DISABLE_INGEST_WITH_LANGFLOW,
|
|
13
13
|
INGEST_SAMPLE_DATA,
|
|
14
14
|
LANGFLOW_URL,
|
|
15
15
|
LANGFLOW_CHAT_FLOW_ID,
|
|
@@ -885,6 +885,7 @@ async def onboarding(
|
|
|
885
885
|
flows_service=Depends(get_flows_service),
|
|
886
886
|
session_manager=Depends(get_session_manager),
|
|
887
887
|
document_service=Depends(get_document_service),
|
|
888
|
+
models_service=Depends(get_models_service),
|
|
888
889
|
task_service=Depends(get_task_service),
|
|
889
890
|
langflow_file_service=Depends(get_langflow_file_service),
|
|
890
891
|
knowledge_filter_service=Depends(get_knowledge_filter_service),
|
|
@@ -936,7 +937,7 @@ async def onboarding(
|
|
|
936
937
|
embedding_model_selected = None
|
|
937
938
|
embedding_provider_selected = None
|
|
938
939
|
|
|
939
|
-
if body.embedding_model
|
|
940
|
+
if body.embedding_model:
|
|
940
941
|
embedding_model_selected = body.embedding_model.strip()
|
|
941
942
|
current_config.knowledge.embedding_model = embedding_model_selected
|
|
942
943
|
config_updated = True
|
|
@@ -1151,8 +1152,12 @@ async def onboarding(
|
|
|
1151
1152
|
# Import the function here to avoid circular imports
|
|
1152
1153
|
from main import ingest_default_documents_when_ready
|
|
1153
1154
|
|
|
1155
|
+
if not config_manager.save_config_file(current_config):
|
|
1156
|
+
logger.error("Failed to save embedding model to config")
|
|
1157
|
+
|
|
1154
1158
|
task_id = await ingest_default_documents_when_ready(
|
|
1155
1159
|
document_service,
|
|
1160
|
+
models_service,
|
|
1156
1161
|
task_service,
|
|
1157
1162
|
langflow_file_service,
|
|
1158
1163
|
session_manager,
|
|
@@ -1664,8 +1669,6 @@ async def rollback_onboarding(
|
|
|
1664
1669
|
{"error": "No onboarding configuration to rollback"}, status_code=400
|
|
1665
1670
|
)
|
|
1666
1671
|
|
|
1667
|
-
jwt_token = user.jwt_token
|
|
1668
|
-
|
|
1669
1672
|
logger.info("Rolling back onboarding configuration due to file failures")
|
|
1670
1673
|
|
|
1671
1674
|
# Get all tasks for the user
|
|
@@ -1728,7 +1731,7 @@ async def rollback_onboarding(
|
|
|
1728
1731
|
if filename:
|
|
1729
1732
|
try:
|
|
1730
1733
|
opensearch_client = session_manager.get_user_opensearch_client(
|
|
1731
|
-
user.user_id, jwt_token
|
|
1734
|
+
user.user_id, user.jwt_token
|
|
1732
1735
|
)
|
|
1733
1736
|
from utils.opensearch_queries import build_filename_delete_body
|
|
1734
1737
|
from config.settings import get_index_name
|
|
@@ -1890,6 +1893,7 @@ async def update_docling_preset(
|
|
|
1890
1893
|
async def refresh_openrag_docs(
|
|
1891
1894
|
document_service=Depends(get_document_service),
|
|
1892
1895
|
task_service=Depends(get_task_service),
|
|
1896
|
+
models_service=Depends(get_models_service),
|
|
1893
1897
|
langflow_file_service=Depends(get_langflow_file_service),
|
|
1894
1898
|
session_manager=Depends(get_session_manager),
|
|
1895
1899
|
user: User = Depends(get_current_user),
|
|
@@ -1900,6 +1904,7 @@ async def refresh_openrag_docs(
|
|
|
1900
1904
|
|
|
1901
1905
|
refreshed = await refresh_default_openrag_docs(
|
|
1902
1906
|
document_service=document_service,
|
|
1907
|
+
models_service=models_service,
|
|
1903
1908
|
task_service=task_service,
|
|
1904
1909
|
langflow_file_service=langflow_file_service,
|
|
1905
1910
|
session_manager=session_manager,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from dependencies import get_models_service
|
|
1
2
|
import os
|
|
2
3
|
from typing import Optional
|
|
3
4
|
from urllib.parse import urlparse
|
|
@@ -35,15 +36,10 @@ async def upload(
|
|
|
35
36
|
try:
|
|
36
37
|
|
|
37
38
|
from config.settings import is_no_auth_mode
|
|
38
|
-
|
|
39
|
-
if
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
owner_email = None
|
|
43
|
-
else:
|
|
44
|
-
owner_user_id = user.user_id
|
|
45
|
-
owner_name = user.name
|
|
46
|
-
owner_email = user.email
|
|
39
|
+
is_no_auth = is_no_auth_mode()
|
|
40
|
+
owner_user_id = user.user_id if (user and not is_no_auth) else None
|
|
41
|
+
owner_name = user.name if user else None
|
|
42
|
+
owner_email = user.email if user else None
|
|
47
43
|
|
|
48
44
|
result = await document_service.process_upload_file(
|
|
49
45
|
file,
|
|
@@ -84,15 +80,10 @@ async def upload_path(
|
|
|
84
80
|
jwt_token = user.jwt_token
|
|
85
81
|
|
|
86
82
|
from config.settings import is_no_auth_mode
|
|
87
|
-
|
|
88
|
-
if
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
owner_email = None
|
|
92
|
-
else:
|
|
93
|
-
owner_user_id = user.user_id
|
|
94
|
-
owner_name = user.name
|
|
95
|
-
owner_email = user.email
|
|
83
|
+
is_no_auth = is_no_auth_mode()
|
|
84
|
+
owner_user_id = user.user_id if (user and not is_no_auth) else None
|
|
85
|
+
owner_name = user.name if user else None
|
|
86
|
+
owner_email = user.email if user else None
|
|
96
87
|
|
|
97
88
|
from api.documents import _ensure_index_exists
|
|
98
89
|
await _ensure_index_exists()
|
|
@@ -163,6 +154,7 @@ async def upload_options(
|
|
|
163
154
|
async def upload_bucket(
|
|
164
155
|
body: UploadBucketBody,
|
|
165
156
|
task_service=Depends(get_task_service),
|
|
157
|
+
models_service=Depends(get_models_service),
|
|
166
158
|
session_manager=Depends(get_session_manager),
|
|
167
159
|
user: User = Depends(get_current_user),
|
|
168
160
|
):
|
|
@@ -194,18 +186,13 @@ async def upload_bucket(
|
|
|
194
186
|
jwt_token = user.jwt_token
|
|
195
187
|
|
|
196
188
|
from models.processors import S3FileProcessor
|
|
197
|
-
from config.settings import is_no_auth_mode
|
|
198
189
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
else
|
|
205
|
-
owner_user_id = user.user_id
|
|
206
|
-
owner_name = user.name
|
|
207
|
-
owner_email = user.email
|
|
208
|
-
task_user_id = user.user_id
|
|
190
|
+
from config.settings import is_no_auth_mode
|
|
191
|
+
is_no_auth = is_no_auth_mode()
|
|
192
|
+
owner_user_id = user.user_id if (user and not is_no_auth) else None
|
|
193
|
+
owner_name = user.name if user else None
|
|
194
|
+
owner_email = user.email if user else None
|
|
195
|
+
task_user_id = user.user_id if (user and not is_no_auth) else None
|
|
209
196
|
|
|
210
197
|
from api.documents import _ensure_index_exists
|
|
211
198
|
await _ensure_index_exists()
|
|
@@ -213,6 +200,7 @@ async def upload_bucket(
|
|
|
213
200
|
processor = S3FileProcessor(
|
|
214
201
|
task_service.document_service,
|
|
215
202
|
bucket,
|
|
203
|
+
models_service=models_service,
|
|
216
204
|
s3_client=s3_client,
|
|
217
205
|
owner_user_id=owner_user_id,
|
|
218
206
|
jwt_token=jwt_token,
|
|
@@ -31,8 +31,6 @@ OPENAI_VALIDATION_MODELS = [
|
|
|
31
31
|
]
|
|
32
32
|
|
|
33
33
|
OPENAI_DEFAULT_LANGUAGE_MODEL = "gpt-4o"
|
|
34
|
-
OPENAI_DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small"
|
|
35
|
-
OPENAI_EMBEDDING_MODEL_PREFIX = "text-embedding"
|
|
36
34
|
|
|
37
35
|
ANTHROPIC_DEFAULT_LANGUAGE_MODEL = "claude-sonnet-4-5-20250929"
|
|
38
36
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import os
|
|
3
|
+
import threading
|
|
4
|
+
import concurrent.futures
|
|
3
5
|
from utils.env_utils import get_env_int, get_env_float
|
|
4
6
|
|
|
5
7
|
import httpx
|
|
@@ -8,6 +10,7 @@ from dotenv import load_dotenv
|
|
|
8
10
|
from openai import AsyncOpenAI
|
|
9
11
|
from opensearchpy import AsyncOpenSearch
|
|
10
12
|
from opensearchpy._async.http_aiohttp import AIOHttpConnection
|
|
13
|
+
from config.embedding_constants import OPENAI_DEFAULT_EMBEDDING_MODEL
|
|
11
14
|
|
|
12
15
|
from utils.container_utils import get_container_host
|
|
13
16
|
from utils.logging_config import get_logger
|
|
@@ -107,26 +110,6 @@ WEBHOOK_BASE_URL = os.getenv(
|
|
|
107
110
|
VECTOR_DIM = 1536
|
|
108
111
|
KNN_EF_CONSTRUCTION = 100
|
|
109
112
|
KNN_M = 16
|
|
110
|
-
EMBED_MODEL = "text-embedding-3-small"
|
|
111
|
-
|
|
112
|
-
OPENAI_EMBEDDING_DIMENSIONS = {
|
|
113
|
-
"text-embedding-3-small": 1536,
|
|
114
|
-
"text-embedding-3-large": 3072,
|
|
115
|
-
"text-embedding-ada-002": 1536,
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
WATSONX_EMBEDDING_DIMENSIONS = {
|
|
119
|
-
# IBM Models
|
|
120
|
-
"ibm/granite-embedding-107m-multilingual": 384,
|
|
121
|
-
"ibm/granite-embedding-278m-multilingual": 1024,
|
|
122
|
-
"ibm/slate-125m-english-rtrvr": 768,
|
|
123
|
-
"ibm/slate-125m-english-rtrvr-v2": 768,
|
|
124
|
-
"ibm/slate-30m-english-rtrvr": 384,
|
|
125
|
-
"ibm/slate-30m-english-rtrvr-v2": 384,
|
|
126
|
-
# Third Party Models
|
|
127
|
-
"intfloat/multilingual-e5-large": 1024,
|
|
128
|
-
"sentence-transformers/all-minilm-l6-v2": 384,
|
|
129
|
-
}
|
|
130
113
|
|
|
131
114
|
INDEX_BODY = {
|
|
132
115
|
"settings": {
|
|
@@ -320,7 +303,7 @@ class AppClients:
|
|
|
320
303
|
self.langflow_client = None
|
|
321
304
|
self.langflow_http_client = None
|
|
322
305
|
self._patched_async_client = None # Private attribute - single client for all providers
|
|
323
|
-
self._client_init_lock =
|
|
306
|
+
self._client_init_lock = threading.Lock() # Lock for thread-safe initialization
|
|
324
307
|
self.docling_http_client = None
|
|
325
308
|
|
|
326
309
|
async def initialize(self):
|
|
@@ -455,6 +438,11 @@ class AppClients:
|
|
|
455
438
|
if config.providers.openai.api_key:
|
|
456
439
|
os.environ["OPENAI_API_KEY"] = config.providers.openai.api_key
|
|
457
440
|
logger.debug("Loaded OpenAI API key from config")
|
|
441
|
+
elif not os.environ.get("OPENAI_API_KEY"):
|
|
442
|
+
# Provide dummy key to satisfy AsyncOpenAI constructor;
|
|
443
|
+
# LiteLLM/MCP will handle routing to other providers if needed.
|
|
444
|
+
os.environ["OPENAI_API_KEY"] = "no-key-required"
|
|
445
|
+
logger.debug("Using dummy OpenAI API key to satisfy client constructor")
|
|
458
446
|
|
|
459
447
|
# Set Anthropic credentials
|
|
460
448
|
if config.providers.anthropic.api_key:
|
|
@@ -478,14 +466,23 @@ class AppClients:
|
|
|
478
466
|
os.environ["OLLAMA_ENDPOINT"] = config.providers.ollama.endpoint
|
|
479
467
|
logger.debug("Loaded Ollama endpoint from config")
|
|
480
468
|
|
|
469
|
+
# Determine model and provider for both probe and production client
|
|
470
|
+
model_name = config.knowledge.embedding_model or OPENAI_DEFAULT_EMBEDDING_MODEL
|
|
471
|
+
provider = config.knowledge.embedding_provider or "openai"
|
|
481
472
|
except Exception as e:
|
|
482
473
|
logger.debug("Could not load provider credentials from config", error=str(e))
|
|
474
|
+
# Provide fallbacks if config loading failed
|
|
475
|
+
model_name = OPENAI_DEFAULT_EMBEDDING_MODEL
|
|
476
|
+
provider = "openai"
|
|
477
|
+
# Ensure a dummy key is available to satisfy the AsyncOpenAI constructor
|
|
478
|
+
# and avoid AuthenticationError if config loading failed.
|
|
479
|
+
if not os.environ.get("OPENAI_API_KEY"):
|
|
480
|
+
os.environ["OPENAI_API_KEY"] = "no-key-required"
|
|
481
|
+
logger.debug("Using dummy OpenAI API key fallback (config load failed)")
|
|
482
|
+
|
|
483
483
|
|
|
484
|
-
#
|
|
485
|
-
|
|
486
|
-
import asyncio
|
|
487
|
-
import concurrent.futures
|
|
488
|
-
import threading
|
|
484
|
+
# API key for AsyncOpenAI constructor
|
|
485
|
+
api_key = os.environ.get("OPENAI_API_KEY")
|
|
489
486
|
|
|
490
487
|
async def probe_http2():
|
|
491
488
|
"""Returns True if HTTP/2 works, False to fall back to HTTP/1.1.
|
|
@@ -495,20 +492,21 @@ class AppClients:
|
|
|
495
492
|
production client is created after this thread exits, in the
|
|
496
493
|
caller's event loop, avoiding cross-loop SSL transport errors.
|
|
497
494
|
"""
|
|
498
|
-
client
|
|
499
|
-
|
|
495
|
+
# Use a standard OpenAI client for the probe (only runs for OpenAI provider)
|
|
496
|
+
client = AsyncOpenAI(api_key=api_key)
|
|
497
|
+
logger.info(f"Probing client with HTTP/2 using model {model_name}...")
|
|
500
498
|
try:
|
|
501
499
|
await asyncio.wait_for(
|
|
502
500
|
client.embeddings.create(
|
|
503
|
-
model=
|
|
501
|
+
model=model_name,
|
|
504
502
|
input=['test']
|
|
505
503
|
),
|
|
506
504
|
timeout=5.0
|
|
507
505
|
)
|
|
508
|
-
logger.info("HTTP/2 probe successful")
|
|
506
|
+
logger.info(f"HTTP/2 probe successful with {model_name}")
|
|
509
507
|
return True
|
|
510
508
|
except (asyncio.TimeoutError, Exception) as probe_error:
|
|
511
|
-
logger.warning("HTTP/2 probe failed, falling back to HTTP/1.1", error=str(probe_error))
|
|
509
|
+
logger.warning(f"HTTP/2 probe failed with {model_name}, falling back to HTTP/1.1", error=str(probe_error))
|
|
512
510
|
return False
|
|
513
511
|
finally:
|
|
514
512
|
# Always close the probe client so its connections are fully
|
|
@@ -528,26 +526,32 @@ class AppClients:
|
|
|
528
526
|
loop.close()
|
|
529
527
|
|
|
530
528
|
try:
|
|
531
|
-
# Run the probe
|
|
532
|
-
#
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
529
|
+
# Run the probe only for OpenAI provider; local and other providers
|
|
530
|
+
# (Ollama, WatsonX) typically use HTTP/1.1 for reliability.
|
|
531
|
+
if provider.lower() == "openai":
|
|
532
|
+
# Run the probe in a separate thread with its own event loop.
|
|
533
|
+
# Only the probe result (bool) crosses the thread boundary;
|
|
534
|
+
# the production client is created here so its connections are
|
|
535
|
+
# bound to the caller's event loop, not the (now closed) probe loop.
|
|
536
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
|
|
537
|
+
future = executor.submit(run_probe_in_thread)
|
|
538
|
+
use_http2 = future.result(timeout=15)
|
|
539
|
+
else:
|
|
540
|
+
use_http2 = False
|
|
541
|
+
logger.debug(f"Skipping HTTP/2 probe for provider: {provider}")
|
|
538
542
|
|
|
539
543
|
if use_http2:
|
|
540
|
-
self._patched_async_client = patch_openai_with_mcp(AsyncOpenAI())
|
|
541
|
-
logger.info("OpenAI client initialized with HTTP/2")
|
|
544
|
+
self._patched_async_client = patch_openai_with_mcp(AsyncOpenAI(api_key=api_key))
|
|
545
|
+
logger.info(f"OpenAI-compatible client initialized with HTTP/2 (model: {model_name})")
|
|
542
546
|
else:
|
|
543
547
|
http_client = httpx.AsyncClient(
|
|
544
548
|
http2=False,
|
|
545
549
|
timeout=httpx.Timeout(60.0, connect=10.0)
|
|
546
550
|
)
|
|
547
551
|
self._patched_async_client = patch_openai_with_mcp(
|
|
548
|
-
AsyncOpenAI(http_client=http_client)
|
|
552
|
+
AsyncOpenAI(api_key=api_key, http_client=http_client)
|
|
549
553
|
)
|
|
550
|
-
logger.info("OpenAI client initialized with HTTP/1.1 (
|
|
554
|
+
logger.info(f"OpenAI-compatible client initialized with HTTP/1.1 fallback (model: {model_name})")
|
|
551
555
|
logger.info("Successfully initialized OpenAI client")
|
|
552
556
|
except Exception as e:
|
|
553
557
|
logger.error(f"Failed to initialize OpenAI client: {e.__class__.__name__}: {str(e)}")
|
|
@@ -864,7 +868,7 @@ def get_openrag_config():
|
|
|
864
868
|
# Expose configuration settings for backward compatibility and easy access
|
|
865
869
|
def get_provider_config():
|
|
866
870
|
"""Get provider configuration."""
|
|
867
|
-
return get_openrag_config().
|
|
871
|
+
return get_openrag_config().providers
|
|
868
872
|
|
|
869
873
|
|
|
870
874
|
def get_knowledge_config():
|
|
@@ -879,7 +883,7 @@ def get_agent_config():
|
|
|
879
883
|
|
|
880
884
|
def get_embedding_model() -> str:
|
|
881
885
|
"""Return the currently configured embedding model."""
|
|
882
|
-
return get_openrag_config().knowledge.embedding_model or
|
|
886
|
+
return get_openrag_config().knowledge.embedding_model or (OPENAI_DEFAULT_EMBEDDING_MODEL if DISABLE_INGEST_WITH_LANGFLOW else "")
|
|
883
887
|
|
|
884
888
|
|
|
885
889
|
def get_index_name() -> str:
|
|
@@ -20,6 +20,8 @@ class ConnectorService:
|
|
|
20
20
|
index_name: str,
|
|
21
21
|
task_service=None,
|
|
22
22
|
session_manager=None,
|
|
23
|
+
models_service=None,
|
|
24
|
+
document_service=None,
|
|
23
25
|
):
|
|
24
26
|
self.clients = patched_async_client
|
|
25
27
|
self.embed_model = embed_model
|
|
@@ -27,6 +29,8 @@ class ConnectorService:
|
|
|
27
29
|
self.task_service = task_service
|
|
28
30
|
self.session_manager = session_manager
|
|
29
31
|
self.connection_manager = ConnectionManager()
|
|
32
|
+
self.models_service = models_service
|
|
33
|
+
self.document_service = document_service
|
|
30
34
|
|
|
31
35
|
async def initialize(self):
|
|
32
36
|
"""Initialize the service by loading existing connections"""
|
|
@@ -57,18 +61,12 @@ class ConnectorService:
|
|
|
57
61
|
with open(tmp_path, "wb") as f:
|
|
58
62
|
f.write(document.content)
|
|
59
63
|
|
|
60
|
-
# Use existing process_file_common function with connector document metadata
|
|
61
|
-
# We'll use the document service's process_file_common method
|
|
62
|
-
from services.document_service import DocumentService
|
|
63
|
-
|
|
64
|
-
doc_service = DocumentService(session_manager=self.session_manager)
|
|
65
|
-
|
|
66
64
|
logger.debug("Processing connector document", document_id=document.id)
|
|
67
65
|
|
|
68
66
|
# Process using consolidated processing pipeline
|
|
69
67
|
from models.processors import TaskProcessor
|
|
70
68
|
|
|
71
|
-
processor = TaskProcessor(document_service=
|
|
69
|
+
processor = TaskProcessor(document_service=self.document_service, models_service=self.models_service)
|
|
72
70
|
result = await processor.process_document_standard(
|
|
73
71
|
file_path=tmp_path,
|
|
74
72
|
file_hash=document.id, # Use connector document ID as hash
|
|
@@ -284,6 +282,7 @@ class ConnectorService:
|
|
|
284
282
|
if self.task_service and self.task_service.document_service
|
|
285
283
|
else DocumentService(session_manager=self.session_manager)
|
|
286
284
|
),
|
|
285
|
+
models_service=self.models_service,
|
|
287
286
|
)
|
|
288
287
|
|
|
289
288
|
# Use file IDs as items (no more fake file paths!)
|
|
@@ -415,6 +414,7 @@ class ConnectorService:
|
|
|
415
414
|
if self.task_service and self.task_service.document_service
|
|
416
415
|
else DocumentService(session_manager=self.session_manager)
|
|
417
416
|
),
|
|
417
|
+
models_service=self.models_service,
|
|
418
418
|
)
|
|
419
419
|
|
|
420
420
|
# Create custom task using TaskService
|