synth-ai 0.2.4.dev4__py3-none-any.whl → 0.2.4.dev5__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.
- synth_ai/environments/examples/__init__.py +1 -0
- synth_ai/environments/examples/crafter_classic/__init__.py +8 -0
- synth_ai/environments/examples/crafter_classic/config_logging.py +111 -0
- synth_ai/environments/examples/crafter_classic/debug_translation.py +0 -0
- synth_ai/environments/examples/crafter_classic/engine.py +575 -0
- synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +63 -0
- synth_ai/environments/examples/crafter_classic/engine_helpers/action_map.py +5 -0
- synth_ai/environments/examples/crafter_classic/engine_helpers/serialization.py +74 -0
- synth_ai/environments/examples/crafter_classic/engine_serialization_patch_v3.py +266 -0
- synth_ai/environments/examples/crafter_classic/environment.py +364 -0
- synth_ai/environments/examples/crafter_classic/taskset.py +233 -0
- synth_ai/environments/examples/crafter_classic/trace_hooks_v3.py +229 -0
- synth_ai/environments/examples/crafter_classic/world_config_patch_simple.py +298 -0
- synth_ai/environments/examples/crafter_custom/__init__.py +4 -0
- synth_ai/environments/examples/crafter_custom/crafter/__init__.py +7 -0
- synth_ai/environments/examples/crafter_custom/crafter/config.py +182 -0
- synth_ai/environments/examples/crafter_custom/crafter/constants.py +8 -0
- synth_ai/environments/examples/crafter_custom/crafter/engine.py +269 -0
- synth_ai/environments/examples/crafter_custom/crafter/env.py +266 -0
- synth_ai/environments/examples/crafter_custom/crafter/objects.py +418 -0
- synth_ai/environments/examples/crafter_custom/crafter/recorder.py +187 -0
- synth_ai/environments/examples/crafter_custom/crafter/worldgen.py +119 -0
- synth_ai/environments/examples/crafter_custom/dataset_builder.py +373 -0
- synth_ai/environments/examples/crafter_custom/environment.py +312 -0
- synth_ai/environments/examples/crafter_custom/run_dataset.py +305 -0
- synth_ai/environments/examples/enron/art_helpers/email_search_tools.py +156 -0
- synth_ai/environments/examples/enron/art_helpers/local_email_db.py +280 -0
- synth_ai/environments/examples/enron/art_helpers/types_enron.py +24 -0
- synth_ai/environments/examples/enron/engine.py +291 -0
- synth_ai/environments/examples/enron/environment.py +165 -0
- synth_ai/environments/examples/enron/taskset.py +112 -0
- synth_ai/environments/examples/minigrid/__init__.py +48 -0
- synth_ai/environments/examples/minigrid/engine.py +589 -0
- synth_ai/environments/examples/minigrid/environment.py +274 -0
- synth_ai/environments/examples/minigrid/environment_mapping.py +242 -0
- synth_ai/environments/examples/minigrid/puzzle_loader.py +416 -0
- synth_ai/environments/examples/minigrid/taskset.py +583 -0
- synth_ai/environments/examples/nethack/__init__.py +7 -0
- synth_ai/environments/examples/nethack/achievements.py +337 -0
- synth_ai/environments/examples/nethack/engine.py +738 -0
- synth_ai/environments/examples/nethack/environment.py +255 -0
- synth_ai/environments/examples/nethack/helpers/__init__.py +42 -0
- synth_ai/environments/examples/nethack/helpers/action_mapping.py +301 -0
- synth_ai/environments/examples/nethack/helpers/nle_wrapper.py +401 -0
- synth_ai/environments/examples/nethack/helpers/observation_utils.py +433 -0
- synth_ai/environments/examples/nethack/helpers/recording_wrapper.py +201 -0
- synth_ai/environments/examples/nethack/helpers/trajectory_recorder.py +268 -0
- synth_ai/environments/examples/nethack/helpers/visualization/replay_viewer.py +308 -0
- synth_ai/environments/examples/nethack/helpers/visualization/visualizer.py +430 -0
- synth_ai/environments/examples/nethack/taskset.py +323 -0
- synth_ai/environments/examples/red/__init__.py +7 -0
- synth_ai/environments/examples/red/config_logging.py +110 -0
- synth_ai/environments/examples/red/engine.py +693 -0
- synth_ai/environments/examples/red/engine_helpers/__init__.py +1 -0
- synth_ai/environments/examples/red/engine_helpers/memory_map.py +28 -0
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +275 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/__init__.py +142 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/adaptive_rewards.py +56 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/battle_rewards.py +283 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/composite_rewards.py +149 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/economy_rewards.py +137 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/efficiency_rewards.py +56 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/exploration_rewards.py +330 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/novelty_rewards.py +120 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_rewards.py +558 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/pokemon_rewards.py +312 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/social_rewards.py +147 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/story_rewards.py +246 -0
- synth_ai/environments/examples/red/engine_helpers/screen_analysis.py +367 -0
- synth_ai/environments/examples/red/engine_helpers/state_extraction.py +139 -0
- synth_ai/environments/examples/red/environment.py +235 -0
- synth_ai/environments/examples/red/taskset.py +77 -0
- synth_ai/environments/examples/sokoban/__init__.py +1 -0
- synth_ai/environments/examples/sokoban/engine.py +675 -0
- synth_ai/environments/examples/sokoban/engine_helpers/__init__.py +1 -0
- synth_ai/environments/examples/sokoban/engine_helpers/room_utils.py +656 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/__init__.py +17 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/__init__.py +3 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/boxoban_env.py +129 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/render_utils.py +370 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/room_utils.py +331 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env.py +305 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_fixed_targets.py +66 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_pull.py +114 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_two_player.py +122 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_variations.py +394 -0
- synth_ai/environments/examples/sokoban/environment.py +228 -0
- synth_ai/environments/examples/sokoban/generate_verified_puzzles.py +438 -0
- synth_ai/environments/examples/sokoban/puzzle_loader.py +311 -0
- synth_ai/environments/examples/sokoban/taskset.py +425 -0
- synth_ai/environments/examples/tictactoe/__init__.py +1 -0
- synth_ai/environments/examples/tictactoe/engine.py +368 -0
- synth_ai/environments/examples/tictactoe/environment.py +239 -0
- synth_ai/environments/examples/tictactoe/taskset.py +214 -0
- synth_ai/environments/examples/verilog/__init__.py +10 -0
- synth_ai/environments/examples/verilog/engine.py +328 -0
- synth_ai/environments/examples/verilog/environment.py +349 -0
- synth_ai/environments/examples/verilog/taskset.py +418 -0
- {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev5.dist-info}/METADATA +1 -1
- {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev5.dist-info}/RECORD +104 -6
- {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev5.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev5.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev5.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,349 @@
|
|
1
|
+
from typing import List, Optional, Any, Dict, Union
|
2
|
+
from pydantic import BaseModel
|
3
|
+
|
4
|
+
from synth_ai.environments.examples.verilog.engine import (
|
5
|
+
VerilogEngine,
|
6
|
+
VerilogPrivateState,
|
7
|
+
VerilogPublicState,
|
8
|
+
VerilogEngineSnapshot,
|
9
|
+
)
|
10
|
+
from synth_ai.environments.environment.shared_engine import (
|
11
|
+
GetObservationCallable,
|
12
|
+
InternalObservation,
|
13
|
+
)
|
14
|
+
from synth_ai.environments.stateful.core import StatefulEnvironment
|
15
|
+
from synth_ai.environments.tasks.core import TaskInstance
|
16
|
+
from synth_ai.environments.environment.tools import (
|
17
|
+
AbstractTool,
|
18
|
+
EnvToolCall,
|
19
|
+
ToolResult,
|
20
|
+
TOOL_REGISTRY,
|
21
|
+
register_tool,
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
# Tool Input Schemas
|
26
|
+
class WriteFileInput(BaseModel):
|
27
|
+
path: str
|
28
|
+
content: str
|
29
|
+
|
30
|
+
|
31
|
+
class CompileInput(BaseModel):
|
32
|
+
sources: Optional[List[str]] = None
|
33
|
+
testbench: Optional[str] = None
|
34
|
+
|
35
|
+
|
36
|
+
class SimulateInput(BaseModel):
|
37
|
+
binary: Optional[str] = None
|
38
|
+
|
39
|
+
|
40
|
+
class SubmitInput(BaseModel):
|
41
|
+
pass # No arguments needed for submit
|
42
|
+
|
43
|
+
|
44
|
+
# Tool Implementations
|
45
|
+
class VerilogWriteFileTool(AbstractTool):
|
46
|
+
name = "write_file"
|
47
|
+
description = "Write content to a Verilog file"
|
48
|
+
call_schema = WriteFileInput
|
49
|
+
result_schema = ToolResult
|
50
|
+
|
51
|
+
def __init__(self, engine: VerilogEngine):
|
52
|
+
self.engine = engine
|
53
|
+
|
54
|
+
async def __call__(self, call: EnvToolCall) -> ToolResult:
|
55
|
+
try:
|
56
|
+
validated_args = self.call_schema(**call.args)
|
57
|
+
result = await self.engine.write_file(validated_args.path, validated_args.content)
|
58
|
+
return ToolResult(ok=result["ok"], payload=result)
|
59
|
+
except Exception as e:
|
60
|
+
return ToolResult(ok=False, error=str(e))
|
61
|
+
|
62
|
+
|
63
|
+
class VerilogCompileTool(AbstractTool):
|
64
|
+
name = "compile"
|
65
|
+
description = "Compile Verilog sources with iverilog"
|
66
|
+
call_schema = CompileInput
|
67
|
+
result_schema = ToolResult
|
68
|
+
|
69
|
+
def __init__(self, engine: VerilogEngine):
|
70
|
+
self.engine = engine
|
71
|
+
|
72
|
+
async def __call__(self, call: EnvToolCall) -> ToolResult:
|
73
|
+
try:
|
74
|
+
validated_args = self.call_schema(**call.args)
|
75
|
+
result = await self.engine.compile(validated_args.sources, validated_args.testbench)
|
76
|
+
return ToolResult(ok=result["ok"], payload=result)
|
77
|
+
except Exception as e:
|
78
|
+
return ToolResult(ok=False, error=str(e))
|
79
|
+
|
80
|
+
|
81
|
+
class VerilogSimulateTool(AbstractTool):
|
82
|
+
name = "simulate"
|
83
|
+
description = "Run vvp on compiled binary"
|
84
|
+
call_schema = SimulateInput
|
85
|
+
result_schema = ToolResult
|
86
|
+
|
87
|
+
def __init__(self, engine: VerilogEngine):
|
88
|
+
self.engine = engine
|
89
|
+
|
90
|
+
async def __call__(self, call: EnvToolCall) -> ToolResult:
|
91
|
+
try:
|
92
|
+
validated_args = self.call_schema(**call.args)
|
93
|
+
result = await self.engine.simulate(validated_args.binary)
|
94
|
+
return ToolResult(ok=result["ok"], payload=result)
|
95
|
+
except Exception as e:
|
96
|
+
return ToolResult(ok=False, error=str(e))
|
97
|
+
|
98
|
+
|
99
|
+
class VerilogSubmitTool(AbstractTool):
|
100
|
+
name = "submit"
|
101
|
+
description = "Submit solution for grading"
|
102
|
+
call_schema = SubmitInput
|
103
|
+
result_schema = ToolResult
|
104
|
+
|
105
|
+
def __init__(self, engine: VerilogEngine):
|
106
|
+
self.engine = engine
|
107
|
+
|
108
|
+
async def __call__(self, call: EnvToolCall) -> ToolResult:
|
109
|
+
try:
|
110
|
+
result = await self.engine.submit()
|
111
|
+
return ToolResult(ok=result["ok"], payload=result)
|
112
|
+
except Exception as e:
|
113
|
+
return ToolResult(ok=False, error=str(e))
|
114
|
+
|
115
|
+
|
116
|
+
class VerilogObservationCallable(GetObservationCallable):
|
117
|
+
async def get_observation(
|
118
|
+
self, pub: VerilogPublicState, priv: VerilogPrivateState
|
119
|
+
) -> InternalObservation:
|
120
|
+
files_summary = f"{len(pub.files)} Verilog files available"
|
121
|
+
if pub.files:
|
122
|
+
files_summary += f": {', '.join(pub.files.keys())}"
|
123
|
+
|
124
|
+
compile_status = ""
|
125
|
+
if pub.last_compile_output is not None:
|
126
|
+
# Check for common error indicators in compile output
|
127
|
+
output_lower = pub.last_compile_output.lower()
|
128
|
+
is_success = not any(
|
129
|
+
indicator in output_lower for indicator in ["error", "failed", "syntax"]
|
130
|
+
)
|
131
|
+
if is_success:
|
132
|
+
compile_status = "Last compile: Success"
|
133
|
+
else:
|
134
|
+
# Include the actual error message to help the agent debug
|
135
|
+
compile_status = f"Last compile: Failed\n{pub.last_compile_output}"
|
136
|
+
|
137
|
+
simulate_status = ""
|
138
|
+
if pub.last_simulate_output:
|
139
|
+
# Use same success detection logic as in engine
|
140
|
+
stdout = pub.last_simulate_output
|
141
|
+
passed = (
|
142
|
+
"ALL_TESTS_PASSED" in stdout
|
143
|
+
or ("Mismatches: 0 " in stdout and "samples" in stdout)
|
144
|
+
or ("no mismatches" in stdout.lower() and "errors" not in stdout.lower())
|
145
|
+
)
|
146
|
+
simulate_status = f"Last simulation: {'Passed' if passed else 'Failed'}"
|
147
|
+
|
148
|
+
observation: Dict[str, Any] = {
|
149
|
+
"files": pub.files,
|
150
|
+
"build_dir": pub.build_dir,
|
151
|
+
"files_summary": files_summary,
|
152
|
+
"task_completed": pub.task_completed,
|
153
|
+
"reward_last": priv.reward_last,
|
154
|
+
"total_reward": priv.total_reward,
|
155
|
+
"terminated": priv.terminated,
|
156
|
+
"compile_status": compile_status,
|
157
|
+
"simulate_status": simulate_status,
|
158
|
+
}
|
159
|
+
return observation # type: ignore[return-value]
|
160
|
+
|
161
|
+
|
162
|
+
class VerilogEnvironment(StatefulEnvironment):
|
163
|
+
def __init__(
|
164
|
+
self,
|
165
|
+
task_instance: TaskInstance,
|
166
|
+
custom_obs: Optional[GetObservationCallable] = None,
|
167
|
+
):
|
168
|
+
self.name = "VerilogEval"
|
169
|
+
self.task_instance = task_instance
|
170
|
+
self.custom_observation_callable = custom_obs or VerilogObservationCallable()
|
171
|
+
self.engine: VerilogEngine = VerilogEngine(task_instance)
|
172
|
+
|
173
|
+
# Initialize tools
|
174
|
+
self._tools_instances = {
|
175
|
+
"write_file": VerilogWriteFileTool(self.engine),
|
176
|
+
"compile": VerilogCompileTool(self.engine),
|
177
|
+
"simulate": VerilogSimulateTool(self.engine),
|
178
|
+
"submit": VerilogSubmitTool(self.engine),
|
179
|
+
}
|
180
|
+
|
181
|
+
# Register tools
|
182
|
+
for tool_name, tool_instance in self._tools_instances.items():
|
183
|
+
if tool_name not in TOOL_REGISTRY:
|
184
|
+
register_tool(tool_instance)
|
185
|
+
|
186
|
+
async def initialize(self) -> InternalObservation:
|
187
|
+
priv, pub = await self.engine._reset_engine()
|
188
|
+
return await self._to_observation(priv, pub)
|
189
|
+
|
190
|
+
async def terminate(self) -> InternalObservation:
|
191
|
+
# Get current state and mark as terminated
|
192
|
+
try:
|
193
|
+
# Try to get current state from engine
|
194
|
+
current_files = self.engine._get_file_contents()
|
195
|
+
build_dir = str(self.engine.build_dir) if self.engine.build_dir else ""
|
196
|
+
|
197
|
+
priv = VerilogPrivateState(
|
198
|
+
reward_last=0.0,
|
199
|
+
total_reward=self.engine._total_reward,
|
200
|
+
terminated=True,
|
201
|
+
truncated=False,
|
202
|
+
)
|
203
|
+
|
204
|
+
pub = VerilogPublicState(files=current_files, build_dir=build_dir, task_completed=False)
|
205
|
+
except Exception:
|
206
|
+
# Fallback if engine state is not accessible
|
207
|
+
priv = VerilogPrivateState(
|
208
|
+
reward_last=0.0, total_reward=0.0, terminated=True, truncated=False
|
209
|
+
)
|
210
|
+
|
211
|
+
pub = VerilogPublicState(files={}, build_dir="", task_completed=False)
|
212
|
+
|
213
|
+
obs = await self._to_observation(priv, pub)
|
214
|
+
if isinstance(obs, dict):
|
215
|
+
obs["terminated"] = True
|
216
|
+
obs["message"] = "Environment terminated."
|
217
|
+
return obs
|
218
|
+
|
219
|
+
def validate_tool_calls(
|
220
|
+
self,
|
221
|
+
tool_calls: Union[
|
222
|
+
EnvToolCall,
|
223
|
+
List[Dict[str, Any]],
|
224
|
+
List[List[Dict[str, Any]]],
|
225
|
+
Dict[str, Any],
|
226
|
+
],
|
227
|
+
) -> EnvToolCall:
|
228
|
+
"""Normalize and validate tool calls to a single EnvToolCall."""
|
229
|
+
raw_call_data: Dict[str, Any]
|
230
|
+
|
231
|
+
if isinstance(tool_calls, list):
|
232
|
+
if not tool_calls:
|
233
|
+
raise ValueError("Received empty list of tool calls.")
|
234
|
+
first_item = tool_calls[0]
|
235
|
+
if isinstance(first_item, list):
|
236
|
+
if not first_item:
|
237
|
+
raise ValueError("Received empty inner list of tool calls.")
|
238
|
+
raw_call_data = first_item[0]
|
239
|
+
elif isinstance(first_item, dict):
|
240
|
+
raw_call_data = first_item
|
241
|
+
elif isinstance(first_item, EnvToolCall):
|
242
|
+
return first_item
|
243
|
+
else:
|
244
|
+
raise TypeError(f"Unexpected type in tool_calls list: {type(first_item)}")
|
245
|
+
elif isinstance(tool_calls, dict):
|
246
|
+
raw_call_data = tool_calls
|
247
|
+
elif isinstance(tool_calls, EnvToolCall):
|
248
|
+
return tool_calls
|
249
|
+
else:
|
250
|
+
raise TypeError(f"Unexpected type for tool_calls: {type(tool_calls)}")
|
251
|
+
|
252
|
+
if not isinstance(raw_call_data, dict):
|
253
|
+
raise TypeError(f"Processed call data is not a dict: {type(raw_call_data)}")
|
254
|
+
|
255
|
+
# Convert dict to EnvToolCall instance
|
256
|
+
tool_name = raw_call_data.get("tool")
|
257
|
+
tool_args = raw_call_data.get("args", {})
|
258
|
+
|
259
|
+
valid_tools = {"write_file", "compile", "simulate", "submit"}
|
260
|
+
if tool_name not in valid_tools:
|
261
|
+
raise ValueError(f"Unknown tool: {tool_name}. Expected one of: {valid_tools}")
|
262
|
+
|
263
|
+
return EnvToolCall(tool=tool_name, args=tool_args)
|
264
|
+
|
265
|
+
async def step(
|
266
|
+
self,
|
267
|
+
tool_calls: Union[
|
268
|
+
EnvToolCall,
|
269
|
+
List[Dict[str, Any]],
|
270
|
+
List[List[Dict[str, Any]]],
|
271
|
+
Dict[str, Any],
|
272
|
+
],
|
273
|
+
) -> InternalObservation:
|
274
|
+
agent_call = self.validate_tool_calls(tool_calls)
|
275
|
+
|
276
|
+
# Get the appropriate tool
|
277
|
+
tool_instance = self._tools_instances.get(agent_call.tool)
|
278
|
+
if not tool_instance:
|
279
|
+
tool_instance = TOOL_REGISTRY.get(agent_call.tool)
|
280
|
+
if not tool_instance:
|
281
|
+
raise ValueError(f"Tool '{agent_call.tool}' not found.")
|
282
|
+
|
283
|
+
# Execute the tool
|
284
|
+
tool_result: ToolResult = await tool_instance(agent_call)
|
285
|
+
|
286
|
+
# Update engine state with tool result
|
287
|
+
if tool_result.payload:
|
288
|
+
action_result = tool_result.payload
|
289
|
+
elif not tool_result.ok:
|
290
|
+
action_result = {
|
291
|
+
"ok": False,
|
292
|
+
"error": tool_result.error,
|
293
|
+
"type": agent_call.tool,
|
294
|
+
}
|
295
|
+
else:
|
296
|
+
action_result = {}
|
297
|
+
|
298
|
+
priv_state, pub_state = await self.engine._step_engine(action_result)
|
299
|
+
|
300
|
+
return await self._to_observation(priv_state, pub_state)
|
301
|
+
|
302
|
+
async def checkpoint(self) -> InternalObservation:
|
303
|
+
engine_snapshot: VerilogEngineSnapshot = await self.engine._serialize_engine()
|
304
|
+
|
305
|
+
# Get current state for observation
|
306
|
+
try:
|
307
|
+
current_files = self.engine._get_file_contents()
|
308
|
+
build_dir = str(self.engine.build_dir) if self.engine.build_dir else ""
|
309
|
+
|
310
|
+
priv = VerilogPrivateState(
|
311
|
+
reward_last=0.0,
|
312
|
+
total_reward=self.engine._total_reward,
|
313
|
+
terminated=False,
|
314
|
+
truncated=False,
|
315
|
+
)
|
316
|
+
|
317
|
+
pub = VerilogPublicState(files=current_files, build_dir=build_dir, task_completed=False)
|
318
|
+
|
319
|
+
obs_data = await self._to_observation(priv, pub)
|
320
|
+
except Exception:
|
321
|
+
obs_data = {"message": "Checkpoint created"}
|
322
|
+
|
323
|
+
if isinstance(obs_data, dict):
|
324
|
+
obs_data["engine_snapshot_data"] = engine_snapshot.model_dump()
|
325
|
+
|
326
|
+
return obs_data
|
327
|
+
|
328
|
+
async def _to_observation(
|
329
|
+
self,
|
330
|
+
priv: VerilogPrivateState,
|
331
|
+
pub: VerilogPublicState,
|
332
|
+
extra_obs: Optional[Dict[str, Any]] = None,
|
333
|
+
) -> InternalObservation:
|
334
|
+
observation = await self.custom_observation_callable.get_observation(pub, priv)
|
335
|
+
if extra_obs and isinstance(observation, dict):
|
336
|
+
observation.update(extra_obs)
|
337
|
+
return observation
|
338
|
+
|
339
|
+
async def _serialize_engine(self) -> VerilogEngineSnapshot:
|
340
|
+
return await self.engine._serialize_engine()
|
341
|
+
|
342
|
+
@classmethod
|
343
|
+
async def _deserialize_engine(
|
344
|
+
cls, snapshot: VerilogEngineSnapshot, task_instance: TaskInstance
|
345
|
+
) -> "VerilogEnvironment":
|
346
|
+
eng = await VerilogEngine._deserialize_engine(snapshot)
|
347
|
+
env = cls(task_instance)
|
348
|
+
env.engine = eng
|
349
|
+
return env
|