sunholo 0.88.4__tar.gz → 0.89.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. {sunholo-0.88.4 → sunholo-0.89.2}/PKG-INFO +2 -2
  2. {sunholo-0.88.4 → sunholo-0.89.2}/setup.py +1 -1
  3. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/dispatch_to_qa.py +18 -0
  4. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/flask/vac_routes.py +11 -8
  5. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/cli_init.py +1 -1
  6. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/genai/process_funcs_cls.py +19 -8
  7. sunholo-0.89.2/sunholo/langfuse/evals.py +83 -0
  8. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/terraform/tfvars_editor.py +19 -4
  9. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo.egg-info/PKG-INFO +2 -2
  10. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo.egg-info/SOURCES.txt +1 -0
  11. {sunholo-0.88.4 → sunholo-0.89.2}/LICENSE.txt +0 -0
  12. {sunholo-0.88.4 → sunholo-0.89.2}/MANIFEST.in +0 -0
  13. {sunholo-0.88.4 → sunholo-0.89.2}/README.md +0 -0
  14. {sunholo-0.88.4 → sunholo-0.89.2}/setup.cfg +0 -0
  15. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/__init__.py +0 -0
  16. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/__init__.py +0 -0
  17. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/chat_history.py +0 -0
  18. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/fastapi/__init__.py +0 -0
  19. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/fastapi/base.py +0 -0
  20. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/fastapi/qna_routes.py +0 -0
  21. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/flask/__init__.py +0 -0
  22. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/flask/base.py +0 -0
  23. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/flask/qna_routes.py +0 -0
  24. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/langserve.py +0 -0
  25. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/pubsub.py +0 -0
  26. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/route.py +0 -0
  27. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/special_commands.py +0 -0
  28. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/agents/swagger.py +0 -0
  29. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/archive/__init__.py +0 -0
  30. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/archive/archive.py +0 -0
  31. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/auth/__init__.py +0 -0
  32. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/auth/gcloud.py +0 -0
  33. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/auth/refresh.py +0 -0
  34. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/auth/run.py +0 -0
  35. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/azure/__init__.py +0 -0
  36. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/azure/auth.py +0 -0
  37. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/azure/blobs.py +0 -0
  38. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/azure/event_grid.py +0 -0
  39. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/bots/__init__.py +0 -0
  40. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/bots/discord.py +0 -0
  41. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/bots/github_webhook.py +0 -0
  42. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/bots/webapp.py +0 -0
  43. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/__init__.py +0 -0
  44. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/azure.py +0 -0
  45. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/doc_handling.py +0 -0
  46. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/encode_metadata.py +0 -0
  47. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/images.py +0 -0
  48. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/loaders.py +0 -0
  49. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/message_data.py +0 -0
  50. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/pdfs.py +0 -0
  51. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/process_chunker_data.py +0 -0
  52. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/publish.py +0 -0
  53. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/pubsub.py +0 -0
  54. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/chunker/splitter.py +0 -0
  55. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/__init__.py +0 -0
  56. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/chat_vac.py +0 -0
  57. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/cli.py +0 -0
  58. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/configs.py +0 -0
  59. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/deploy.py +0 -0
  60. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/embedder.py +0 -0
  61. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/merge_texts.py +0 -0
  62. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/run_proxy.py +0 -0
  63. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/sun_rich.py +0 -0
  64. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/swagger.py +0 -0
  65. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/cli/vertex.py +0 -0
  66. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/components/__init__.py +0 -0
  67. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/components/llm.py +0 -0
  68. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/components/retriever.py +0 -0
  69. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/components/vectorstore.py +0 -0
  70. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/custom_logging.py +0 -0
  71. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/__init__.py +0 -0
  72. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/alloydb.py +0 -0
  73. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/alloydb_client.py +0 -0
  74. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/database.py +0 -0
  75. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/lancedb.py +0 -0
  76. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/sql/sb/create_function.sql +0 -0
  77. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/sql/sb/create_function_time.sql +0 -0
  78. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/sql/sb/create_table.sql +0 -0
  79. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  80. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/sql/sb/return_sources.sql +0 -0
  81. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/sql/sb/setup.sql +0 -0
  82. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/static_dbs.py +0 -0
  83. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/database/uuid.py +0 -0
  84. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/discovery_engine/__init__.py +0 -0
  85. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/discovery_engine/chunker_handler.py +0 -0
  86. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/discovery_engine/create_new.py +0 -0
  87. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  88. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  89. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/embedder/__init__.py +0 -0
  90. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/embedder/embed_chunk.py +0 -0
  91. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/excel/__init__.py +0 -0
  92. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/excel/plugin.py +0 -0
  93. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/gcs/__init__.py +0 -0
  94. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/gcs/add_file.py +0 -0
  95. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/gcs/download_folder.py +0 -0
  96. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/gcs/download_url.py +0 -0
  97. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/gcs/metadata.py +0 -0
  98. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/genai/__init__.py +0 -0
  99. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/genai/init.py +0 -0
  100. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/genai/safety.py +0 -0
  101. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/invoke/__init__.py +0 -0
  102. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/invoke/async_class.py +0 -0
  103. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/invoke/direct_vac_func.py +0 -0
  104. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/invoke/invoke_vac_utils.py +0 -0
  105. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/langfuse/__init__.py +0 -0
  106. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/langfuse/callback.py +0 -0
  107. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/langfuse/prompts.py +0 -0
  108. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/llamaindex/__init__.py +0 -0
  109. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/llamaindex/get_files.py +0 -0
  110. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/llamaindex/import_files.py +0 -0
  111. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/llamaindex/llamaindex_class.py +0 -0
  112. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/llamaindex/user_history.py +0 -0
  113. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/lookup/__init__.py +0 -0
  114. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/lookup/model_lookup.yaml +0 -0
  115. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/patches/__init__.py +0 -0
  116. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/patches/langchain/__init__.py +0 -0
  117. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/patches/langchain/lancedb.py +0 -0
  118. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/patches/langchain/vertexai.py +0 -0
  119. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/pubsub/__init__.py +0 -0
  120. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/pubsub/process_pubsub.py +0 -0
  121. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/pubsub/pubsub_manager.py +0 -0
  122. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/qna/__init__.py +0 -0
  123. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/qna/parsers.py +0 -0
  124. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/qna/retry.py +0 -0
  125. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/streaming/__init__.py +0 -0
  126. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/streaming/content_buffer.py +0 -0
  127. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/streaming/langserve.py +0 -0
  128. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/streaming/stream_lookup.py +0 -0
  129. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/streaming/streaming.py +0 -0
  130. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/summarise/__init__.py +0 -0
  131. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/summarise/summarise.py +0 -0
  132. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/terraform/__init__.py +0 -0
  133. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/tools/__init__.py +0 -0
  134. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/tools/web_browser.py +0 -0
  135. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/__init__.py +0 -0
  136. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/api_key.py +0 -0
  137. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/big_context.py +0 -0
  138. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/config.py +0 -0
  139. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/config_class.py +0 -0
  140. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/config_schema.py +0 -0
  141. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/gcp.py +0 -0
  142. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/gcp_project.py +0 -0
  143. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/parsers.py +0 -0
  144. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/timedelta.py +0 -0
  145. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/user_ids.py +0 -0
  146. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/utils/version.py +0 -0
  147. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/__init__.py +0 -0
  148. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/extensions_call.py +0 -0
  149. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/extensions_class.py +0 -0
  150. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/genai_functions.py +0 -0
  151. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/init.py +0 -0
  152. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/memory_tools.py +0 -0
  153. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/safety.py +0 -0
  154. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo/vertex/type_dict_to_json.py +0 -0
  155. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo.egg-info/dependency_links.txt +0 -0
  156. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo.egg-info/entry_points.txt +0 -0
  157. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo.egg-info/requires.txt +0 -0
  158. {sunholo-0.88.4 → sunholo-0.89.2}/sunholo.egg-info/top_level.txt +0 -0
  159. {sunholo-0.88.4 → sunholo-0.89.2}/tests/test_chat_history.py +0 -0
  160. {sunholo-0.88.4 → sunholo-0.89.2}/tests/test_config.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.88.4
3
+ Version: 0.89.2
4
4
  Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
5
5
  Home-page: https://github.com/sunholo-data/sunholo-py
6
- Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.88.4.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.89.2.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -1,6 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- version = '0.88.4'
3
+ version = '0.89.2'
4
4
 
5
5
  setup(
6
6
  name='sunholo',
@@ -20,6 +20,12 @@ from .langserve import prepare_request_data
20
20
 
21
21
  from .route import route_endpoint
22
22
 
23
+ try:
24
+ from langfuse import Langfuse
25
+ langfuse = Langfuse()
26
+ except ImportError:
27
+ langfuse = None
28
+
23
29
  def prep_request_payload(user_input, chat_history, vector_name, stream, **kwargs):
24
30
  """
25
31
  Prepares the request payload for sending a query to the QA system.
@@ -79,9 +85,21 @@ def prep_request_payload(user_input, chat_history, vector_name, stream, **kwargs
79
85
 
80
86
  if 'vector_name' not in qna_data:
81
87
  qna_data['vector_name'] = vector_name
88
+
89
+ qna_data['trace_id'] = add_langfuse_trace(qna_endpoint)
82
90
 
83
91
  return qna_endpoint, qna_data
84
92
 
93
+ def add_langfuse_trace(qna_endpoint):
94
+ if not langfuse:
95
+ return None
96
+
97
+ trace = langfuse.trace(name = f'auto/{qna_endpoint}')
98
+
99
+ log.info('Adding langfuse trace {trace.id}')
100
+
101
+ return trace.id
102
+
85
103
  def send_to_qa(user_input, vector_name, chat_history, stream=False, **kwargs):
86
104
  """
87
105
  Sends a query to the QA system synchronously.
@@ -161,7 +161,7 @@ if __name__ == "__main__":
161
161
 
162
162
 
163
163
  def handle_stream_vac(self, vector_name):
164
- observed_stream_interpreter = observe()(self.stream_interpreter)
164
+ observed_stream_interpreter = self.stream_interpreter
165
165
  prep = self.prep_vac(request, vector_name)
166
166
  log.info(f"Processing prep: {prep}")
167
167
  trace = prep["trace"]
@@ -225,7 +225,7 @@ if __name__ == "__main__":
225
225
  return response
226
226
 
227
227
  def handle_process_vac(self, vector_name):
228
- observed_vac_interpreter = observe()(self.vac_interpreter)
228
+ observed_vac_interpreter = self.vac_interpreter
229
229
  prep = self.prep_vac(request, vector_name)
230
230
  log.debug(f"Processing prep: {prep}")
231
231
  trace = prep["trace"]
@@ -365,7 +365,7 @@ if __name__ == "__main__":
365
365
  "kwargs": data
366
366
  }
367
367
 
368
- observed_stream_interpreter = observe()(self.stream_interpreter)
368
+ observed_stream_interpreter = self.stream_interpreter
369
369
 
370
370
  response_id = str(uuid.uuid4())
371
371
 
@@ -416,7 +416,7 @@ if __name__ == "__main__":
416
416
  return Response(generate_response_content(), content_type='text/plain; charset=utf-8')
417
417
 
418
418
  try:
419
- observed_vac_interpreter = observe()(self.vac_interpreter)
419
+ observed_vac_interpreter = self.vac_interpreter
420
420
  bot_output = observed_vac_interpreter(
421
421
  question=user_message,
422
422
  vector_name=vector_name,
@@ -437,7 +437,7 @@ if __name__ == "__main__":
437
437
  return self.make_openai_response(user_message, vector_name, f'ERROR: {str(err)}')
438
438
 
439
439
 
440
- def create_langfuse_trace(self, request, vector_name):
440
+ def create_langfuse_trace(self, request, vector_name, trace_id):
441
441
  try:
442
442
  from langfuse import Langfuse
443
443
  langfuse = Langfuse()
@@ -451,11 +451,12 @@ if __name__ == "__main__":
451
451
  message_source = request.headers.get("X-Message-Source")
452
452
 
453
453
  package_version = sunholo_version()
454
- tags = [package_version]
454
+ tags = [package_version, "autogenerated"]
455
455
  if message_source:
456
456
  tags.append(message_source)
457
457
 
458
458
  return langfuse.trace(
459
+ id=trace_id,
459
460
  name = f"/vac/{vector_name}",
460
461
  user_id = user_id,
461
462
  session_id = session_id,
@@ -464,8 +465,6 @@ if __name__ == "__main__":
464
465
  )
465
466
 
466
467
  def prep_vac(self, request, vector_name):
467
- trace = self.create_langfuse_trace(request, vector_name)
468
- span = None
469
468
 
470
469
  if request.content_type.startswith('application/json'):
471
470
  data = request.get_json()
@@ -490,6 +489,10 @@ if __name__ == "__main__":
490
489
 
491
490
  log.info(f"vac/{vector_name} got data: {data}")
492
491
 
492
+ trace_id = data.get('trace_id')
493
+ trace = self.create_langfuse_trace(request, vector_name, trace_id)
494
+ span = None
495
+
493
496
  config, _ = load_config("config/llm_config.yaml")
494
497
  vac_configs = config.get("vac")
495
498
  if vac_configs:
@@ -201,7 +201,7 @@ def write_vac_config(project_dir: str, service_name: str):
201
201
  with open(vac_config_path, 'w') as file:
202
202
  yaml.dump(vac_config_content, file, default_flow_style=False)
203
203
 
204
- print(f"vac_config.yaml written successfully with service name '{service_name}'.")
204
+ print(f"{vac_config_path} written successfully with service name '{service_name}'.")
205
205
 
206
206
 
207
207
  def setup_init_subparser(subparsers):
@@ -109,14 +109,24 @@ class GenAIFunctionProcessor:
109
109
  work_on = api_requests_and_responses or self.last_api_requests_and_responses
110
110
  parts = []
111
111
  for part in work_on:
112
- parts.append(
113
- Part(
114
- function_response=genai.protos.FunctionResponse(
115
- name=part[0],
116
- response={"result": part[2], "args": json.dumps(part[1])}
112
+ try:
113
+ parts.append(
114
+ Part(
115
+ function_response=genai.protos.FunctionResponse(
116
+ name=part[0],
117
+ response={"result": part[2], "args": json.dumps(part[1])}
118
+ )
117
119
  )
118
120
  )
119
- )
121
+ except Exception as err:
122
+ parts.append(
123
+ Part(
124
+ function_response=genai.protos.FunctionResponse(
125
+ name=part[0],
126
+ response={"result": f"ERROR: {str(err)}"}
127
+ )
128
+ )
129
+ )
120
130
 
121
131
  return parts
122
132
 
@@ -212,14 +222,15 @@ class GenAIFunctionProcessor:
212
222
  if fn := part.function_call:
213
223
  # Extract parameters for the function call
214
224
  function_name = fn.name
215
- params = {key: val for key, val in fn.args.items()}
225
+ params_obj = {key: val for key, val in fn.args.items()}
226
+ params = ', '.join(f'{key}={val}' for key, val in params_obj.items())
216
227
  log.info(f"Executing {function_name} with params {params}")
217
228
 
218
229
  # Check if the function is in our dictionary of available functions
219
230
  if function_name in self.funcs:
220
231
  try:
221
232
  # Execute the function with the provided parameters
222
- result = self.funcs[function_name](**params)
233
+ result = self.funcs[function_name](**params_obj)
223
234
  log.info(f"Got result from {function_name}: {result}")
224
235
  except Exception as err:
225
236
  error_message = f"Error in {function_name}: {str(err)}"
@@ -0,0 +1,83 @@
1
+ import os
2
+ from ..pubsub import decode_pubsub_message
3
+ from langfuse import Langfuse
4
+ from ..custom_logging import log
5
+
6
+ # Example of how eval_funcs might be structured
7
+ def eval_length(trace):
8
+ """
9
+ An example of how eval_funcs might be structured.
10
+ Must output a dictionary with 'score' and 'reason' keys.
11
+ """
12
+ # Example evaluation logic
13
+ return {
14
+ "score": len(trace.output), # Example: length of the output text
15
+ "reason": "Length of the output text"
16
+ }
17
+
18
+ def pubsub_to_evals(data: dict, eval_funcs: list=[eval_length]) -> dict:
19
+ """
20
+ Process a Pub/Sub message and run evaluations using the provided evaluation functions.
21
+
22
+ Args:
23
+ data (dict): The Pub/Sub message data.
24
+ eval_funcs (list): A list of evaluation functions to run. Each function should return a dict with 'score' and 'reason'.
25
+ """
26
+
27
+ # Decode the message
28
+ message_data, metadata, vector_name = decode_pubsub_message(data)
29
+
30
+ if 'trace_id' not in message_data:
31
+ raise ValueError('No trace_id found in message data')
32
+
33
+ trace_id = message_data.pop('trace_id', None)
34
+
35
+ return do_evals(trace_id, eval_funcs, **message_data)
36
+
37
+
38
+ def direct_langfuse_evals(data, eval_funcs: list=[eval_length]):
39
+ if 'trace_id' not in data:
40
+ raise ValueError('No trace_id found in data')
41
+
42
+ return do_evals(data['trace_id'], eval_funcs, **data)
43
+
44
+
45
+ def do_evals(trace_id, eval_funcs: list=[eval_length], **kwargs) -> dict:
46
+ # Initialize Langfuse with environment variables
47
+ langfuse = Langfuse(
48
+ secret_key=os.environ["LANGFUSE_SECRET_KEY"],
49
+ public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
50
+ host=os.environ["LANGFUSE_HOST"]
51
+ )
52
+
53
+ # Fetch the latest trace (or modify as needed to fetch a specific trace)
54
+ trace = langfuse.fetch_trace(id=trace_id)
55
+
56
+ if trace.output is None:
57
+ raise ValueError("Trace {trace.name} had no generated output, it was skipped")
58
+
59
+ # Run the evaluation functions
60
+ eval_results = []
61
+ for eval_func in eval_funcs:
62
+ eval_result = eval_func(trace) # Assuming eval_func returns a dict with 'score' and 'reason'
63
+ eval_results.append(eval_result)
64
+
65
+ eval_name = eval_func.__name__
66
+
67
+ if 'score' or 'reason' not in eval_result:
68
+ raise ValueError(f"Trace {trace.name} using {eval_name=} did not return a dict with 'score' and 'reason': {eval_result=}")
69
+
70
+ log.info(f"TraceId {trace.id} with name {trace.name} had {eval_name=} with score {eval_result=}")
71
+
72
+ # Submit the evaluation to Langfuse
73
+ langfuse.score(
74
+ trace_id=trace.id,
75
+ name=eval_name, # Use the function name as the evaluation name
76
+ value=eval_result["score"],
77
+ comment=eval_result["reason"],
78
+ **kwargs
79
+ )
80
+
81
+ return {"trace_id": trace.id, "eval_results": eval_results}
82
+
83
+
@@ -5,6 +5,8 @@ except ImportError:
5
5
 
6
6
  import json
7
7
  import subprocess
8
+ from datetime import datetime
9
+ import shutil
8
10
  import os
9
11
  import io
10
12
  from typing import Dict, Any
@@ -75,6 +77,13 @@ class TerraformVarsEditor:
75
77
 
76
78
  self.tfvars_file = tfvars_file
77
79
  self.terraform_dir = terraform_dir
80
+
81
+ # Ensure the tfvars file exists, if not, create it
82
+ if not os.path.exists(self.tfvars_file):
83
+ log.info(f"{self.tfvars_file} does not exist. Creating a new file.")
84
+ with open(self.tfvars_file, 'w') as file:
85
+ file.write("") # Create an empty tfvars file
86
+
78
87
  self.tfvars_data = self._load_tfvars()
79
88
 
80
89
  def _load_tfvars(self) -> Dict[str, Any]:
@@ -118,8 +127,9 @@ class TerraformVarsEditor:
118
127
  -------
119
128
  backup_file = self._backup_tfvars()
120
129
  """
121
- backup_file = f"{self.tfvars_file}.bak"
122
- os.rename(self.tfvars_file, backup_file)
130
+ timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
131
+ backup_file = f"{self.tfvars_file}.{timestamp}.bak"
132
+ shutil.copy2(self.tfvars_file, backup_file)
123
133
  return backup_file
124
134
 
125
135
  def _restore_tfvars(self, backup_file: str) -> None:
@@ -231,8 +241,10 @@ class TerraformVarsEditor:
231
241
  # Attempt to validate the changes with Terraform
232
242
  if not self.validate_terraform():
233
243
  # If validation fails, restore the original file from the backup
244
+ failed_file = f"{self.tfvars_file}.failed"
245
+ shutil.copy2(self.tfvars_file, failed_file)
234
246
  self._restore_tfvars(backup_file)
235
- log.error(f"Changes aborted, original {self.tfvars_file} restored.")
247
+ print(f"Changes aborted, original {self.tfvars_file} restored. Failed file: {failed_file}")
236
248
  else:
237
249
  log.info(f"Terraform validation passed, changes saved to {self.tfvars_file}.")
238
250
  os.remove(backup_file) # Remove the backup if validation passes
@@ -273,8 +285,11 @@ class TerraformVarsEditor:
273
285
  # Attempt to validate the changes with Terraform
274
286
  if not self.validate_terraform():
275
287
  # If validation fails, restore the original file from the backup
288
+ failed_file = f"{self.tfvars_file}.failed"
289
+ shutil.copy2(self.tfvars_file, failed_file)
276
290
  self._restore_tfvars(backup_file)
277
- console.print(f"Changes aborted, original {self.tfvars_file} restored.")
291
+
292
+ print(f"Changes aborted, original {self.tfvars_file} restored. Failed file: {failed_file}")
278
293
  else:
279
294
  console.print(f"Terraform validation passed, changes saved to {self.tfvars_file}.")
280
295
  os.remove(backup_file) # Remove the backup if validation passes
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.88.4
3
+ Version: 0.89.2
4
4
  Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
5
5
  Home-page: https://github.com/sunholo-data/sunholo-py
6
- Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.88.4.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.89.2.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -105,6 +105,7 @@ sunholo/invoke/direct_vac_func.py
105
105
  sunholo/invoke/invoke_vac_utils.py
106
106
  sunholo/langfuse/__init__.py
107
107
  sunholo/langfuse/callback.py
108
+ sunholo/langfuse/evals.py
108
109
  sunholo/langfuse/prompts.py
109
110
  sunholo/llamaindex/__init__.py
110
111
  sunholo/llamaindex/get_files.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes