OpenRAG 0.4.1__tar.gz → 0.4.1.dev1__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.
Files changed (166) hide show
  1. {openrag-0.4.1/src/openrag.egg-info → openrag-0.4.1.dev1}/PKG-INFO +2 -4
  2. {openrag-0.4.1 → openrag-0.4.1.dev1}/pyproject.toml +2 -4
  3. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/agent.py +21 -69
  4. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/settings.py +5 -10
  5. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/upload.py +29 -17
  6. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/config/model_constants.py +2 -0
  7. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/config/settings.py +44 -51
  8. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/service.py +7 -7
  9. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/main.py +44 -99
  10. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/models/processors.py +20 -37
  11. {openrag-0.4.1 → openrag-0.4.1.dev1/src/openrag.egg-info}/PKG-INFO +2 -4
  12. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/openrag.egg-info/SOURCES.txt +0 -1
  13. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/openrag.egg-info/requires.txt +1 -3
  14. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/document_service.py +9 -15
  15. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/models_service.py +13 -150
  16. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/search_service.py +25 -62
  17. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/task_service.py +1 -15
  18. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/session_manager.py +0 -2
  19. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/docker-compose.yml +19 -22
  20. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/config_fields.py +6 -0
  21. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/main.py +6 -3
  22. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/managers/container_manager.py +13 -27
  23. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/managers/env_manager.py +7 -2
  24. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/screens/config.py +78 -0
  25. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/screens/monitor.py +17 -0
  26. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/utils/startup_checks.py +19 -86
  27. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/embedding_fields.py +2 -4
  28. openrag-0.4.1.dev1/src/utils/embeddings.py +196 -0
  29. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/opensearch_utils.py +0 -37
  30. openrag-0.4.1/src/config/embedding_constants.py +0 -4
  31. openrag-0.4.1/src/utils/embeddings.py +0 -39
  32. {openrag-0.4.1 → openrag-0.4.1.dev1}/LICENSE +0 -0
  33. {openrag-0.4.1 → openrag-0.4.1.dev1}/MANIFEST.in +0 -0
  34. {openrag-0.4.1 → openrag-0.4.1.dev1}/README.md +0 -0
  35. {openrag-0.4.1 → openrag-0.4.1.dev1}/setup.cfg +0 -0
  36. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/__init__.py +0 -0
  37. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/auth.py +0 -0
  38. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/chat.py +0 -0
  39. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/connector_router.py +0 -0
  40. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/connectors.py +0 -0
  41. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/docling.py +0 -0
  42. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/documents.py +0 -0
  43. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/flows.py +0 -0
  44. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/keys.py +0 -0
  45. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/knowledge_filter.py +0 -0
  46. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/langflow_files.py +0 -0
  47. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/models.py +0 -0
  48. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/nudges.py +0 -0
  49. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/oidc.py +0 -0
  50. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/provider_health.py +0 -0
  51. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/provider_validation.py +0 -0
  52. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/router.py +0 -0
  53. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/search.py +0 -0
  54. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/tasks.py +0 -0
  55. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/__init__.py +0 -0
  56. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/chat.py +0 -0
  57. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/documents.py +0 -0
  58. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/knowledge_filters.py +0 -0
  59. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/models.py +0 -0
  60. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/search.py +0 -0
  61. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/api/v1/settings.py +0 -0
  62. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/auth_context.py +0 -0
  63. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/config/__init__.py +0 -0
  64. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/config/config_manager.py +0 -0
  65. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/__init__.py +0 -0
  66. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/aws_s3/__init__.py +0 -0
  67. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/aws_s3/api.py +0 -0
  68. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/aws_s3/auth.py +0 -0
  69. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/aws_s3/connector.py +0 -0
  70. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/aws_s3/models.py +0 -0
  71. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/aws_s3/support.py +0 -0
  72. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/base.py +0 -0
  73. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/connection_manager.py +0 -0
  74. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/google_drive/__init__.py +0 -0
  75. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/google_drive/connector.py +0 -0
  76. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/google_drive/oauth.py +0 -0
  77. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/ibm_cos/__init__.py +0 -0
  78. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/ibm_cos/api.py +0 -0
  79. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/ibm_cos/auth.py +0 -0
  80. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/ibm_cos/connector.py +0 -0
  81. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/ibm_cos/models.py +0 -0
  82. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/ibm_cos/support.py +0 -0
  83. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/langflow_connector_service.py +0 -0
  84. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/onedrive/__init__.py +0 -0
  85. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/onedrive/connector.py +0 -0
  86. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/onedrive/oauth.py +0 -0
  87. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/sharepoint/__init__.py +0 -0
  88. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/sharepoint/connector.py +0 -0
  89. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/sharepoint/oauth.py +0 -0
  90. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/connectors/sharepoint/utils.py +0 -0
  91. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/dependencies.py +0 -0
  92. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/models/__init__.py +0 -0
  93. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/models/tasks.py +0 -0
  94. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/models/url.py +0 -0
  95. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/openrag.egg-info/dependency_links.txt +0 -0
  96. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/openrag.egg-info/entry_points.txt +0 -0
  97. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/openrag.egg-info/top_level.txt +0 -0
  98. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/__init__.py +0 -0
  99. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/api_key_service.py +0 -0
  100. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/auth_service.py +0 -0
  101. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/chat_service.py +0 -0
  102. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/conversation_persistence_service.py +0 -0
  103. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/flows_service.py +0 -0
  104. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/knowledge_filter_service.py +0 -0
  105. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/langflow_file_service.py +0 -0
  106. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/langflow_history_service.py +0 -0
  107. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/langflow_mcp_service.py +0 -0
  108. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/monitor_service.py +0 -0
  109. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/services/session_ownership_service.py +0 -0
  110. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/__init__.py +0 -0
  111. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/docker-compose.gpu.yml +0 -0
  112. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
  113. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
  114. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
  115. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
  116. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
  117. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
  118. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/ingestion_flow.json +0 -0
  119. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/openrag_agent.json +0 -0
  120. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/openrag_nudges.json +0 -0
  121. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/flows/openrag_url_mcp.json +0 -0
  122. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
  123. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
  124. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/openrag-documents/openrag-documentation.pdf +0 -0
  125. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
  126. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/cli.py +0 -0
  127. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/managers/__init__.py +0 -0
  128. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/managers/docling_manager.py +0 -0
  129. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/screens/__init__.py +0 -0
  130. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/screens/diagnostics.py +0 -0
  131. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/screens/logs.py +0 -0
  132. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/screens/welcome.py +0 -0
  133. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/utils/__init__.py +0 -0
  134. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/utils/clipboard.py +0 -0
  135. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/utils/platform.py +0 -0
  136. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/utils/validation.py +0 -0
  137. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/utils/version_check.py +0 -0
  138. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/__init__.py +0 -0
  139. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/command_modal.py +0 -0
  140. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/diagnostics_notification.py +0 -0
  141. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/error_notification.py +0 -0
  142. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
  143. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/flow_backup_warning_modal.py +0 -0
  144. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/prune_options_modal.py +0 -0
  145. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
  146. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/version_mismatch_warning_modal.py +0 -0
  147. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/tui/widgets/waves.py +0 -0
  148. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/__init__.py +0 -0
  149. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/acl_utils.py +0 -0
  150. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/container_utils.py +0 -0
  151. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/docling_client.py +0 -0
  152. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/document_processing.py +0 -0
  153. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/env_utils.py +0 -0
  154. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/file_utils.py +0 -0
  155. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/gpu_detection.py +0 -0
  156. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/hash_utils.py +0 -0
  157. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/langflow_headers.py +0 -0
  158. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/langflow_utils.py +0 -0
  159. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/logging_config.py +0 -0
  160. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/opensearch_queries.py +0 -0
  161. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/paths.py +0 -0
  162. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/telemetry/__init__.py +0 -0
  163. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/telemetry/category.py +0 -0
  164. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/telemetry/client.py +0 -0
  165. {openrag-0.4.1 → openrag-0.4.1.dev1}/src/utils/telemetry/message_id.py +0 -0
  166. {openrag-0.4.1 → openrag-0.4.1.dev1}/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.1
3
+ Version: 0.4.1.dev1
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,6 @@ 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.8.1
19
18
  Requires-Dist: aiofiles>=24.1.0
20
19
  Requires-Dist: cryptography>=45.0.6
21
20
  Requires-Dist: google-api-python-client>=2.143.0
@@ -37,10 +36,9 @@ Requires-Dist: python-dotenv>=1.0.0
37
36
  Requires-Dist: textual-fspicker>=0.6.0
38
37
  Requires-Dist: structlog>=25.4.0
39
38
  Requires-Dist: zxcvbn>=4.5.0
40
- Requires-Dist: litellm==1.83.3
39
+ Requires-Dist: openai>=1.0.0
41
40
  Requires-Dist: pyyaml>=6.0
42
41
  Requires-Dist: tiktoken>=0.7.0
43
- Requires-Dist: openai>=2.30.0
44
42
  Dynamic: license-file
45
43
 
46
44
  <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.1"
7
+ version = "0.4.1.dev1"
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,6 @@ classifiers = [
21
21
  "Topic :: Software Development :: Libraries :: Python Modules",
22
22
  ]
23
23
  dependencies = [
24
- "agentd>=0.8.1",
25
24
  "aiofiles>=24.1.0",
26
25
  "cryptography>=45.0.6",
27
26
  "google-api-python-client>=2.143.0",
@@ -43,10 +42,9 @@ dependencies = [
43
42
  "textual-fspicker>=0.6.0",
44
43
  "structlog>=25.4.0",
45
44
  "zxcvbn>=4.5.0",
46
- "litellm==1.83.3",
45
+ "openai>=1.0.0",
47
46
  "pyyaml>=6.0",
48
47
  "tiktoken>=0.7.0",
49
- "openai>=2.30.0",
50
48
  ]
51
49
 
52
50
  [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,68 +626,20 @@ 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).
633
629
  if hasattr(response_obj, "output") and response_obj.output:
634
630
  for output_item in response_obj.output:
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
- })
631
+ item_type = getattr(output_item, "type", None)
632
+ if item_type in ("tool_call", "retrieval_call"):
633
+ for result in getattr(output_item, "results", None) or []:
634
+ rd = result.model_dump() if hasattr(result, "model_dump") else (result if isinstance(result, dict) else {})
635
+ if "text" in rd:
636
+ sources.append({
637
+ "filename": rd.get("filename", ""),
638
+ "text": rd.get("text", ""),
639
+ "score": rd.get("score", 0),
640
+ "page": rd.get("page"),
641
+ "mimetype": rd.get("mimetype"),
642
+ })
691
643
 
692
644
  if not store_conversation:
693
645
  return response_text, response_id, sources
@@ -787,7 +739,7 @@ async def async_langflow_chat_stream(
787
739
  response_id = chunk_data["id"]
788
740
  elif "response_id" in chunk_data:
789
741
  response_id = chunk_data["response_id"]
790
-
742
+
791
743
  # Check for error status
792
744
  if chunk_data.get("finish_reason") == "error" or chunk_data.get("status") == "failed":
793
745
  error_occurred = True
@@ -836,7 +788,7 @@ async def async_langflow_chat_stream(
836
788
  # Log the error
837
789
  logger.error(f"Error in langflow chat stream: {e}", exc_info=True)
838
790
  error_occurred = True
839
-
791
+
840
792
  # Store error message in conversation history so it persists
841
793
  error_message = {
842
794
  "role": "assistant",
@@ -845,19 +797,19 @@ async def async_langflow_chat_stream(
845
797
  "error": True,
846
798
  }
847
799
  conversation_state["messages"].append(error_message)
848
-
800
+
849
801
  # Try to store the conversation with error message
850
802
  # Use a temporary response_id if we don't have one
851
803
  if not response_id:
852
804
  response_id = f"error_{user_id}_{int(datetime.now().timestamp())}"
853
-
805
+
854
806
  try:
855
807
  conversation_state["last_activity"] = datetime.now()
856
808
  await store_conversation_thread(user_id, response_id, conversation_state)
857
809
  logger.debug(f"Stored conversation with error for user {user_id}")
858
810
  except Exception as store_error:
859
811
  logger.error(f"Failed to store error conversation: {store_error}")
860
-
812
+
861
813
  # Re-raise the exception so it propagates to the API layer
862
814
  raise
863
815
 
@@ -1,4 +1,3 @@
1
- from dependencies import get_models_service
2
1
  import asyncio
3
2
  import json
4
3
  import platform
@@ -10,6 +9,7 @@ from utils.telemetry import TelemetryClient, Category, MessageId
10
9
  from utils.version_utils import OPENRAG_VERSION
11
10
  from config.settings import (
12
11
  DEFAULT_DOCS_URL,
12
+ DISABLE_INGEST_WITH_LANGFLOW,
13
13
  INGEST_SAMPLE_DATA,
14
14
  LANGFLOW_URL,
15
15
  LANGFLOW_CHAT_FLOW_ID,
@@ -885,7 +885,6 @@ 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),
889
888
  task_service=Depends(get_task_service),
890
889
  langflow_file_service=Depends(get_langflow_file_service),
891
890
  knowledge_filter_service=Depends(get_knowledge_filter_service),
@@ -937,7 +936,7 @@ async def onboarding(
937
936
  embedding_model_selected = None
938
937
  embedding_provider_selected = None
939
938
 
940
- if body.embedding_model:
939
+ if body.embedding_model and not DISABLE_INGEST_WITH_LANGFLOW:
941
940
  embedding_model_selected = body.embedding_model.strip()
942
941
  current_config.knowledge.embedding_model = embedding_model_selected
943
942
  config_updated = True
@@ -1152,12 +1151,8 @@ async def onboarding(
1152
1151
  # Import the function here to avoid circular imports
1153
1152
  from main import ingest_default_documents_when_ready
1154
1153
 
1155
- if not config_manager.save_config_file(current_config):
1156
- logger.error("Failed to save embedding model to config")
1157
-
1158
1154
  task_id = await ingest_default_documents_when_ready(
1159
1155
  document_service,
1160
- models_service,
1161
1156
  task_service,
1162
1157
  langflow_file_service,
1163
1158
  session_manager,
@@ -1669,6 +1664,8 @@ async def rollback_onboarding(
1669
1664
  {"error": "No onboarding configuration to rollback"}, status_code=400
1670
1665
  )
1671
1666
 
1667
+ jwt_token = user.jwt_token
1668
+
1672
1669
  logger.info("Rolling back onboarding configuration due to file failures")
1673
1670
 
1674
1671
  # Get all tasks for the user
@@ -1731,7 +1728,7 @@ async def rollback_onboarding(
1731
1728
  if filename:
1732
1729
  try:
1733
1730
  opensearch_client = session_manager.get_user_opensearch_client(
1734
- user.user_id, user.jwt_token
1731
+ user.user_id, jwt_token
1735
1732
  )
1736
1733
  from utils.opensearch_queries import build_filename_delete_body
1737
1734
  from config.settings import get_index_name
@@ -1893,7 +1890,6 @@ async def update_docling_preset(
1893
1890
  async def refresh_openrag_docs(
1894
1891
  document_service=Depends(get_document_service),
1895
1892
  task_service=Depends(get_task_service),
1896
- models_service=Depends(get_models_service),
1897
1893
  langflow_file_service=Depends(get_langflow_file_service),
1898
1894
  session_manager=Depends(get_session_manager),
1899
1895
  user: User = Depends(get_current_user),
@@ -1904,7 +1900,6 @@ async def refresh_openrag_docs(
1904
1900
 
1905
1901
  refreshed = await refresh_default_openrag_docs(
1906
1902
  document_service=document_service,
1907
- models_service=models_service,
1908
1903
  task_service=task_service,
1909
1904
  langflow_file_service=langflow_file_service,
1910
1905
  session_manager=session_manager,
@@ -1,4 +1,3 @@
1
- from dependencies import get_models_service
2
1
  import os
3
2
  from typing import Optional
4
3
  from urllib.parse import urlparse
@@ -36,10 +35,15 @@ async def upload(
36
35
  try:
37
36
 
38
37
  from config.settings import is_no_auth_mode
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
38
+
39
+ if is_no_auth_mode():
40
+ owner_user_id = None
41
+ owner_name = None
42
+ owner_email = None
43
+ else:
44
+ owner_user_id = user.user_id
45
+ owner_name = user.name
46
+ owner_email = user.email
43
47
 
44
48
  result = await document_service.process_upload_file(
45
49
  file,
@@ -80,10 +84,15 @@ async def upload_path(
80
84
  jwt_token = user.jwt_token
81
85
 
82
86
  from config.settings import is_no_auth_mode
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
87
+
88
+ if is_no_auth_mode():
89
+ owner_user_id = None
90
+ owner_name = None
91
+ owner_email = None
92
+ else:
93
+ owner_user_id = user.user_id
94
+ owner_name = user.name
95
+ owner_email = user.email
87
96
 
88
97
  from api.documents import _ensure_index_exists
89
98
  await _ensure_index_exists()
@@ -154,7 +163,6 @@ async def upload_options(
154
163
  async def upload_bucket(
155
164
  body: UploadBucketBody,
156
165
  task_service=Depends(get_task_service),
157
- models_service=Depends(get_models_service),
158
166
  session_manager=Depends(get_session_manager),
159
167
  user: User = Depends(get_current_user),
160
168
  ):
@@ -186,13 +194,18 @@ async def upload_bucket(
186
194
  jwt_token = user.jwt_token
187
195
 
188
196
  from models.processors import S3FileProcessor
189
-
190
197
  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
198
+
199
+ if is_no_auth_mode():
200
+ owner_user_id = None
201
+ owner_name = None
202
+ owner_email = None
203
+ task_user_id = None
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
196
209
 
197
210
  from api.documents import _ensure_index_exists
198
211
  await _ensure_index_exists()
@@ -200,7 +213,6 @@ async def upload_bucket(
200
213
  processor = S3FileProcessor(
201
214
  task_service.document_service,
202
215
  bucket,
203
- models_service=models_service,
204
216
  s3_client=s3_client,
205
217
  owner_user_id=owner_user_id,
206
218
  jwt_token=jwt_token,
@@ -31,6 +31,8 @@ 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"
34
36
 
35
37
  ANTHROPIC_DEFAULT_LANGUAGE_MODEL = "claude-sonnet-4-5-20250929"
36
38
 
@@ -1,16 +1,12 @@
1
1
  import asyncio
2
2
  import os
3
- import threading
4
- import concurrent.futures
5
3
  from utils.env_utils import get_env_int, get_env_float
6
4
 
7
5
  import httpx
8
- from agentd.patch import patch_openai_with_mcp
9
6
  from dotenv import load_dotenv
10
7
  from openai import AsyncOpenAI
11
8
  from opensearchpy import AsyncOpenSearch
12
9
  from opensearchpy._async.http_aiohttp import AIOHttpConnection
13
- from config.embedding_constants import OPENAI_DEFAULT_EMBEDDING_MODEL
14
10
 
15
11
  from utils.container_utils import get_container_host
16
12
  from utils.logging_config import get_logger
@@ -110,6 +106,26 @@ WEBHOOK_BASE_URL = os.getenv(
110
106
  VECTOR_DIM = 1536
111
107
  KNN_EF_CONSTRUCTION = 100
112
108
  KNN_M = 16
109
+ EMBED_MODEL = "text-embedding-3-small"
110
+
111
+ OPENAI_EMBEDDING_DIMENSIONS = {
112
+ "text-embedding-3-small": 1536,
113
+ "text-embedding-3-large": 3072,
114
+ "text-embedding-ada-002": 1536,
115
+ }
116
+
117
+ WATSONX_EMBEDDING_DIMENSIONS = {
118
+ # IBM Models
119
+ "ibm/granite-embedding-107m-multilingual": 384,
120
+ "ibm/granite-embedding-278m-multilingual": 1024,
121
+ "ibm/slate-125m-english-rtrvr": 768,
122
+ "ibm/slate-125m-english-rtrvr-v2": 768,
123
+ "ibm/slate-30m-english-rtrvr": 384,
124
+ "ibm/slate-30m-english-rtrvr-v2": 384,
125
+ # Third Party Models
126
+ "intfloat/multilingual-e5-large": 1024,
127
+ "sentence-transformers/all-minilm-l6-v2": 384,
128
+ }
113
129
 
114
130
  INDEX_BODY = {
115
131
  "settings": {
@@ -303,7 +319,7 @@ class AppClients:
303
319
  self.langflow_client = None
304
320
  self.langflow_http_client = None
305
321
  self._patched_async_client = None # Private attribute - single client for all providers
306
- self._client_init_lock = threading.Lock() # Lock for thread-safe initialization
322
+ self._client_init_lock = __import__('threading').Lock() # Lock for thread-safe initialization
307
323
  self.docling_http_client = None
308
324
 
309
325
  async def initialize(self):
@@ -438,11 +454,6 @@ class AppClients:
438
454
  if config.providers.openai.api_key:
439
455
  os.environ["OPENAI_API_KEY"] = config.providers.openai.api_key
440
456
  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")
446
457
 
447
458
  # Set Anthropic credentials
448
459
  if config.providers.anthropic.api_key:
@@ -466,23 +477,14 @@ class AppClients:
466
477
  os.environ["OLLAMA_ENDPOINT"] = config.providers.ollama.endpoint
467
478
  logger.debug("Loaded Ollama endpoint from config")
468
479
 
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"
472
480
  except Exception as e:
473
481
  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
482
 
484
- # API key for AsyncOpenAI constructor
485
- api_key = os.environ.get("OPENAI_API_KEY")
483
+ # Try to initialize the client - AsyncOpenAI() will read from environment
484
+ # We'll try HTTP/2 first with a probe, then fall back to HTTP/1.1 if it times out
485
+ import asyncio
486
+ import concurrent.futures
487
+ import threading
486
488
 
487
489
  async def probe_http2():
488
490
  """Returns True if HTTP/2 works, False to fall back to HTTP/1.1.
@@ -492,21 +494,20 @@ class AppClients:
492
494
  production client is created after this thread exits, in the
493
495
  caller's event loop, avoiding cross-loop SSL transport errors.
494
496
  """
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}...")
497
+ client = AsyncOpenAI()
498
+ logger.info("Probing OpenAI client with HTTP/2...")
498
499
  try:
499
500
  await asyncio.wait_for(
500
501
  client.embeddings.create(
501
- model=model_name,
502
+ model='text-embedding-3-small',
502
503
  input=['test']
503
504
  ),
504
505
  timeout=5.0
505
506
  )
506
- logger.info(f"HTTP/2 probe successful with {model_name}")
507
+ logger.info("HTTP/2 probe successful")
507
508
  return True
508
509
  except (asyncio.TimeoutError, Exception) as probe_error:
509
- logger.warning(f"HTTP/2 probe failed with {model_name}, falling back to HTTP/1.1", error=str(probe_error))
510
+ logger.warning("HTTP/2 probe failed, falling back to HTTP/1.1", error=str(probe_error))
510
511
  return False
511
512
  finally:
512
513
  # Always close the probe client so its connections are fully
@@ -526,32 +527,24 @@ class AppClients:
526
527
  loop.close()
527
528
 
528
529
  try:
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}")
530
+ # Run the probe in a separate thread with its own event loop.
531
+ # Only the probe result (bool) crosses the thread boundary;
532
+ # the production client is created here so its connections are
533
+ # bound to the caller's event loop, not the (now closed) probe loop.
534
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
535
+ future = executor.submit(run_probe_in_thread)
536
+ use_http2 = future.result(timeout=15)
542
537
 
543
538
  if use_http2:
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})")
539
+ self._patched_async_client = AsyncOpenAI()
540
+ logger.info("OpenAI client initialized with HTTP/2")
546
541
  else:
547
542
  http_client = httpx.AsyncClient(
548
543
  http2=False,
549
544
  timeout=httpx.Timeout(60.0, connect=10.0)
550
545
  )
551
- self._patched_async_client = patch_openai_with_mcp(
552
- AsyncOpenAI(api_key=api_key, http_client=http_client)
553
- )
554
- logger.info(f"OpenAI-compatible client initialized with HTTP/1.1 fallback (model: {model_name})")
546
+ self._patched_async_client = AsyncOpenAI(http_client=http_client)
547
+ logger.info("OpenAI client initialized with HTTP/1.1 (fallback)")
555
548
  logger.info("Successfully initialized OpenAI client")
556
549
  except Exception as e:
557
550
  logger.error(f"Failed to initialize OpenAI client: {e.__class__.__name__}: {str(e)}")
@@ -868,7 +861,7 @@ def get_openrag_config():
868
861
  # Expose configuration settings for backward compatibility and easy access
869
862
  def get_provider_config():
870
863
  """Get provider configuration."""
871
- return get_openrag_config().providers
864
+ return get_openrag_config().provider
872
865
 
873
866
 
874
867
  def get_knowledge_config():
@@ -883,7 +876,7 @@ def get_agent_config():
883
876
 
884
877
  def get_embedding_model() -> str:
885
878
  """Return the currently configured embedding model."""
886
- return get_openrag_config().knowledge.embedding_model or (OPENAI_DEFAULT_EMBEDDING_MODEL if DISABLE_INGEST_WITH_LANGFLOW else "")
879
+ return get_openrag_config().knowledge.embedding_model or EMBED_MODEL if DISABLE_INGEST_WITH_LANGFLOW else ""
887
880
 
888
881
 
889
882
  def get_index_name() -> str:
@@ -20,8 +20,6 @@ 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,
25
23
  ):
26
24
  self.clients = patched_async_client
27
25
  self.embed_model = embed_model
@@ -29,8 +27,6 @@ class ConnectorService:
29
27
  self.task_service = task_service
30
28
  self.session_manager = session_manager
31
29
  self.connection_manager = ConnectionManager()
32
- self.models_service = models_service
33
- self.document_service = document_service
34
30
 
35
31
  async def initialize(self):
36
32
  """Initialize the service by loading existing connections"""
@@ -61,12 +57,18 @@ class ConnectorService:
61
57
  with open(tmp_path, "wb") as f:
62
58
  f.write(document.content)
63
59
 
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
+
64
66
  logger.debug("Processing connector document", document_id=document.id)
65
67
 
66
68
  # Process using consolidated processing pipeline
67
69
  from models.processors import TaskProcessor
68
70
 
69
- processor = TaskProcessor(document_service=self.document_service, models_service=self.models_service)
71
+ processor = TaskProcessor(document_service=doc_service)
70
72
  result = await processor.process_document_standard(
71
73
  file_path=tmp_path,
72
74
  file_hash=document.id, # Use connector document ID as hash
@@ -282,7 +284,6 @@ class ConnectorService:
282
284
  if self.task_service and self.task_service.document_service
283
285
  else DocumentService(session_manager=self.session_manager)
284
286
  ),
285
- models_service=self.models_service,
286
287
  )
287
288
 
288
289
  # Use file IDs as items (no more fake file paths!)
@@ -414,7 +415,6 @@ class ConnectorService:
414
415
  if self.task_service and self.task_service.document_service
415
416
  else DocumentService(session_manager=self.session_manager)
416
417
  ),
417
- models_service=self.models_service,
418
418
  )
419
419
 
420
420
  # Create custom task using TaskService