cyberosa commited on
Commit
acc99f2
·
1 Parent(s): 40ac692

cleaning and updating dashboards

Browse files
data/all_trades_profitability.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:76583ca11eb853af0f328a3739379afb12919cdf4751a8df4fc0d710e09ce77e
3
- size 2585132
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:906e77fed8d2af6d7a4f4acf73640ce6aa3e3d4357e01c7b00af1c180f3b6eaf
3
+ size 2460157
data/delivers.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:83a8e368360e97a07a7b7e1bf4b68cd4153a9cd8f2c3a37218ca2c25fa0004a7
3
- size 533832215
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2d975d5fc2c3c7c50bec7136dffa135aef50fe3802bd1650cd46f236675318af
3
+ size 510466826
data/fpmmTrades.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c3783e00d33252efd8cec813cd9ede010d089f984b5189b3d2e03726ea4bc16c
3
- size 6743682
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:781a9625add04d8337bb3909befb6c0d4c39f3e0c9a5c47c1fb9398a96ba36ae
3
+ size 6482896
data/fpmms.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:b080d92b95e9cb78c83a458aa9fafb1b22079c364dde7837ab89bcfd33c50481
3
- size 335554
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a2c07ed22be9463c8465d34717222f1553c5890254b350fb07aec2604e925795
3
+ size 336922
data/requests.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c531cdd253c89a513fc52bf873fe8795e0a44ce6c033c89f07989d4f0932e424
3
- size 18043976
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bff6dbad037f5f9c3cee3631c126ba0f6e582b32b7e3fb75d79fc60a43a9dadb
3
+ size 11547978
data/summary_profitability.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:4005bc0e5b1f940da6108a449f8a2a1feed75183dea917f5dcaac1f9cc64f6de
3
- size 40468
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c5db58ef61b7a256437ee87238249cd1da9d229a4ca5f9af79b02efe61fa73cc
3
+ size 40127
data/t_map.pkl CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:12faddc220fb5c6f9583b1029c19cb5a210ff3ae59f6fdef8a74667a7b36d53c
3
- size 8678809
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:29c60bf39a93cad87fd54b7a87407cb8f50bb2cd2122e993762cec36d76e76fb
3
+ size 8982599
data/tools.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:166e8ec777aaa5fa8bfa2f62f22e753b5b2f32b2f8c4138f81282e99a0c03b69
3
- size 536907540
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf3ed51b3e32b32e3cd9bba607afbc1e6d67583e6ca9126df68585c339964a8a
3
+ size 378117330
scripts/get_mech_info.py CHANGED
@@ -48,6 +48,8 @@ def fetch_block_number(timestamp_from: int, timestamp_to: int) -> dict:
48
  result_json = response.json()
49
  print(f"Response of the query={result_json}")
50
  blocks = result_json.get("data", {}).get("blocks", "")
 
 
51
  return blocks[0]
52
 
53
 
 
48
  result_json = response.json()
49
  print(f"Response of the query={result_json}")
50
  blocks = result_json.get("data", {}).get("blocks", "")
51
+ if len(blocks) == 0:
52
+ raise ValueError(f"The query {query} did not return any results")
53
  return blocks[0]
54
 
55
 
scripts/tools.py CHANGED
@@ -17,23 +17,18 @@
17
  #
18
  # ------------------------------------------------------------------------------
19
 
20
- import json
21
  import os.path
22
  import re
23
  import time
24
  import random
25
- from dataclasses import dataclass
26
- from enum import Enum
27
  from typing import (
28
  Optional,
29
  List,
30
  Dict,
31
- Any,
32
  Union,
33
  )
34
  import pandas as pd
35
  import requests
36
- from json.decoder import JSONDecodeError
37
  from eth_typing import ChecksumAddress
38
  from eth_utils import to_checksum_address
39
  from requests.adapters import HTTPAdapter
@@ -62,6 +57,15 @@ from utils import (
62
  limit_text,
63
  DATA_DIR,
64
  REQUEST_ID_FIELD,
 
 
 
 
 
 
 
 
 
65
  )
66
 
67
  CONTRACTS_PATH = "contracts"
@@ -78,13 +82,6 @@ BLOCK_DATA_NUMBER = "number"
78
  BLOCKS_CHUNK_SIZE = 10_000
79
  EVENT_ARGUMENTS = "args"
80
  DATA = "data"
81
- REQUEST_ID = "requestId"
82
- REQUEST_SENDER = "sender"
83
- PROMPT_FIELD = "prompt"
84
- CID_PREFIX = "f01701220"
85
- HTTP = "http://"
86
- HTTPS = HTTP[:4] + "s" + HTTP[4:]
87
- IPFS_ADDRESS = f"{HTTPS}gateway.autonolas.tech/ipfs/"
88
  IPFS_LINKS_SERIES_NAME = "ipfs_links"
89
  BACKOFF_FACTOR = 1
90
  STATUS_FORCELIST = [404, 500, 502, 503, 504]
@@ -96,7 +93,6 @@ N_IPFS_RETRIES = 1
96
  N_RPC_RETRIES = 100
97
  RPC_POLL_INTERVAL = 0.05
98
  IPFS_POLL_INTERVAL = 0.05
99
- FORMAT_UPDATE_BLOCK_NUMBER = 30411638
100
  IRRELEVANT_TOOLS = [
101
  "openai-text-davinci-002",
102
  "openai-text-davinci-003",
@@ -117,178 +113,6 @@ NUM_WORKERS = 10
117
  GET_CONTENTS_BATCH_SIZE = 1000
118
 
119
 
120
- class MechEventName(Enum):
121
- """The mech's event names."""
122
-
123
- REQUEST = "Request"
124
- DELIVER = "Deliver"
125
-
126
-
127
- @dataclass
128
- class MechEvent:
129
- """A mech's on-chain event representation."""
130
-
131
- for_block: int
132
- requestId: int
133
- data: bytes
134
- sender: str
135
-
136
- def _ipfs_link(self) -> Optional[str]:
137
- """Get the ipfs link for the data."""
138
- return f"{IPFS_ADDRESS}{CID_PREFIX}{self.data.hex()}"
139
-
140
- @property
141
- def ipfs_request_link(self) -> Optional[str]:
142
- """Get the IPFS link for the request."""
143
- return f"{self._ipfs_link()}/metadata.json"
144
-
145
- @property
146
- def ipfs_deliver_link(self) -> Optional[str]:
147
- """Get the IPFS link for the deliver."""
148
- if self.requestId is None:
149
- return None
150
- return f"{self._ipfs_link()}/{self.requestId}"
151
-
152
- def ipfs_link(self, event_name: MechEventName) -> Optional[str]:
153
- """Get the ipfs link based on the event."""
154
- if event_name == MechEventName.REQUEST:
155
- if self.for_block < FORMAT_UPDATE_BLOCK_NUMBER:
156
- return self._ipfs_link()
157
- return self.ipfs_request_link
158
- if event_name == MechEventName.DELIVER:
159
- return self.ipfs_deliver_link
160
- return None
161
-
162
-
163
- @dataclass(init=False)
164
- class MechRequest:
165
- """A structure for a request to a mech."""
166
-
167
- request_id: Optional[int]
168
- request_block: Optional[int]
169
- prompt_request: Optional[str]
170
- tool: Optional[str]
171
- nonce: Optional[str]
172
- trader_address: Optional[str]
173
-
174
- def __init__(self, **kwargs: Any) -> None:
175
- """Initialize the request ignoring extra keys."""
176
- self.request_id = int(kwargs.pop(REQUEST_ID, 0))
177
- self.request_block = int(kwargs.pop(BLOCK_FIELD, 0))
178
- self.prompt_request = kwargs.pop(PROMPT_FIELD, None)
179
- self.tool = kwargs.pop("tool", None)
180
- self.nonce = kwargs.pop("nonce", None)
181
- self.trader_address = kwargs.pop("sender", None)
182
-
183
-
184
- @dataclass(init=False)
185
- class PredictionResponse:
186
- """A response of a prediction."""
187
-
188
- p_yes: float
189
- p_no: float
190
- confidence: float
191
- info_utility: float
192
- vote: Optional[str]
193
- win_probability: Optional[float]
194
-
195
- def __init__(self, **kwargs: Any) -> None:
196
- """Initialize the mech's prediction ignoring extra keys."""
197
- try:
198
- self.p_yes = float(kwargs.pop("p_yes"))
199
- self.p_no = float(kwargs.pop("p_no"))
200
- self.confidence = float(kwargs.pop("confidence"))
201
- self.info_utility = float(kwargs.pop("info_utility"))
202
- self.win_probability = 0
203
-
204
- # Validate probabilities
205
- probabilities = {
206
- "p_yes": self.p_yes,
207
- "p_no": self.p_no,
208
- "confidence": self.confidence,
209
- "info_utility": self.info_utility,
210
- }
211
-
212
- for name, prob in probabilities.items():
213
- if not 0 <= prob <= 1:
214
- raise ValueError(f"{name} probability is out of bounds: {prob}")
215
-
216
- if self.p_yes + self.p_no != 1:
217
- raise ValueError(
218
- f"Sum of p_yes and p_no is not 1: {self.p_yes} + {self.p_no}"
219
- )
220
-
221
- self.vote = self.get_vote()
222
- self.win_probability = self.get_win_probability()
223
-
224
- except KeyError as e:
225
- raise KeyError(f"Missing key in PredictionResponse: {e}")
226
- except ValueError as e:
227
- raise ValueError(f"Invalid value in PredictionResponse: {e}")
228
-
229
- def get_vote(self) -> Optional[str]:
230
- """Return the vote."""
231
- if self.p_no == self.p_yes:
232
- return None
233
- if self.p_no > self.p_yes:
234
- return "No"
235
- return "Yes"
236
-
237
- def get_win_probability(self) -> Optional[float]:
238
- """Return the probability estimation for winning with vote."""
239
- return max(self.p_no, self.p_yes)
240
-
241
-
242
- @dataclass(init=False)
243
- class MechResponse:
244
- """A structure for the response of a mech."""
245
-
246
- request_id: int
247
- deliver_block: Optional[int]
248
- result: Optional[PredictionResponse]
249
- error: Optional[str]
250
- error_message: Optional[str]
251
- prompt_response: Optional[str]
252
- mech_address: Optional[str]
253
-
254
- def __init__(self, **kwargs: Any) -> None:
255
- """Initialize the mech's response ignoring extra keys."""
256
- self.error = kwargs.get("error", None)
257
- self.request_id = int(kwargs.get(REQUEST_ID, 0))
258
- self.deliver_block = int(kwargs.get(BLOCK_FIELD, 0))
259
- self.result = kwargs.get("result", None)
260
- self.prompt_response = kwargs.get(PROMPT_FIELD, None)
261
- self.mech_address = kwargs.get("sender", None)
262
-
263
- if self.result != "Invalid response":
264
- self.error_message = kwargs.get("error_message", None)
265
-
266
- try:
267
- if isinstance(self.result, str):
268
- kwargs = json.loads(self.result)
269
- self.result = PredictionResponse(**kwargs)
270
- self.error = 0
271
-
272
- except JSONDecodeError:
273
- self.error_message = "Response parsing error"
274
- self.error = 1
275
-
276
- except Exception as e:
277
- self.error_message = str(e)
278
- self.error = 1
279
-
280
- else:
281
- self.error_message = "Invalid response from tool"
282
- self.error = 1
283
- self.result = None
284
-
285
-
286
- EVENT_TO_MECH_STRUCT = {
287
- MechEventName.REQUEST: MechRequest,
288
- MechEventName.DELIVER: MechResponse,
289
- }
290
-
291
-
292
  def get_events(
293
  w3: Web3,
294
  event: str,
@@ -554,7 +378,8 @@ def etl(
554
  rpcs: List[str],
555
  filename: Optional[str] = None,
556
  ) -> pd.DataFrame:
557
- """Fetch from on-chain events, process, store and return the tools' results on all the questions as a Dataframe."""
 
558
  w3s = [Web3(HTTPProvider(r)) for r in rpcs]
559
  session = create_session()
560
  event_to_transformer = {
 
17
  #
18
  # ------------------------------------------------------------------------------
19
 
 
20
  import os.path
21
  import re
22
  import time
23
  import random
 
 
24
  from typing import (
25
  Optional,
26
  List,
27
  Dict,
 
28
  Union,
29
  )
30
  import pandas as pd
31
  import requests
 
32
  from eth_typing import ChecksumAddress
33
  from eth_utils import to_checksum_address
34
  from requests.adapters import HTTPAdapter
 
57
  limit_text,
58
  DATA_DIR,
59
  REQUEST_ID_FIELD,
60
+ MechEvent,
61
+ MechEventName,
62
+ MechRequest,
63
+ MechResponse,
64
+ EVENT_TO_MECH_STRUCT,
65
+ REQUEST_ID,
66
+ HTTP,
67
+ HTTPS,
68
+ REQUEST_SENDER,
69
  )
70
 
71
  CONTRACTS_PATH = "contracts"
 
82
  BLOCKS_CHUNK_SIZE = 10_000
83
  EVENT_ARGUMENTS = "args"
84
  DATA = "data"
 
 
 
 
 
 
 
85
  IPFS_LINKS_SERIES_NAME = "ipfs_links"
86
  BACKOFF_FACTOR = 1
87
  STATUS_FORCELIST = [404, 500, 502, 503, 504]
 
93
  N_RPC_RETRIES = 100
94
  RPC_POLL_INTERVAL = 0.05
95
  IPFS_POLL_INTERVAL = 0.05
 
96
  IRRELEVANT_TOOLS = [
97
  "openai-text-davinci-002",
98
  "openai-text-davinci-003",
 
113
  GET_CONTENTS_BATCH_SIZE = 1000
114
 
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  def get_events(
117
  w3: Web3,
118
  event: str,
 
378
  rpcs: List[str],
379
  filename: Optional[str] = None,
380
  ) -> pd.DataFrame:
381
+ """Fetch from on-chain events, process, store and return the tools' results on
382
+ all the questions as a Dataframe."""
383
  w3s = [Web3(HTTPProvider(r)) for r in rpcs]
384
  session = create_session()
385
  event_to_transformer = {
scripts/utils.py CHANGED
@@ -1,12 +1,15 @@
1
  import sys
 
2
  import os
3
  import time
4
  from tqdm import tqdm
5
- from tools import MechEventName
6
- from typing import List
7
  import pandas as pd
8
  import gc
 
9
  from pathlib import Path
 
 
10
 
11
  REDUCE_FACTOR = 0.25
12
  SLEEP = 0.5
@@ -15,6 +18,186 @@ SCRIPTS_DIR = Path(__file__).parent
15
  ROOT_DIR = SCRIPTS_DIR.parent
16
  DATA_DIR = ROOT_DIR / "data"
17
  BLOCK_FIELD = "block"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
 
20
  def parse_args() -> str:
 
1
  import sys
2
+ import json
3
  import os
4
  import time
5
  from tqdm import tqdm
6
+ from typing import List, Any, Optional
 
7
  import pandas as pd
8
  import gc
9
+ from dataclasses import dataclass
10
  from pathlib import Path
11
+ from enum import Enum
12
+ from json.decoder import JSONDecodeError
13
 
14
  REDUCE_FACTOR = 0.25
15
  SLEEP = 0.5
 
18
  ROOT_DIR = SCRIPTS_DIR.parent
19
  DATA_DIR = ROOT_DIR / "data"
20
  BLOCK_FIELD = "block"
21
+ CID_PREFIX = "f01701220"
22
+ REQUEST_ID = "requestId"
23
+ REQUEST_SENDER = "sender"
24
+ PROMPT_FIELD = "prompt"
25
+ HTTP = "http://"
26
+ HTTPS = HTTP[:4] + "s" + HTTP[4:]
27
+ IPFS_ADDRESS = f"{HTTPS}gateway.autonolas.tech/ipfs/"
28
+ FORMAT_UPDATE_BLOCK_NUMBER = 30411638
29
+
30
+
31
+ class MechEventName(Enum):
32
+ """The mech's event names."""
33
+
34
+ REQUEST = "Request"
35
+ DELIVER = "Deliver"
36
+
37
+
38
+ @dataclass
39
+ class MechEvent:
40
+ """A mech's on-chain event representation."""
41
+
42
+ for_block: int
43
+ requestId: int
44
+ data: bytes
45
+ sender: str
46
+
47
+ def _ipfs_link(self) -> Optional[str]:
48
+ """Get the ipfs link for the data."""
49
+ return f"{IPFS_ADDRESS}{CID_PREFIX}{self.data.hex()}"
50
+
51
+ @property
52
+ def ipfs_request_link(self) -> Optional[str]:
53
+ """Get the IPFS link for the request."""
54
+ return f"{self._ipfs_link()}/metadata.json"
55
+
56
+ @property
57
+ def ipfs_deliver_link(self) -> Optional[str]:
58
+ """Get the IPFS link for the deliver."""
59
+ if self.requestId is None:
60
+ return None
61
+ return f"{self._ipfs_link()}/{self.requestId}"
62
+
63
+ def ipfs_link(self, event_name: MechEventName) -> Optional[str]:
64
+ """Get the ipfs link based on the event."""
65
+ if event_name == MechEventName.REQUEST:
66
+ if self.for_block < FORMAT_UPDATE_BLOCK_NUMBER:
67
+ return self._ipfs_link()
68
+ return self.ipfs_request_link
69
+ if event_name == MechEventName.DELIVER:
70
+ return self.ipfs_deliver_link
71
+ return None
72
+
73
+
74
+ @dataclass(init=False)
75
+ class MechRequest:
76
+ """A structure for a request to a mech."""
77
+
78
+ request_id: Optional[int]
79
+ request_block: Optional[int]
80
+ prompt_request: Optional[str]
81
+ tool: Optional[str]
82
+ nonce: Optional[str]
83
+ trader_address: Optional[str]
84
+
85
+ def __init__(self, **kwargs: Any) -> None:
86
+ """Initialize the request ignoring extra keys."""
87
+ self.request_id = int(kwargs.pop(REQUEST_ID, 0))
88
+ self.request_block = int(kwargs.pop(BLOCK_FIELD, 0))
89
+ self.prompt_request = kwargs.pop(PROMPT_FIELD, None)
90
+ self.tool = kwargs.pop("tool", None)
91
+ self.nonce = kwargs.pop("nonce", None)
92
+ self.trader_address = kwargs.pop("sender", None)
93
+
94
+
95
+ @dataclass(init=False)
96
+ class PredictionResponse:
97
+ """A response of a prediction."""
98
+
99
+ p_yes: float
100
+ p_no: float
101
+ confidence: float
102
+ info_utility: float
103
+ vote: Optional[str]
104
+ win_probability: Optional[float]
105
+
106
+ def __init__(self, **kwargs: Any) -> None:
107
+ """Initialize the mech's prediction ignoring extra keys."""
108
+ try:
109
+ self.p_yes = float(kwargs.pop("p_yes"))
110
+ self.p_no = float(kwargs.pop("p_no"))
111
+ self.confidence = float(kwargs.pop("confidence"))
112
+ self.info_utility = float(kwargs.pop("info_utility"))
113
+ self.win_probability = 0
114
+
115
+ # Validate probabilities
116
+ probabilities = {
117
+ "p_yes": self.p_yes,
118
+ "p_no": self.p_no,
119
+ "confidence": self.confidence,
120
+ "info_utility": self.info_utility,
121
+ }
122
+
123
+ for name, prob in probabilities.items():
124
+ if not 0 <= prob <= 1:
125
+ raise ValueError(f"{name} probability is out of bounds: {prob}")
126
+
127
+ if self.p_yes + self.p_no != 1:
128
+ raise ValueError(
129
+ f"Sum of p_yes and p_no is not 1: {self.p_yes} + {self.p_no}"
130
+ )
131
+
132
+ self.vote = self.get_vote()
133
+ self.win_probability = self.get_win_probability()
134
+
135
+ except KeyError as e:
136
+ raise KeyError(f"Missing key in PredictionResponse: {e}")
137
+ except ValueError as e:
138
+ raise ValueError(f"Invalid value in PredictionResponse: {e}")
139
+
140
+ def get_vote(self) -> Optional[str]:
141
+ """Return the vote."""
142
+ if self.p_no == self.p_yes:
143
+ return None
144
+ if self.p_no > self.p_yes:
145
+ return "No"
146
+ return "Yes"
147
+
148
+ def get_win_probability(self) -> Optional[float]:
149
+ """Return the probability estimation for winning with vote."""
150
+ return max(self.p_no, self.p_yes)
151
+
152
+
153
+ @dataclass(init=False)
154
+ class MechResponse:
155
+ """A structure for the response of a mech."""
156
+
157
+ request_id: int
158
+ deliver_block: Optional[int]
159
+ result: Optional[PredictionResponse]
160
+ error: Optional[str]
161
+ error_message: Optional[str]
162
+ prompt_response: Optional[str]
163
+ mech_address: Optional[str]
164
+
165
+ def __init__(self, **kwargs: Any) -> None:
166
+ """Initialize the mech's response ignoring extra keys."""
167
+ self.error = kwargs.get("error", None)
168
+ self.request_id = int(kwargs.get(REQUEST_ID, 0))
169
+ self.deliver_block = int(kwargs.get(BLOCK_FIELD, 0))
170
+ self.result = kwargs.get("result", None)
171
+ self.prompt_response = kwargs.get(PROMPT_FIELD, None)
172
+ self.mech_address = kwargs.get("sender", None)
173
+
174
+ if self.result != "Invalid response":
175
+ self.error_message = kwargs.get("error_message", None)
176
+
177
+ try:
178
+ if isinstance(self.result, str):
179
+ kwargs = json.loads(self.result)
180
+ self.result = PredictionResponse(**kwargs)
181
+ self.error = 0
182
+
183
+ except JSONDecodeError:
184
+ self.error_message = "Response parsing error"
185
+ self.error = 1
186
+
187
+ except Exception as e:
188
+ self.error_message = str(e)
189
+ self.error = 1
190
+
191
+ else:
192
+ self.error_message = "Invalid response from tool"
193
+ self.error = 1
194
+ self.result = None
195
+
196
+
197
+ EVENT_TO_MECH_STRUCT = {
198
+ MechEventName.REQUEST: MechRequest,
199
+ MechEventName.DELIVER: MechResponse,
200
+ }
201
 
202
 
203
  def parse_args() -> str: