cwyodmodules 0.3.31__tar.gz → 0.3.33__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 (132) hide show
  1. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/PKG-INFO +2 -1
  2. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/api/chat_history.py +14 -7
  3. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/chat_history/auth_utils.py +7 -3
  4. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/chat_history/cosmosdb.py +17 -1
  5. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/chat_history/postgresdbservice.py +291 -0
  6. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/common/source_document.py +60 -61
  7. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/fixed_size_overlap.py +8 -3
  8. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/layout.py +8 -3
  9. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/page.py +8 -3
  10. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/document_loading/read.py +44 -0
  11. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_computer_vision_client.py +10 -3
  12. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_form_recognizer_helper.py +6 -2
  13. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_identity_helper.py +3 -34
  14. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_postgres_helper.py +14 -2
  15. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_postgres_helper_light_rag.py +14 -2
  16. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_search_helper.py +15 -6
  17. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/config_helper.py +24 -2
  18. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/env_helper.py +9 -9
  19. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/lightrag_helper.py +9 -2
  20. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/llm_helper.py +13 -2
  21. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/secret_helper.py +9 -9
  22. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/integrated_vectorization/azure_search_index.py +8 -2
  23. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/integrated_vectorization/azure_search_indexer.py +9 -2
  24. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/integrated_vectorization/azure_search_skillset.py +6 -2
  25. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/lang_chain_agent.py +8 -2
  26. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/open_ai_functions.py +6 -2
  27. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/orchestrator_base.py +9 -3
  28. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/prompt_flow.py +8 -2
  29. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/orchestrator/semantic_kernel_orchestrator.py +196 -0
  30. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/parser/output_parser_tool.py +151 -0
  31. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/plugins/outlook_calendar_plugin.py +119 -0
  32. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/search/azure_search_handler.py +16 -3
  33. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/search/azure_search_handler_light_rag.py +14 -2
  34. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/search/integrated_vectorization_search_handler.py +36 -24
  35. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/search/lightrag_search_handler.py +14 -2
  36. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/search/postgres_search_handler.py +142 -0
  37. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/search/postgres_search_handler_light_rag.py +146 -0
  38. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/search/search.py +21 -24
  39. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/tools/content_safety_checker.py +91 -0
  40. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/tools/post_prompt_tool.py +64 -0
  41. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/tools/question_answer_tool.py +333 -0
  42. cwyodmodules-0.3.33/cwyodmodules/batch/utilities/tools/text_processing_tool.py +50 -0
  43. cwyodmodules-0.3.33/cwyodmodules/logging_config.py +15 -0
  44. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules.egg-info/PKG-INFO +2 -1
  45. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules.egg-info/SOURCES.txt +1 -0
  46. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules.egg-info/requires.txt +1 -0
  47. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/pyproject.toml +3 -2
  48. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/chat_history/postgresdbservice.py +0 -306
  49. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/document_loading/read.py +0 -48
  50. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/orchestrator/semantic_kernel_orchestrator.py +0 -199
  51. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/parser/output_parser_tool.py +0 -151
  52. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/plugins/outlook_calendar_plugin.py +0 -121
  53. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/search/postgres_search_handler.py +0 -139
  54. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/search/postgres_search_handler_light_rag.py +0 -147
  55. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/tools/content_safety_checker.py +0 -103
  56. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/tools/post_prompt_tool.py +0 -76
  57. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/tools/question_answer_tool.py +0 -343
  58. cwyodmodules-0.3.31/cwyodmodules/batch/utilities/tools/text_processing_tool.py +0 -53
  59. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/LICENSE +0 -0
  60. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/README.md +0 -0
  61. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/api/__init__.py +0 -0
  62. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/__init__.py +0 -0
  63. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/__init__.py +0 -0
  64. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/chat_history/database_client_base.py +0 -0
  65. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/chat_history/database_factory.py +0 -0
  66. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/chat_history/sample_user.py +0 -0
  67. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/common/__init__.py +0 -0
  68. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/common/answer.py +0 -0
  69. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/__init__.py +0 -0
  70. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/chunking_strategy.py +0 -0
  71. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/document_chunking_base.py +0 -0
  72. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/paragraph.py +0 -0
  73. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_chunking/strategies.py +0 -0
  74. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_loading/__init__.py +0 -0
  75. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_loading/document_loading_base.py +0 -0
  76. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_loading/layout.py +0 -0
  77. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_loading/strategies.py +0 -0
  78. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_loading/web.py +0 -0
  79. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/document_loading/word_document.py +0 -0
  80. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/__init__.py +0 -0
  81. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/azure_blob_storage_client.py +0 -0
  82. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/assistant_strategy.py +0 -0
  83. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/conversation_flow.py +0 -0
  84. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/database_type.py +0 -0
  85. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/default.json +0 -0
  86. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/default_contract_assistant_prompt.txt +0 -0
  87. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/default_employee_assistant_prompt.txt +0 -0
  88. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/config/embedding_config.py +0 -0
  89. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/document_chunking_helper.py +0 -0
  90. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/document_loading_helper.py +0 -0
  91. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/embedders/embedder_base.py +0 -0
  92. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/embedders/embedder_factory.py +0 -0
  93. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/embedders/integrated_vectorization_embedder.py +0 -0
  94. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/embedders/postgres_embedder.py +0 -0
  95. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/embedders/push_embedder.py +0 -0
  96. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/helpers/orchestrator_helper.py +0 -0
  97. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/integrated_vectorization/azure_search_datasource.py +0 -0
  98. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/loggers/conversation_logger.py +0 -0
  99. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/__init__.py +0 -0
  100. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/orchestration_strategy.py +0 -0
  101. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/orchestrator/strategies.py +0 -0
  102. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/parser/__init__.py +0 -0
  103. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/parser/parser_base.py +0 -0
  104. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/plugins/chat_plugin.py +0 -0
  105. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/plugins/post_answering_plugin.py +0 -0
  106. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/search/search_handler_base.py +0 -0
  107. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/tools/__init__.py +0 -0
  108. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/tools/answer_processing_base.py +0 -0
  109. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/batch/utilities/tools/answering_tool_base.py +0 -0
  110. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/__init__.py +0 -0
  111. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/config.py +0 -0
  112. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/database/__init__.py +0 -0
  113. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/database/base.py +0 -0
  114. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/database/models.py +0 -0
  115. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/indexing/__init__.py +0 -0
  116. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/indexing/chunking.py +0 -0
  117. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/indexing/extraction.py +0 -0
  118. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/indexing/types.py +0 -0
  119. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/indexing/upsert.py +0 -0
  120. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/indexing/utils.py +0 -0
  121. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/llm/__init__.py +0 -0
  122. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/llm/llm.py +0 -0
  123. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/llm/prompt.py +0 -0
  124. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/main.py +0 -0
  125. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/query/__init__.py +0 -0
  126. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/query/generate.py +0 -0
  127. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/query/graph_search.py +0 -0
  128. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/query/types.py +0 -0
  129. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules/graphrag/query/vector_search.py +0 -0
  130. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules.egg-info/dependency_links.txt +0 -0
  131. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/cwyodmodules.egg-info/top_level.txt +0 -0
  132. {cwyodmodules-0.3.31 → cwyodmodules-0.3.33}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cwyodmodules
3
- Version: 0.3.31
3
+ Version: 0.3.33
4
4
  Summary: Add your description here
5
5
  Author-email: Patrik <patrikhartl@gmail.com>
6
6
  Classifier: Operating System :: OS Independent
@@ -40,6 +40,7 @@ Requires-Dist: azure-search-documents==11.6.0b4
40
40
  Requires-Dist: semantic-kernel==1.3.0
41
41
  Requires-Dist: pydantic==2.7.4
42
42
  Requires-Dist: pandas>=2.2.3
43
+ Requires-Dist: azpaddypy>=0.2.4
43
44
  Dynamic: license-file
44
45
 
45
46
  # paddypy
@@ -1,5 +1,4 @@
1
1
  import os
2
- import logging
3
2
  from uuid import uuid4
4
3
 
5
4
  # from dotenv import load_dotenv
@@ -11,15 +10,16 @@ from ..batch.utilities.chat_history.auth_utils import (
11
10
  from ..batch.utilities.helpers.config.config_helper import ConfigHelper
12
11
  from ..batch.utilities.helpers.env_helper import EnvHelper
13
12
  from ..batch.utilities.chat_history.database_factory import DatabaseFactory
14
-
13
+ from logging_config import logger
15
14
  # load_dotenv()
15
+
16
16
  bp_chat_history_response = Blueprint("chat_history", __name__)
17
- logger = logging.getLogger("__main__")
18
- logger.setLevel(level=os.environ.get("LOGLEVEL", "INFO").upper())
19
17
 
20
18
  env_helper: EnvHelper = EnvHelper()
19
+ log_args = env_helper.LOG_ARGS
20
+ log_result = env_helper.LOG_RESULT
21
21
 
22
-
22
+ @logger.trace_function(log_args=log_args, log_result=log_result)
23
23
  def init_database_client():
24
24
  try:
25
25
  conversation_client = DatabaseFactory.get_conversation_client()
@@ -28,7 +28,7 @@ def init_database_client():
28
28
  logger.exception("Exception in database initialization: %s", e)
29
29
  raise e
30
30
 
31
-
31
+ @logger.trace_function(log_args=log_args, log_result=log_result)
32
32
  def init_openai_client():
33
33
  try:
34
34
  if env_helper.is_auth_type_keys():
@@ -45,11 +45,12 @@ def init_openai_client():
45
45
  )
46
46
  return azure_openai_client
47
47
  except Exception as e:
48
- logging.exception("Exception in Azure OpenAI initialization: %s", e)
48
+ logger.exception("Exception in Azure OpenAI initialization: %s", e)
49
49
  raise e
50
50
 
51
51
 
52
52
  @bp_chat_history_response.route("/history/list", methods=["GET"])
53
+ @logger.trace_function(log_args=log_args, log_result=log_result)
53
54
  async def list_conversations():
54
55
  config = ConfigHelper.get_active_config_or_default()
55
56
  if not config.enable_chat_history:
@@ -89,6 +90,7 @@ async def list_conversations():
89
90
 
90
91
 
91
92
  @bp_chat_history_response.route("/history/rename", methods=["POST"])
93
+ @logger.trace_function(log_args=log_args, log_result=log_result)
92
94
  async def rename_conversation():
93
95
  config = ConfigHelper.get_active_config_or_default()
94
96
  if not config.enable_chat_history:
@@ -151,6 +153,7 @@ async def rename_conversation():
151
153
 
152
154
 
153
155
  @bp_chat_history_response.route("/history/read", methods=["POST"])
156
+ @logger.trace_function(log_args=log_args, log_result=log_result)
154
157
  async def get_conversation():
155
158
  config = ConfigHelper.get_active_config_or_default()
156
159
  if not config.enable_chat_history:
@@ -223,6 +226,7 @@ async def get_conversation():
223
226
 
224
227
 
225
228
  @bp_chat_history_response.route("/history/delete", methods=["DELETE"])
229
+ @logger.trace_function(log_args=log_args, log_result=log_result)
226
230
  async def delete_conversation():
227
231
  config = ConfigHelper.get_active_config_or_default()
228
232
  if not config.enable_chat_history:
@@ -283,6 +287,7 @@ async def delete_conversation():
283
287
 
284
288
 
285
289
  @bp_chat_history_response.route("/history/delete_all", methods=["DELETE"])
290
+ @logger.trace_function(log_args=log_args, log_result=log_result)
286
291
  async def delete_all_conversations():
287
292
  config = ConfigHelper.get_active_config_or_default()
288
293
 
@@ -354,6 +359,7 @@ async def delete_all_conversations():
354
359
 
355
360
 
356
361
  @bp_chat_history_response.route("/history/update", methods=["POST"])
362
+ @logger.trace_function(log_args=log_args, log_result=log_result)
357
363
  async def update_conversation():
358
364
  config = ConfigHelper.get_active_config_or_default()
359
365
  if not config.enable_chat_history:
@@ -455,6 +461,7 @@ async def update_conversation():
455
461
 
456
462
 
457
463
  @bp_chat_history_response.route("/history/frontend_settings", methods=["GET"])
464
+ @logger.trace_function(log_args=log_args, log_result=log_result)
458
465
  def get_frontend_settings():
459
466
  try:
460
467
  # Clear the cache for the config helper method
@@ -1,8 +1,13 @@
1
1
  import base64
2
2
  import json
3
- import logging
4
3
 
4
+ from ...utilities.helpers.env_helper import EnvHelper
5
+ from logging_config import logger
6
+ env_helper: EnvHelper = EnvHelper()
7
+ log_args = env_helper.LOG_ARGS
8
+ log_result = env_helper.LOG_RESULT
5
9
 
10
+ @logger.trace_function(log_args=log_args, log_result=log_result)
6
11
  def get_authenticated_user_details(request_headers):
7
12
  user_object = {}
8
13
 
@@ -25,9 +30,8 @@ def get_authenticated_user_details(request_headers):
25
30
 
26
31
  return user_object
27
32
 
28
-
33
+ @logger.trace_function(log_args=log_args, log_result=log_result)
29
34
  def get_tenantid(client_principal_b64):
30
- logger = logging.getLogger("__main__")
31
35
  tenant_id = ""
32
36
  if client_principal_b64:
33
37
  try:
@@ -3,7 +3,11 @@ from azure.cosmos.aio import CosmosClient
3
3
  from azure.cosmos import exceptions
4
4
 
5
5
  from .database_client_base import DatabaseClientBase
6
-
6
+ from ...utilities.helpers.env_helper import EnvHelper
7
+ from logging_config import logger
8
+ env_helper: EnvHelper = EnvHelper()
9
+ log_args = env_helper.LOG_ARGS
10
+ log_result = env_helper.LOG_RESULT
7
11
 
8
12
  class CosmosConversationClient(DatabaseClientBase):
9
13
 
@@ -44,12 +48,15 @@ class CosmosConversationClient(DatabaseClientBase):
44
48
  except exceptions.CosmosResourceNotFoundError:
45
49
  raise ValueError("Invalid CosmosDB container name")
46
50
 
51
+ @logger.trace_function(log_args=log_args, log_result=log_result)
47
52
  async def connect(self):
48
53
  pass
49
54
 
55
+ @logger.trace_function(log_args=log_args, log_result=log_result)
50
56
  async def close(self):
51
57
  pass
52
58
 
59
+ @logger.trace_function(log_args=log_args, log_result=log_result)
53
60
  async def ensure(self):
54
61
  if (
55
62
  not self.cosmosdb_client
@@ -72,6 +79,7 @@ class CosmosConversationClient(DatabaseClientBase):
72
79
 
73
80
  return True, "CosmosDB client initialized successfully"
74
81
 
82
+ @logger.trace_function(log_args=log_args, log_result=log_result)
75
83
  async def create_conversation(self, user_id, conversation_id, title=""):
76
84
  conversation = {
77
85
  "id": conversation_id,
@@ -89,6 +97,7 @@ class CosmosConversationClient(DatabaseClientBase):
89
97
  else:
90
98
  return False
91
99
 
100
+ @logger.trace_function(log_args=log_args, log_result=log_result)
92
101
  async def upsert_conversation(self, conversation):
93
102
  resp = await self.container_client.upsert_item(conversation)
94
103
  if resp:
@@ -96,6 +105,7 @@ class CosmosConversationClient(DatabaseClientBase):
96
105
  else:
97
106
  return False
98
107
 
108
+ @logger.trace_function(log_args=log_args, log_result=log_result)
99
109
  async def delete_conversation(self, user_id, conversation_id):
100
110
  conversation = await self.container_client.read_item(
101
111
  item=conversation_id, partition_key=user_id
@@ -108,6 +118,7 @@ class CosmosConversationClient(DatabaseClientBase):
108
118
  else:
109
119
  return True
110
120
 
121
+ @logger.trace_function(log_args=log_args, log_result=log_result)
111
122
  async def delete_messages(self, conversation_id, user_id):
112
123
  # get a list of all the messages in the conversation
113
124
  messages = await self.get_messages(user_id, conversation_id)
@@ -120,6 +131,7 @@ class CosmosConversationClient(DatabaseClientBase):
120
131
  response_list.append(resp)
121
132
  return response_list
122
133
 
134
+ @logger.trace_function(log_args=log_args, log_result=log_result)
123
135
  async def get_conversations(self, user_id, limit, sort_order="DESC", offset=0):
124
136
  parameters = [{"name": "@userId", "value": user_id}]
125
137
  query = f"SELECT * FROM c where c.userId = @userId and c.type='conversation' order by c.updatedAt {sort_order}"
@@ -134,6 +146,7 @@ class CosmosConversationClient(DatabaseClientBase):
134
146
 
135
147
  return conversations
136
148
 
149
+ @logger.trace_function(log_args=log_args, log_result=log_result)
137
150
  async def get_conversation(self, user_id, conversation_id):
138
151
  parameters = [
139
152
  {"name": "@conversationId", "value": conversation_id},
@@ -152,6 +165,7 @@ class CosmosConversationClient(DatabaseClientBase):
152
165
  else:
153
166
  return conversations[0]
154
167
 
168
+ @logger.trace_function(log_args=log_args, log_result=log_result)
155
169
  async def create_message(self, uuid, conversation_id, user_id, input_message: dict):
156
170
  message = {
157
171
  "id": uuid,
@@ -179,6 +193,7 @@ class CosmosConversationClient(DatabaseClientBase):
179
193
  else:
180
194
  return False
181
195
 
196
+ @logger.trace_function(log_args=log_args, log_result=log_result)
182
197
  async def update_message_feedback(self, user_id, message_id, feedback):
183
198
  message = await self.container_client.read_item(
184
199
  item=message_id, partition_key=user_id
@@ -190,6 +205,7 @@ class CosmosConversationClient(DatabaseClientBase):
190
205
  else:
191
206
  return False
192
207
 
208
+ @logger.trace_function(log_args=log_args, log_result=log_result)
193
209
  async def get_messages(self, user_id, conversation_id):
194
210
  parameters = [
195
211
  {"name": "@conversationId", "value": conversation_id},
@@ -0,0 +1,291 @@
1
+ import asyncpg
2
+ from datetime import datetime, timezone
3
+ from ..helpers.azure_identity_helper import AzureIdentityHelper
4
+ from .database_client_base import DatabaseClientBase
5
+
6
+ from ...utilities.helpers.env_helper import EnvHelper
7
+ from logging_config import logger
8
+ env_helper: EnvHelper = EnvHelper()
9
+ log_args = env_helper.LOG_ARGS
10
+ log_result = env_helper.LOG_RESULT
11
+
12
+
13
+ class PostgresConversationClient(DatabaseClientBase):
14
+
15
+ def __init__(
16
+ self, user: str, host: str, database: str, enable_message_feedback: bool = False
17
+ ):
18
+ self.azure_identity_helper = AzureIdentityHelper()
19
+ self.user = user
20
+ self.host = host
21
+ self.database = database
22
+ self.enable_message_feedback = enable_message_feedback
23
+ self.conn = None
24
+
25
+ @logger.trace_function(log_args=log_args, log_result=log_result)
26
+ async def connect(self):
27
+ try:
28
+ access_information = self.azure_identity_helper.get_token(scopes="https://ossrdbms-aad.database.windows.net/.default")
29
+ token = access_information.token
30
+ self.conn = await asyncpg.connect(
31
+ user=self.user,
32
+ host=self.host,
33
+ database=self.database,
34
+ password=token,
35
+ port=5432,
36
+ ssl="require",
37
+ )
38
+ logger.info("Successfully connected to PostgreSQL")
39
+ except Exception as e:
40
+ logger.error("Failed to connect to PostgreSQL: %s", e, exc_info=True)
41
+ raise
42
+
43
+ @logger.trace_function(log_args=log_args, log_result=log_result)
44
+ async def close(self):
45
+ if self.conn:
46
+ await self.conn.close()
47
+ logger.info("PostgreSQL connection closed")
48
+
49
+ @logger.trace_function(log_args=log_args, log_result=log_result)
50
+ async def ensure(self):
51
+ if not self.conn:
52
+ logger.warning("PostgreSQL client not initialized correctly")
53
+ return False, "PostgreSQL client not initialized correctly"
54
+ logger.info("PostgreSQL client initialized successfully")
55
+ return True, "PostgreSQL client initialized successfully"
56
+
57
+ @logger.trace_function(log_args=log_args, log_result=log_result)
58
+ async def create_conversation(self, conversation_id, user_id, title=""):
59
+ utc_now = datetime.now(timezone.utc)
60
+ createdAt = utc_now.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
61
+ query = """
62
+ INSERT INTO conversations (id, conversation_id, type, "createdAt", "updatedAt", user_id, title)
63
+ VALUES ($1, $2, 'conversation', $3, $3, $4, $5)
64
+ RETURNING *
65
+ """
66
+ try:
67
+ conversation = await self.conn.fetchrow(
68
+ query, conversation_id, conversation_id, createdAt, user_id, title
69
+ )
70
+ if conversation:
71
+ logger.info(f"Conversation created with id: {conversation_id}")
72
+ return dict(conversation)
73
+ else:
74
+ logger.warning(
75
+ f"Failed to create conversation with id: {conversation_id}"
76
+ )
77
+ return False
78
+ except Exception as e:
79
+ logger.error(
80
+ f"Error creating conversation with id: {conversation_id}: {e}",
81
+ exc_info=True,
82
+ )
83
+ raise
84
+
85
+ @logger.trace_function(log_args=log_args, log_result=log_result)
86
+ async def upsert_conversation(self, conversation):
87
+ query = """
88
+ INSERT INTO conversations (id, conversation_id, type, "createdAt", "updatedAt", user_id, title)
89
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
90
+ ON CONFLICT (id) DO UPDATE SET
91
+ "updatedAt" = EXCLUDED."updatedAt",
92
+ title = EXCLUDED.title
93
+ RETURNING *
94
+ """
95
+ try:
96
+ updated_conversation = await self.conn.fetchrow(
97
+ query,
98
+ conversation["id"],
99
+ conversation["conversation_id"],
100
+ conversation["type"],
101
+ conversation["createdAt"],
102
+ conversation["updatedAt"],
103
+ conversation["user_id"],
104
+ conversation["title"],
105
+ )
106
+ if updated_conversation:
107
+ logger.info(f"Conversation upserted with id: {conversation['id']}")
108
+ return dict(updated_conversation)
109
+ else:
110
+ logger.warning(
111
+ f"Failed to upsert conversation with id: {conversation['id']}"
112
+ )
113
+ return False
114
+ except Exception as e:
115
+ logger.error(
116
+ f"Error upserting conversation with id: {conversation['id']}: {e}",
117
+ exc_info=True,
118
+ )
119
+ raise
120
+
121
+ @logger.trace_function(log_args=log_args, log_result=log_result)
122
+ async def delete_conversation(self, user_id, conversation_id):
123
+ query = (
124
+ "DELETE FROM conversations WHERE conversation_id = $1 AND user_id = $2"
125
+ )
126
+ try:
127
+ await self.conn.execute(query, conversation_id, user_id)
128
+ logger.info(
129
+ f"Conversation deleted with conversation_id: {conversation_id} and user_id: {user_id}"
130
+ )
131
+ return True
132
+ except Exception as e:
133
+ logger.error(
134
+ f"Error deleting conversation with conversation_id: {conversation_id} and user_id: {user_id}: {e}",
135
+ exc_info=True,
136
+ )
137
+ raise
138
+
139
+ @logger.trace_function(log_args=log_args, log_result=log_result)
140
+ async def delete_messages(self, conversation_id, user_id):
141
+ query = "DELETE FROM messages WHERE conversation_id = $1 AND user_id = $2 RETURNING *"
142
+ try:
143
+ messages = await self.conn.fetch(query, conversation_id, user_id)
144
+ logger.info(
145
+ f"Messages deleted for conversation_id: {conversation_id} and user_id: {user_id}"
146
+ )
147
+ return [dict(message) for message in messages]
148
+ except Exception as e:
149
+ logger.error(
150
+ f"Error deleting messages for conversation_id: {conversation_id} and user_id: {user_id}: {e}",
151
+ exc_info=True,
152
+ )
153
+ raise
154
+
155
+ @logger.trace_function(log_args=log_args, log_result=log_result)
156
+ async def get_conversations(self, user_id, limit=None, sort_order="DESC", offset=0):
157
+ try:
158
+ offset = int(offset) # Ensure offset is an integer
159
+ except ValueError:
160
+ logger.error("Offset must be an integer.", exc_info=True)
161
+ raise ValueError("Offset must be an integer.")
162
+ # Base query without LIMIT and OFFSET
163
+ query = f"""
164
+ SELECT * FROM conversations
165
+ WHERE user_id = $1 AND type = 'conversation'
166
+ ORDER BY "updatedAt" {sort_order}
167
+ """
168
+ # Append LIMIT and OFFSET to the query if limit is specified
169
+ if limit is not None:
170
+ try:
171
+ limit = int(limit) # Ensure limit is an integer
172
+ query += " LIMIT $2 OFFSET $3"
173
+ # Fetch records with LIMIT and OFFSET
174
+ conversations = await self.conn.fetch(query, user_id, limit, offset)
175
+ logger.info(
176
+ f"Retrieved conversations for user_id: {user_id} with limit: {limit} and offset: {offset}"
177
+ )
178
+ except ValueError:
179
+ logger.error("Limit must be an integer.", exc_info=True)
180
+ raise ValueError("Limit must be an integer.")
181
+ else:
182
+ # Fetch records without LIMIT and OFFSET
183
+ conversations = await self.conn.fetch(query, user_id)
184
+ logger.info(
185
+ f"Retrieved conversations for user_id: {user_id} without limit and offset"
186
+ )
187
+ return [dict(conversation) for conversation in conversations]
188
+
189
+ @logger.trace_function(log_args=log_args, log_result=log_result)
190
+ async def get_conversation(self, user_id, conversation_id):
191
+ query = "SELECT * FROM conversations WHERE id = $1 AND user_id = $2 AND type = 'conversation'"
192
+ try:
193
+ conversation = await self.conn.fetchrow(query, conversation_id, user_id)
194
+ if conversation:
195
+ logger.info(
196
+ f"Retrieved conversation with id: {conversation_id} and user_id: {user_id}"
197
+ )
198
+ return dict(conversation)
199
+ else:
200
+ logger.warning(
201
+ f"No conversation found with id: {conversation_id} and user_id: {user_id}"
202
+ )
203
+ return None
204
+ except Exception as e:
205
+ logger.error(
206
+ f"Error retrieving conversation with id: {conversation_id} and user_id: {user_id}: {e}",
207
+ exc_info=True,
208
+ )
209
+ raise
210
+
211
+ @logger.trace_function(log_args=log_args, log_result=log_result)
212
+ async def create_message(self, uuid, conversation_id, user_id, input_message: dict):
213
+ message_id = uuid
214
+ utc_now = datetime.now(timezone.utc)
215
+ createdAt = utc_now.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
216
+ query = """
217
+ INSERT INTO messages (id, type, "createdAt", "updatedAt", user_id, conversation_id, role, content, feedback)
218
+ VALUES ($1, 'message', $2, $2, $3, $4, $5, $6, $7)
219
+ RETURNING *
220
+ """
221
+ feedback = "" if self.enable_message_feedback else None
222
+ try:
223
+ message = await self.conn.fetchrow(
224
+ query,
225
+ message_id,
226
+ createdAt,
227
+ user_id,
228
+ conversation_id,
229
+ input_message["role"],
230
+ input_message["content"],
231
+ feedback,
232
+ )
233
+
234
+ if message:
235
+ update_query = 'UPDATE conversations SET "updatedAt" = $1 WHERE id = $2 AND user_id = $3 RETURNING *'
236
+ await self.conn.execute(
237
+ update_query, createdAt, conversation_id, user_id
238
+ )
239
+ logger.info(
240
+ f"Message created with id: {message_id} in conversation: {conversation_id}"
241
+ )
242
+ return dict(message)
243
+ else:
244
+ logger.warning(
245
+ f"Failed to create message with id: {message_id} in conversation: {conversation_id}"
246
+ )
247
+ return False
248
+ except Exception as e:
249
+ logger.error(
250
+ f"Error creating message with id: {message_id} in conversation: {conversation_id}: {e}",
251
+ exc_info=True,
252
+ )
253
+ raise
254
+
255
+ @logger.trace_function(log_args=log_args, log_result=log_result)
256
+ async def update_message_feedback(self, user_id, message_id, feedback):
257
+ query = "UPDATE messages SET feedback = $1 WHERE id = $2 AND user_id = $3 RETURNING *"
258
+ try:
259
+ message = await self.conn.fetchrow(query, feedback, message_id, user_id)
260
+ if message:
261
+ logger.info(
262
+ f"Message feedback updated for message_id: {message_id} and user_id: {user_id}"
263
+ )
264
+ return dict(message)
265
+ else:
266
+ logger.warning(
267
+ f"Failed to update message feedback for message_id: {message_id} and user_id: {user_id}"
268
+ )
269
+ return False
270
+ except Exception as e:
271
+ logger.error(
272
+ f"Error updating message feedback for message_id: {message_id} and user_id: {user_id}: {e}",
273
+ exc_info=True,
274
+ )
275
+ raise
276
+
277
+ @logger.trace_function(log_args=log_args, log_result=log_result)
278
+ async def get_messages(self, user_id, conversation_id):
279
+ query = 'SELECT * FROM messages WHERE conversation_id = $1 AND user_id = $2 ORDER BY "createdAt" ASC'
280
+ try:
281
+ messages = await self.conn.fetch(query, conversation_id, user_id)
282
+ logger.info(
283
+ f"Retrieved messages for conversation_id: {conversation_id} and user_id: {user_id}"
284
+ )
285
+ return [dict(message) for message in messages]
286
+ except Exception as e:
287
+ logger.error(
288
+ f"Error retrieving messages for conversation_id: {conversation_id} and user_id: {user_id}: {e}",
289
+ exc_info=True,
290
+ )
291
+ raise