synth-ai 0.2.0__py3-none-any.whl → 0.2.1.dev0__py3-none-any.whl

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 (266) hide show
  1. synth_ai/__init__.py +28 -2
  2. synth_ai/core/system.py +4 -0
  3. synth_ai/environments/__init__.py +35 -0
  4. synth_ai/environments/environment/__init__.py +1 -0
  5. synth_ai/environments/environment/artifacts/__init__.py +1 -0
  6. synth_ai/environments/environment/artifacts/base.py +50 -0
  7. synth_ai/environments/environment/core.py +22 -0
  8. synth_ai/environments/environment/db/__init__.py +1 -0
  9. synth_ai/environments/environment/db/sqlite.py +45 -0
  10. synth_ai/environments/environment/registry.py +24 -0
  11. synth_ai/environments/environment/resources/sqlite.py +46 -0
  12. synth_ai/environments/environment/results.py +1 -0
  13. synth_ai/environments/environment/rewards/__init__.py +1 -0
  14. synth_ai/environments/environment/rewards/core.py +28 -0
  15. synth_ai/environments/environment/shared_engine.py +26 -0
  16. synth_ai/environments/environment/tools/__init__.py +34 -0
  17. synth_ai/environments/examples/__init__.py +1 -0
  18. synth_ai/environments/examples/crafter_classic/__init__.py +8 -0
  19. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_comprehensive_evaluation.py +58 -0
  20. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_browser.py +152 -0
  21. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_framework.py +1194 -0
  22. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_quick_evaluation.py +51 -0
  23. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_react_agent.py +872 -0
  24. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluation.py +1412 -0
  25. synth_ai/environments/examples/crafter_classic/agent_demos/test_crafter_react_agent.py +1110 -0
  26. synth_ai/environments/examples/crafter_classic/config_logging.py +111 -0
  27. synth_ai/environments/examples/crafter_classic/engine.py +502 -0
  28. synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +63 -0
  29. synth_ai/environments/examples/crafter_classic/engine_helpers/action_map.py +5 -0
  30. synth_ai/environments/examples/crafter_classic/engine_helpers/serialization.py +74 -0
  31. synth_ai/environments/examples/crafter_classic/environment.py +255 -0
  32. synth_ai/environments/examples/crafter_classic/taskset.py +228 -0
  33. synth_ai/environments/examples/enron/agent_demos/test_synth_react.py +535 -0
  34. synth_ai/environments/examples/enron/art_helpers/email_search_tools.py +156 -0
  35. synth_ai/environments/examples/enron/art_helpers/local_email_db.py +280 -0
  36. synth_ai/environments/examples/enron/art_helpers/types_enron.py +24 -0
  37. synth_ai/environments/examples/enron/engine.py +291 -0
  38. synth_ai/environments/examples/enron/environment.py +165 -0
  39. synth_ai/environments/examples/enron/taskset.py +112 -0
  40. synth_ai/environments/examples/enron/units/keyword_stats.py +111 -0
  41. synth_ai/environments/examples/enron/units/test_email_index.py +8 -0
  42. synth_ai/environments/examples/minigrid/__init__.py +48 -0
  43. synth_ai/environments/examples/minigrid/agent_demos/minigrid_evaluation_framework.py +1188 -0
  44. synth_ai/environments/examples/minigrid/agent_demos/minigrid_quick_evaluation.py +47 -0
  45. synth_ai/environments/examples/minigrid/agent_demos/minigrid_react_agent.py +562 -0
  46. synth_ai/environments/examples/minigrid/agent_demos/minigrid_trace_evaluation.py +220 -0
  47. synth_ai/environments/examples/minigrid/agent_demos/test_minigrid_react_agent.py +393 -0
  48. synth_ai/environments/examples/minigrid/engine.py +589 -0
  49. synth_ai/environments/examples/minigrid/environment.py +274 -0
  50. synth_ai/environments/examples/minigrid/environment_mapping.py +242 -0
  51. synth_ai/environments/examples/minigrid/puzzle_loader.py +416 -0
  52. synth_ai/environments/examples/minigrid/taskset.py +583 -0
  53. synth_ai/environments/examples/minigrid/units/test_action_behavior.py +226 -0
  54. synth_ai/environments/examples/minigrid/units/test_debug_messages.py +83 -0
  55. synth_ai/environments/examples/minigrid/units/test_exploration.py +120 -0
  56. synth_ai/environments/examples/minigrid/units/test_minigrid_engine.py +214 -0
  57. synth_ai/environments/examples/minigrid/units/test_minigrid_environment.py +238 -0
  58. synth_ai/environments/examples/minigrid/units/test_minigrid_environment_mapping.py +301 -0
  59. synth_ai/environments/examples/minigrid/units/test_minigrid_taskset.py +210 -0
  60. synth_ai/environments/examples/nethack/__init__.py +7 -0
  61. synth_ai/environments/examples/nethack/achievements.py +337 -0
  62. synth_ai/environments/examples/nethack/agent_demos/nethack_evaluation_framework.py +981 -0
  63. synth_ai/environments/examples/nethack/agent_demos/nethack_quick_evaluation.py +74 -0
  64. synth_ai/environments/examples/nethack/agent_demos/nethack_react_agent.py +832 -0
  65. synth_ai/environments/examples/nethack/agent_demos/test_nethack_react_agent.py +1112 -0
  66. synth_ai/environments/examples/nethack/engine.py +738 -0
  67. synth_ai/environments/examples/nethack/environment.py +255 -0
  68. synth_ai/environments/examples/nethack/helpers/__init__.py +42 -0
  69. synth_ai/environments/examples/nethack/helpers/action_mapping.py +301 -0
  70. synth_ai/environments/examples/nethack/helpers/nle_wrapper.py +401 -0
  71. synth_ai/environments/examples/nethack/helpers/observation_utils.py +433 -0
  72. synth_ai/environments/examples/nethack/helpers/recording_wrapper.py +201 -0
  73. synth_ai/environments/examples/nethack/helpers/trajectory_recorder.py +268 -0
  74. synth_ai/environments/examples/nethack/helpers/visualization/replay_viewer.py +308 -0
  75. synth_ai/environments/examples/nethack/helpers/visualization/visualizer.py +430 -0
  76. synth_ai/environments/examples/nethack/taskset.py +323 -0
  77. synth_ai/environments/examples/nethack/units/test_nethack_engine.py +277 -0
  78. synth_ai/environments/examples/nethack/units/test_nethack_environment.py +281 -0
  79. synth_ai/environments/examples/nethack/units/test_nethack_taskset.py +213 -0
  80. synth_ai/environments/examples/nethack/units/test_recording.py +307 -0
  81. synth_ai/environments/examples/red/__init__.py +7 -0
  82. synth_ai/environments/examples/red/agent_demos/__init__.py +1 -0
  83. synth_ai/environments/examples/red/agent_demos/test_synth_react.py +1471 -0
  84. synth_ai/environments/examples/red/config_logging.py +110 -0
  85. synth_ai/environments/examples/red/engine.py +693 -0
  86. synth_ai/environments/examples/red/engine_helpers/__init__.py +1 -0
  87. synth_ai/environments/examples/red/engine_helpers/memory_map.py +28 -0
  88. synth_ai/environments/examples/red/engine_helpers/reward_components.py +275 -0
  89. synth_ai/environments/examples/red/engine_helpers/reward_library/__init__.py +142 -0
  90. synth_ai/environments/examples/red/engine_helpers/reward_library/adaptive_rewards.py +56 -0
  91. synth_ai/environments/examples/red/engine_helpers/reward_library/battle_rewards.py +283 -0
  92. synth_ai/environments/examples/red/engine_helpers/reward_library/composite_rewards.py +149 -0
  93. synth_ai/environments/examples/red/engine_helpers/reward_library/economy_rewards.py +137 -0
  94. synth_ai/environments/examples/red/engine_helpers/reward_library/efficiency_rewards.py +56 -0
  95. synth_ai/environments/examples/red/engine_helpers/reward_library/exploration_rewards.py +330 -0
  96. synth_ai/environments/examples/red/engine_helpers/reward_library/novelty_rewards.py +120 -0
  97. synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_rewards.py +558 -0
  98. synth_ai/environments/examples/red/engine_helpers/reward_library/pokemon_rewards.py +312 -0
  99. synth_ai/environments/examples/red/engine_helpers/reward_library/social_rewards.py +147 -0
  100. synth_ai/environments/examples/red/engine_helpers/reward_library/story_rewards.py +246 -0
  101. synth_ai/environments/examples/red/engine_helpers/screen_analysis.py +367 -0
  102. synth_ai/environments/examples/red/engine_helpers/state_extraction.py +139 -0
  103. synth_ai/environments/examples/red/environment.py +235 -0
  104. synth_ai/environments/examples/red/taskset.py +77 -0
  105. synth_ai/environments/examples/red/test_fixes.py +125 -0
  106. synth_ai/environments/examples/red/test_fixes_mock.py +148 -0
  107. synth_ai/environments/examples/red/units/__init__.py +1 -0
  108. synth_ai/environments/examples/red/units/test_basic_functionality.py +97 -0
  109. synth_ai/environments/examples/red/units/test_button_press_requirements.py +217 -0
  110. synth_ai/environments/examples/red/units/test_engine.py +192 -0
  111. synth_ai/environments/examples/red/units/test_environment.py +455 -0
  112. synth_ai/environments/examples/red/units/test_exploration_strategy.py +227 -0
  113. synth_ai/environments/examples/red/units/test_integration.py +217 -0
  114. synth_ai/environments/examples/red/units/test_memory_extraction.py +111 -0
  115. synth_ai/environments/examples/red/units/test_menu_bug_reproduction.py +1100 -0
  116. synth_ai/environments/examples/red/units/test_movement_debug.py +255 -0
  117. synth_ai/environments/examples/red/units/test_pokemon_mcts_debug.py +163 -0
  118. synth_ai/environments/examples/red/units/test_pokemon_mcts_verbose.py +117 -0
  119. synth_ai/environments/examples/red/units/test_red_basic.py +145 -0
  120. synth_ai/environments/examples/red/units/test_red_comprehensive.py +323 -0
  121. synth_ai/environments/examples/red/units/test_retry_movement.py +195 -0
  122. synth_ai/environments/examples/red/units/test_reward_components.py +186 -0
  123. synth_ai/environments/examples/red/units/test_rom_integration.py +260 -0
  124. synth_ai/environments/examples/red/units/test_taskset.py +116 -0
  125. synth_ai/environments/examples/red/units/test_tree.py +448 -0
  126. synth_ai/environments/examples/sokoban/__init__.py +1 -0
  127. synth_ai/environments/examples/sokoban/agent_demos/sokoban_full_eval.py +900 -0
  128. synth_ai/environments/examples/sokoban/agent_demos/test_dspy_react.py +1 -0
  129. synth_ai/environments/examples/sokoban/agent_demos/test_sokoban_react_agent.py +498 -0
  130. synth_ai/environments/examples/sokoban/agent_demos/test_synth_lats.py +1 -0
  131. synth_ai/environments/examples/sokoban/agent_demos/test_synth_react_locally.py +748 -0
  132. synth_ai/environments/examples/sokoban/agent_demos/test_synth_react_service.py +296 -0
  133. synth_ai/environments/examples/sokoban/engine.py +675 -0
  134. synth_ai/environments/examples/sokoban/engine_helpers/__init__.py +1 -0
  135. synth_ai/environments/examples/sokoban/engine_helpers/room_utils.py +656 -0
  136. synth_ai/environments/examples/sokoban/engine_helpers/vendored/__init__.py +17 -0
  137. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/__init__.py +3 -0
  138. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/boxoban_env.py +129 -0
  139. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/render_utils.py +370 -0
  140. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/room_utils.py +331 -0
  141. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env.py +305 -0
  142. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_fixed_targets.py +66 -0
  143. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_pull.py +114 -0
  144. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_two_player.py +122 -0
  145. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_variations.py +394 -0
  146. synth_ai/environments/examples/sokoban/environment.py +228 -0
  147. synth_ai/environments/examples/sokoban/generate_verified_puzzles.py +438 -0
  148. synth_ai/environments/examples/sokoban/puzzle_loader.py +311 -0
  149. synth_ai/environments/examples/sokoban/taskset.py +425 -0
  150. synth_ai/environments/examples/sokoban/units/astar_common.py +94 -0
  151. synth_ai/environments/examples/sokoban/units/test_building_task_set.py +49 -0
  152. synth_ai/environments/examples/sokoban/units/test_false_positive.py +120 -0
  153. synth_ai/environments/examples/sokoban/units/test_simple_run_through_environment.py +119 -0
  154. synth_ai/environments/examples/sokoban/units/test_sokoban_environment.py +98 -0
  155. synth_ai/environments/examples/sokoban/units/test_tree.py +364 -0
  156. synth_ai/environments/examples/tictactoe/__init__.py +1 -0
  157. synth_ai/environments/examples/tictactoe/agent_demos/test_synth_react.py +266 -0
  158. synth_ai/environments/examples/tictactoe/agent_demos/test_tictactoe_react_agent.py +470 -0
  159. synth_ai/environments/examples/tictactoe/engine.py +368 -0
  160. synth_ai/environments/examples/tictactoe/environment.py +239 -0
  161. synth_ai/environments/examples/tictactoe/taskset.py +214 -0
  162. synth_ai/environments/examples/tictactoe/units/test_tictactoe_engine.py +393 -0
  163. synth_ai/environments/examples/tictactoe/units/test_tictactoe_environment.py +493 -0
  164. synth_ai/environments/examples/tictactoe/units/test_tictactoe_taskset.py +191 -0
  165. synth_ai/environments/examples/verilog/__init__.py +10 -0
  166. synth_ai/environments/examples/verilog/agent_demos/test_synth_react.py +520 -0
  167. synth_ai/environments/examples/verilog/engine.py +328 -0
  168. synth_ai/environments/examples/verilog/environment.py +349 -0
  169. synth_ai/environments/examples/verilog/taskset.py +418 -0
  170. synth_ai/environments/examples/verilog/units/test_verilog_engine.py +466 -0
  171. synth_ai/environments/examples/verilog/units/test_verilog_environment.py +585 -0
  172. synth_ai/environments/examples/verilog/units/test_verilog_integration.py +383 -0
  173. synth_ai/environments/examples/verilog/units/test_verilog_taskset.py +457 -0
  174. synth_ai/environments/reproducibility/core.py +42 -0
  175. synth_ai/environments/reproducibility/tree.py +364 -0
  176. synth_ai/environments/service/app.py +78 -0
  177. synth_ai/environments/service/core_routes.py +775 -0
  178. synth_ai/environments/service/external_registry.py +57 -0
  179. synth_ai/environments/service/registry.py +9 -0
  180. synth_ai/environments/stateful/__init__.py +1 -0
  181. synth_ai/environments/stateful/core.py +28 -0
  182. synth_ai/environments/stateful/engine.py +21 -0
  183. synth_ai/environments/stateful/state.py +7 -0
  184. synth_ai/environments/tasks/api.py +19 -0
  185. synth_ai/environments/tasks/core.py +78 -0
  186. synth_ai/environments/tasks/filters.py +39 -0
  187. synth_ai/environments/tasks/utils.py +89 -0
  188. synth_ai/environments/v0_observability/history.py +3 -0
  189. synth_ai/environments/v0_observability/log.py +2 -0
  190. synth_ai/lm/caching/constants.py +1 -0
  191. synth_ai/{zyk/lms → lm}/caching/ephemeral.py +4 -8
  192. synth_ai/{zyk/lms → lm}/caching/handler.py +15 -15
  193. synth_ai/{zyk/lms → lm}/caching/initialize.py +2 -4
  194. synth_ai/{zyk/lms → lm}/caching/persistent.py +4 -10
  195. synth_ai/{zyk/lms → lm}/config.py +2 -1
  196. synth_ai/{zyk/lms → lm}/constants.py +2 -2
  197. synth_ai/{zyk/lms → lm}/core/all.py +10 -10
  198. synth_ai/{zyk/lms → lm}/core/main.py +57 -33
  199. synth_ai/{zyk/lms → lm}/core/vendor_clients.py +12 -10
  200. synth_ai/lm/cost/monitor.py +1 -0
  201. synth_ai/lm/cost/statefulness.py +1 -0
  202. synth_ai/lm/provider_support/__init__.py +8 -0
  203. synth_ai/lm/provider_support/anthropic.py +945 -0
  204. synth_ai/lm/provider_support/openai.py +1115 -0
  205. synth_ai/lm/provider_support/suppress_logging.py +31 -0
  206. synth_ai/{zyk/lms → lm}/structured_outputs/handler.py +58 -80
  207. synth_ai/{zyk/lms → lm}/structured_outputs/inject.py +6 -20
  208. synth_ai/{zyk/lms → lm}/structured_outputs/rehabilitate.py +6 -12
  209. synth_ai/{zyk/lms → lm}/vendors/core/anthropic_api.py +21 -30
  210. synth_ai/{zyk/lms → lm}/vendors/core/gemini_api.py +35 -32
  211. synth_ai/{zyk/lms → lm}/vendors/core/mistral_api.py +19 -28
  212. synth_ai/{zyk/lms → lm}/vendors/core/openai_api.py +26 -36
  213. synth_ai/{zyk/lms → lm}/vendors/openai_standard.py +29 -33
  214. synth_ai/{zyk/lms → lm}/vendors/retries.py +1 -1
  215. synth_ai/lm/vendors/supported/__init__.py +0 -0
  216. synth_ai/{zyk/lms → lm}/vendors/supported/custom_endpoint.py +131 -118
  217. synth_ai/{zyk/lms → lm}/vendors/supported/deepseek.py +4 -8
  218. synth_ai/{zyk/lms → lm}/vendors/supported/grok.py +6 -8
  219. synth_ai/{zyk/lms → lm}/vendors/supported/groq.py +1 -1
  220. synth_ai/{zyk/lms → lm}/vendors/supported/ollama.py +2 -2
  221. synth_ai/{zyk/lms → lm}/vendors/supported/openrouter.py +18 -16
  222. synth_ai/{zyk/lms → lm}/vendors/supported/together.py +1 -1
  223. synth_ai/tracing/__init__.py +0 -0
  224. synth_ai/tracing/abstractions.py +224 -0
  225. synth_ai/tracing/base_client.py +91 -0
  226. synth_ai/tracing/client_manager.py +131 -0
  227. synth_ai/tracing/config.py +140 -0
  228. synth_ai/tracing/context.py +146 -0
  229. synth_ai/tracing/decorators.py +679 -0
  230. synth_ai/tracing/events/__init__.py +0 -0
  231. synth_ai/tracing/events/manage.py +147 -0
  232. synth_ai/tracing/events/scope.py +86 -0
  233. synth_ai/tracing/events/store.py +227 -0
  234. synth_ai/tracing/immediate_client.py +152 -0
  235. synth_ai/tracing/local.py +18 -0
  236. synth_ai/tracing/log_client_base.py +74 -0
  237. synth_ai/tracing/retry_queue.py +187 -0
  238. synth_ai/tracing/trackers.py +515 -0
  239. synth_ai/tracing/upload.py +504 -0
  240. synth_ai/tracing/utils.py +9 -0
  241. synth_ai/zyk/__init__.py +28 -2
  242. synth_ai-0.2.1.dev0.dist-info/METADATA +349 -0
  243. synth_ai-0.2.1.dev0.dist-info/RECORD +261 -0
  244. {synth_ai-0.2.0.dist-info → synth_ai-0.2.1.dev0.dist-info}/WHEEL +1 -1
  245. synth_ai/zyk/lms/caching/constants.py +0 -1
  246. synth_ai/zyk/lms/cost/monitor.py +0 -1
  247. synth_ai/zyk/lms/cost/statefulness.py +0 -1
  248. synth_ai-0.2.0.dist-info/METADATA +0 -36
  249. synth_ai-0.2.0.dist-info/RECORD +0 -50
  250. /synth_ai/{zyk/lms/__init__.py → environments/reproducibility/helpers.py} +0 -0
  251. /synth_ai/{zyk/lms/caching → lm}/__init__.py +0 -0
  252. /synth_ai/{zyk/lms/core → lm/caching}/__init__.py +0 -0
  253. /synth_ai/{zyk/lms → lm}/caching/dbs.py +0 -0
  254. /synth_ai/{zyk/lms/cost → lm/core}/__init__.py +0 -0
  255. /synth_ai/{zyk/lms → lm}/core/exceptions.py +0 -0
  256. /synth_ai/{zyk/lms/structured_outputs → lm/cost}/__init__.py +0 -0
  257. /synth_ai/{zyk/lms/vendors → lm/structured_outputs}/__init__.py +0 -0
  258. /synth_ai/{zyk/lms → lm}/tools/__init__.py +0 -0
  259. /synth_ai/{zyk/lms → lm}/tools/base.py +0 -0
  260. /synth_ai/{zyk/lms/vendors/core → lm/vendors}/__init__.py +0 -0
  261. /synth_ai/{zyk/lms → lm}/vendors/base.py +0 -0
  262. /synth_ai/{zyk/lms/vendors/local → lm/vendors/core}/__init__.py +0 -0
  263. /synth_ai/{zyk/lms/vendors/supported → lm/vendors/local}/__init__.py +0 -0
  264. /synth_ai/{zyk/lms → lm}/vendors/local/ollama.py +0 -0
  265. {synth_ai-0.2.0.dist-info → synth_ai-0.2.1.dev0.dist-info/licenses}/LICENSE +0 -0
  266. {synth_ai-0.2.0.dist-info → synth_ai-0.2.1.dev0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,515 @@
1
+ import asyncio
2
+ import contextvars
3
+ from typing import Any, Dict, List, Literal, Optional, Tuple, Union
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from synth_ai.tracing.config import VALID_TYPES, Message, ModelParams
8
+ from synth_ai.tracing.local import _local
9
+
10
+ # Existing SynthTrackerSync and SynthTrackerAsync classes...
11
+
12
+
13
+ class SynthTrackerSync:
14
+ """Tracker for synchronous functions.
15
+
16
+ Purpose is to annotate the inside of your sync functions to track intermediate values.
17
+ Decorator @trace_event_sync is used to annotate the functions and track the inputs and outputs.
18
+ This tracker is instead used to access the data inside of decorated functions.
19
+ """
20
+
21
+ _local = _local
22
+
23
+ @classmethod
24
+ def initialize(cls) -> None:
25
+ cls._local.initialized = True
26
+ cls._local.inputs = []
27
+ cls._local.outputs = []
28
+
29
+ @classmethod
30
+ def track_lm(
31
+ cls,
32
+ messages: List[Dict[str, str]],
33
+ model_name: str,
34
+ model_params: Optional[Dict[str, Union[str, int, float]]] = None,
35
+ finetune: bool = False,
36
+ ):
37
+ # print("Tracking LM call in sync context - ",messages) # Added logging
38
+ if getattr(cls._local, "initialized", False):
39
+ cls._local.inputs.append(
40
+ {
41
+ "origin": "agent",
42
+ "messages": messages,
43
+ "model_name": model_name,
44
+ "model_params": model_params,
45
+ "finetune": finetune,
46
+ }
47
+ )
48
+ else:
49
+ pass
50
+
51
+ @classmethod
52
+ def track_state(
53
+ cls,
54
+ variable_name: str,
55
+ variable_value: Union[BaseModel, str, dict, int, float, bool, list, None],
56
+ origin: Literal["agent", "environment"],
57
+ annotation: Optional[str] = None,
58
+ ):
59
+ # Skip if value is not a trackable type instead of raising error
60
+ if not isinstance(variable_value, VALID_TYPES):
61
+ return
62
+
63
+ if getattr(cls._local, "initialized", False):
64
+ if isinstance(variable_value, BaseModel):
65
+ variable_value = variable_value.model_dump()
66
+ cls._local.outputs.append(
67
+ {
68
+ "origin": origin,
69
+ "variable_name": variable_name,
70
+ "variable_value": variable_value,
71
+ "annotation": annotation,
72
+ }
73
+ )
74
+ # logger.debug(f"Tracked state: {variable_name}")
75
+ else:
76
+ pass
77
+ # raise RuntimeError(
78
+ # "Trace not initialized. Use within a function decorated with @trace_event_sync."
79
+ # )
80
+
81
+ @classmethod
82
+ def get_traced_data(cls) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
83
+ return getattr(cls._local, "inputs", []), getattr(cls._local, "outputs", [])
84
+
85
+ @classmethod
86
+ def finalize(cls) -> None:
87
+ # Clean up the thread-local storage
88
+ cls._local.initialized = False
89
+ cls._local.inputs = []
90
+ cls._local.outputs = []
91
+ # logger.debug("Finalized trace data")
92
+
93
+ @classmethod
94
+ def track_lm_output(
95
+ cls,
96
+ messages: List[Dict[str, str]],
97
+ model_name: str,
98
+ finetune: bool = False,
99
+ ):
100
+ """
101
+ Tracks 'messages' as if they were output from the LLM.
102
+ """
103
+ if getattr(cls._local, "initialized", False):
104
+ cls._local.outputs.append(
105
+ {
106
+ "origin": "agent",
107
+ "messages": messages,
108
+ "model_name": model_name,
109
+ "finetune": finetune,
110
+ }
111
+ )
112
+ else:
113
+ pass
114
+
115
+
116
+ # Context variables for asynchronous tracing
117
+ trace_inputs_var = contextvars.ContextVar("trace_inputs", default=None)
118
+ trace_outputs_var = contextvars.ContextVar("trace_outputs", default=None)
119
+ trace_initialized_var = contextvars.ContextVar("trace_initialized", default=False)
120
+
121
+
122
+ class SynthTrackerAsync:
123
+ """Tracker for synchronous functions.
124
+
125
+ Purpose is to annotate the inside of your sync functions to track intermediate values.
126
+ Decorator @trace_event_sync is used to annotate the functions and track the inputs and outputs.
127
+ This tracker is instead used to access the data inside of decorated functions.
128
+ """
129
+
130
+ @classmethod
131
+ def initialize(cls) -> None:
132
+ trace_initialized_var.set(True)
133
+ trace_inputs_var.set([]) # List of tuples: (origin, var)
134
+ trace_outputs_var.set([]) # List of tuples: (origin, var)
135
+ # logger.debug("AsyncTrace initialized")
136
+
137
+ @classmethod
138
+ def track_lm(
139
+ cls,
140
+ messages: List[Dict[str, str]],
141
+ model_name: str,
142
+ model_params: Optional[Dict[str, Union[str, int, float]]] = None,
143
+ finetune: bool = False,
144
+ ):
145
+ # print("Tracking LM call in async context") # Added logging
146
+ if trace_initialized_var.get():
147
+ trace_inputs = trace_inputs_var.get()
148
+ trace_inputs.append(
149
+ {
150
+ "origin": "agent",
151
+ "messages": messages,
152
+ "model_name": model_name,
153
+ "model_params": model_params,
154
+ "finetune": finetune,
155
+ }
156
+ )
157
+ trace_inputs_var.set(trace_inputs)
158
+ else:
159
+ pass
160
+ # raise RuntimeError(
161
+ # "Trace not initialized. Use within a function decorated with @trace_event_async."
162
+ # )
163
+
164
+ @classmethod
165
+ def track_state(
166
+ cls,
167
+ variable_name: str,
168
+ variable_value: Union[BaseModel, str, dict, int, float, bool, list, None],
169
+ origin: Literal["agent", "environment"],
170
+ annotation: Optional[str] = None,
171
+ io_type: Literal["input", "output"] = "output",
172
+ ):
173
+ # Skip if value is not a trackable type instead of raising error
174
+ if not isinstance(variable_value, VALID_TYPES):
175
+ return
176
+
177
+ if trace_initialized_var.get():
178
+ if isinstance(variable_value, BaseModel):
179
+ variable_value = variable_value.model_dump()
180
+ trace_outputs = trace_outputs_var.get()
181
+ if io_type == "input":
182
+ trace_inputs = trace_inputs_var.get()
183
+ trace_inputs.append(
184
+ {
185
+ "origin": origin,
186
+ "variable_name": variable_name,
187
+ "variable_value": variable_value,
188
+ "annotation": annotation,
189
+ }
190
+ )
191
+ trace_inputs_var.set(trace_inputs)
192
+ else:
193
+ trace_outputs.append(
194
+ {
195
+ "origin": origin,
196
+ "variable_name": variable_name,
197
+ "variable_value": variable_value,
198
+ "annotation": annotation,
199
+ }
200
+ )
201
+ trace_outputs_var.set(trace_outputs)
202
+ # logger.debug(f"Tracked state: {variable_name}")
203
+ else:
204
+ pass
205
+ # raise RuntimeError(
206
+ # "Trace not initialized. Use within a function decorated with @trace_event_async."
207
+ # )
208
+
209
+ @classmethod
210
+ def get_traced_data(cls) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
211
+ traced_inputs = trace_inputs_var.get()
212
+ traced_outputs = trace_outputs_var.get()
213
+ return traced_inputs, traced_outputs
214
+
215
+ @classmethod
216
+ def finalize(cls) -> None:
217
+ trace_initialized_var.set(False)
218
+ trace_inputs_var.set([])
219
+ trace_outputs_var.set([])
220
+ # logger.debug("Finalized async trace data")
221
+
222
+ @classmethod
223
+ def track_lm_output(
224
+ cls,
225
+ messages: List[Dict[str, str]],
226
+ model_name: str,
227
+ finetune: bool = False,
228
+ ):
229
+ """
230
+ Tracks 'messages' as if they were output from the LLM.
231
+ """
232
+ if trace_initialized_var.get():
233
+ trace_outputs = trace_outputs_var.get()
234
+ trace_outputs.append(
235
+ {
236
+ "origin": "agent",
237
+ "messages": messages,
238
+ "model_name": model_name,
239
+ "finetune": finetune,
240
+ }
241
+ )
242
+ trace_outputs_var.set(trace_outputs)
243
+ else:
244
+ pass
245
+
246
+
247
+ # Make traces available globally
248
+ synth_tracker_sync = SynthTrackerSync
249
+ synth_tracker_async = SynthTrackerAsync
250
+
251
+
252
+ class SynthTracker:
253
+ """Tracker for synchronous and asynchronous functions. Intelligently chooses between sync and async trackers.
254
+
255
+ Purpose is to annotate the inside of your sync and async functions to track intermediate values.
256
+ Decorators @trace_event_sync and @trace_event_async are used to annotate the functions and track the inputs and outputs.
257
+ This tracker is instead used to access the data inside of decorated functions.
258
+ """
259
+
260
+ @classmethod
261
+ def is_called_by_async(cls) -> bool:
262
+ try:
263
+ asyncio.get_running_loop() # Attempt to get the running event loop
264
+ # Debug logging disabled: print("DEBUG: Running in async context")
265
+ return True # If successful, we are in an async context
266
+ except RuntimeError:
267
+ # Debug logging disabled: print("DEBUG: Running in sync context")
268
+ return False # If there's no running event loop, we are in a sync context
269
+
270
+ @classmethod
271
+ def track_lm(
272
+ cls,
273
+ messages: List[Dict[str, str]],
274
+ model_name: str,
275
+ model_params: Optional[Dict[str, Union[str, int, float]]] = None,
276
+ finetune: bool = False,
277
+ ):
278
+ # Debug logging disabled: print("DEBUG: Tracking LM call")
279
+ """
280
+ Track a language model interaction within the current trace.
281
+ Automatically detects whether to use sync or async tracking.
282
+
283
+ Args:
284
+ messages (List[Dict[str, str]]): List of message dictionaries containing the conversation.
285
+ Each message should have:
286
+ - 'role': str - The role of the speaker (e.g., "user", "assistant", "system")
287
+ - 'content': str - The content of the message
288
+
289
+ model_name (str): Name of the language model being used
290
+ Examples: "gpt-4o-mini", "gpt-4o-mini", "claude-3-opus-20240229"
291
+
292
+ finetune (bool, optional): Whether this interaction is part of a fine-tuning process.
293
+ Defaults to False.
294
+
295
+ Raises:
296
+ RuntimeError: If called outside a traced context (use with @trace_event_sync
297
+ or @trace_event_async decorator)
298
+ TypeError: If messages or model_name are not of the correct type
299
+
300
+ Example:
301
+ ```python
302
+ @trace_event_sync(origin="agent", event_type="chat")
303
+ def process_chat(self, user_input: str):
304
+ messages = [
305
+ {"role": "user", "content": user_input}
306
+ ]
307
+ SynthTracker.track_lm(
308
+ messages=messages,
309
+ model_name="gpt-4o-mini"
310
+ )
311
+ ```
312
+ """
313
+ if cls.is_called_by_async() and trace_initialized_var.get():
314
+ # print("DEBUG: Tracking LM call in async context") # Added logging
315
+ synth_tracker_async.track_lm(
316
+ messages,
317
+ model_name,
318
+ model_params,
319
+ finetune,
320
+ )
321
+ elif getattr(synth_tracker_sync._local, "initialized", False):
322
+ # print("DEBUG: Tracking LM call in sync context") # Added logging
323
+ synth_tracker_sync.track_lm(
324
+ messages,
325
+ model_name,
326
+ model_params,
327
+ finetune,
328
+ )
329
+ else:
330
+ # Debug logging disabled: print("DEBUG: Skipping LM tracking - not initialized") # Added logging
331
+ pass
332
+
333
+ @classmethod
334
+ def track_state(
335
+ cls,
336
+ variable_name: str,
337
+ variable_value: Union[BaseModel, str, dict, int, float, bool, list, None],
338
+ origin: Literal["agent", "environment"],
339
+ annotation: Optional[str] = None,
340
+ ):
341
+ """
342
+ Track a state change or variable value within the current trace.
343
+ Automatically detects whether to use sync or async tracking.
344
+
345
+ Args:
346
+ variable_name (str): Name of the variable or state being tracked
347
+
348
+ variable_value (Union[BaseModel, str, dict, int, float, bool, list, None]):
349
+ Value to track. Must be one of the supported types:
350
+ - BaseModel (Pydantic models)
351
+ - Basic Python types (str, dict, int, float, bool, list)
352
+ - None
353
+
354
+ origin (Literal["agent", "environment"]): Source of the state change
355
+ - "agent": Changes from the AI/agent system
356
+ - "environment": Changes from external sources/environment
357
+
358
+ annotation (Optional[str], optional): Additional notes about the state change.
359
+ Defaults to None.
360
+
361
+ Raises:
362
+ RuntimeError: If called outside a traced context (use with @trace_event_sync
363
+ or @trace_event_async decorator)
364
+ TypeError: If variable_value is not one of the supported types
365
+ ValueError: If origin is not "agent" or "environment"
366
+
367
+ Example:
368
+ ```python
369
+ @trace_event_sync(origin="agent", event_type="process")
370
+ def update_state(self, new_value: dict):
371
+ SynthTracker.track_state(
372
+ variable_name="system_state",
373
+ variable_value=new_value,
374
+ origin="agent",
375
+ annotation="Updated after processing"
376
+ )
377
+ ```
378
+ """
379
+ if cls.is_called_by_async() and trace_initialized_var.get():
380
+ # logger.debug("Using async tracker to track state")
381
+ synth_tracker_async.track_state(variable_name, variable_value, origin, annotation)
382
+ elif getattr(synth_tracker_sync._local, "initialized", False):
383
+ # logger.debug("Using sync tracker to track state")
384
+ synth_tracker_sync.track_state(variable_name, variable_value, origin, annotation)
385
+ else:
386
+ # raise RuntimeError("Trace not initialized in track_state.")
387
+ pass
388
+
389
+ @classmethod
390
+ def get_traced_data(
391
+ cls,
392
+ async_sync: Literal[
393
+ "async", "sync", ""
394
+ ] = "", # Force only async or sync data to be returned
395
+ ) -> Tuple[list, list]:
396
+ traced_inputs, traced_outputs = [], []
397
+ # Debug logging disabled: print(
398
+ # f"\nDEBUG: Getting traced data with async_sync='{async_sync}'"
399
+ # ) # Added logging
400
+
401
+ if async_sync in ["async", ""]:
402
+ # Debug logging disabled: print("DEBUG: Retrieving async traced data")
403
+ traced_inputs_async, traced_outputs_async = synth_tracker_async.get_traced_data()
404
+ # Debug logging disabled: print(
405
+ # f"DEBUG: Found {len(traced_inputs_async)} async inputs and {len(traced_outputs_async)} async outputs"
406
+ # ) # Added logging
407
+ traced_inputs.extend(traced_inputs_async)
408
+ traced_outputs.extend(traced_outputs_async)
409
+
410
+ if async_sync in ["sync", ""]:
411
+ # Debug logging disabled: print("DEBUG: Retrieving sync traced data")
412
+ traced_inputs_sync, traced_outputs_sync = synth_tracker_sync.get_traced_data()
413
+ # Debug logging disabled: print(
414
+ # f"DEBUG: Found {len(traced_inputs_sync)} sync inputs and {len(traced_outputs_sync)} sync outputs"
415
+ # ) # Added logging
416
+ traced_inputs.extend(traced_inputs_sync)
417
+ traced_outputs.extend(traced_outputs_sync)
418
+
419
+ # Debug logging disabled: print(
420
+ # f"DEBUG: Final combined data: {len(traced_inputs)} inputs and {len(traced_outputs)} outputs\n"
421
+ # ) # Added logging
422
+ return traced_inputs, traced_outputs
423
+
424
+ @classmethod
425
+ def track_lm_output(
426
+ cls,
427
+ messages: List[Dict[str, str]],
428
+ model_name: str,
429
+ finetune: bool = False,
430
+ ):
431
+ """
432
+ Tracks 'messages' as if they were output from the LLM.
433
+ Automatically detects whether to use sync or async tracking.
434
+ """
435
+ if cls.is_called_by_async() and trace_initialized_var.get():
436
+ # Debug logging disabled: print("DEBUG: Tracking LM output in async context")
437
+ synth_tracker_async.track_lm_output(
438
+ messages=messages,
439
+ model_name=model_name,
440
+ finetune=finetune,
441
+ )
442
+ elif getattr(synth_tracker_sync._local, "initialized", False):
443
+ # Debug logging disabled: print("DEBUG: Tracking LM output in sync context")
444
+ synth_tracker_sync.track_lm_output(
445
+ messages=messages,
446
+ model_name=model_name,
447
+ finetune=finetune,
448
+ )
449
+ else:
450
+ # Debug logging disabled: print("DEBUG: Skipping LM output tracking - not initialized")
451
+ pass
452
+
453
+
454
+ def track_messages_sync(
455
+ input_messages: List[Message],
456
+ output_messages: List[Message],
457
+ model_name: str,
458
+ model_params: Optional[ModelParams] = None,
459
+ finetune: bool = False,
460
+ ) -> None:
461
+ """Track both input and output messages in a conversation synchronously.
462
+
463
+ Args:
464
+ input_messages: List of input messages (e.g., user messages)
465
+ output_messages: List of output messages (e.g., assistant responses)
466
+ model_name: Name of the language model being used
467
+ model_params: Optional parameters used for the model
468
+ finetune: Whether this conversation should be used for fine-tuning
469
+ """
470
+ # Track input messages
471
+ synth_tracker_sync.track_lm(
472
+ messages=input_messages,
473
+ model_name=model_name,
474
+ model_params=model_params,
475
+ finetune=finetune,
476
+ )
477
+
478
+ # Track output messages
479
+ synth_tracker_sync.track_lm_output(
480
+ messages=output_messages,
481
+ model_name=model_name,
482
+ finetune=finetune,
483
+ )
484
+
485
+
486
+ async def track_messages_async(
487
+ input_messages: List[Message],
488
+ output_messages: List[Message],
489
+ model_name: str,
490
+ model_params: Optional[ModelParams] = None,
491
+ finetune: bool = False,
492
+ ) -> None:
493
+ """Track both input and output messages in a conversation asynchronously.
494
+
495
+ Args:
496
+ input_messages: List of input messages (e.g., user messages)
497
+ output_messages: List of output messages (e.g., assistant responses)
498
+ model_name: Name of the language model being used
499
+ model_params: Optional parameters used for the model
500
+ finetune: Whether this conversation should be used for fine-tuning
501
+ """
502
+ # Track input messages
503
+ synth_tracker_async.track_lm(
504
+ messages=input_messages,
505
+ model_name=model_name,
506
+ model_params=model_params,
507
+ finetune=finetune,
508
+ )
509
+
510
+ # Track output messages
511
+ synth_tracker_async.track_lm_output(
512
+ messages=output_messages,
513
+ model_name=model_name,
514
+ finetune=finetune,
515
+ )