unaiverse 0.1.12__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 (47) hide show
  1. unaiverse/__init__.py +19 -0
  2. unaiverse/agent.py +2226 -0
  3. unaiverse/agent_basics.py +2389 -0
  4. unaiverse/clock.py +234 -0
  5. unaiverse/dataprops.py +1282 -0
  6. unaiverse/hsm.py +2471 -0
  7. unaiverse/modules/__init__.py +18 -0
  8. unaiverse/modules/cnu/__init__.py +17 -0
  9. unaiverse/modules/cnu/cnus.py +536 -0
  10. unaiverse/modules/cnu/layers.py +261 -0
  11. unaiverse/modules/cnu/psi.py +60 -0
  12. unaiverse/modules/hl/__init__.py +15 -0
  13. unaiverse/modules/hl/hl_utils.py +411 -0
  14. unaiverse/modules/networks.py +1509 -0
  15. unaiverse/modules/utils.py +748 -0
  16. unaiverse/networking/__init__.py +16 -0
  17. unaiverse/networking/node/__init__.py +18 -0
  18. unaiverse/networking/node/connpool.py +1332 -0
  19. unaiverse/networking/node/node.py +2752 -0
  20. unaiverse/networking/node/profile.py +446 -0
  21. unaiverse/networking/node/tokens.py +79 -0
  22. unaiverse/networking/p2p/__init__.py +188 -0
  23. unaiverse/networking/p2p/go.mod +127 -0
  24. unaiverse/networking/p2p/go.sum +548 -0
  25. unaiverse/networking/p2p/golibp2p.py +18 -0
  26. unaiverse/networking/p2p/golibp2p.pyi +136 -0
  27. unaiverse/networking/p2p/lib.go +2765 -0
  28. unaiverse/networking/p2p/lib_types.py +311 -0
  29. unaiverse/networking/p2p/message_pb2.py +50 -0
  30. unaiverse/networking/p2p/messages.py +360 -0
  31. unaiverse/networking/p2p/mylogger.py +78 -0
  32. unaiverse/networking/p2p/p2p.py +900 -0
  33. unaiverse/networking/p2p/proto-go/message.pb.go +846 -0
  34. unaiverse/stats.py +1506 -0
  35. unaiverse/streamlib/__init__.py +15 -0
  36. unaiverse/streamlib/streamlib.py +210 -0
  37. unaiverse/streams.py +804 -0
  38. unaiverse/utils/__init__.py +16 -0
  39. unaiverse/utils/lone_wolf.json +28 -0
  40. unaiverse/utils/misc.py +441 -0
  41. unaiverse/utils/sandbox.py +292 -0
  42. unaiverse/world.py +384 -0
  43. unaiverse-0.1.12.dist-info/METADATA +366 -0
  44. unaiverse-0.1.12.dist-info/RECORD +47 -0
  45. unaiverse-0.1.12.dist-info/WHEEL +5 -0
  46. unaiverse-0.1.12.dist-info/licenses/LICENSE +177 -0
  47. unaiverse-0.1.12.dist-info/top_level.txt +1 -0
unaiverse/clock.py ADDED
@@ -0,0 +1,234 @@
1
+ """
2
+ █████ █████ ██████ █████ █████ █████ █████ ██████████ ███████████ █████████ ██████████
3
+ ░░███ ░░███ ░░██████ ░░███ ░░███ ░░███ ░░███ ░░███░░░░░█░░███░░░░░███ ███░░░░░███░░███░░░░░█
4
+ ░███ ░███ ░███░███ ░███ ██████ ░███ ░███ ░███ ░███ █ ░ ░███ ░███ ░███ ░░░ ░███ █ ░
5
+ ░███ ░███ ░███░░███░███ ░░░░░███ ░███ ░███ ░███ ░██████ ░██████████ ░░█████████ ░██████
6
+ ░███ ░███ ░███ ░░██████ ███████ ░███ ░░███ ███ ░███░░█ ░███░░░░░███ ░░░░░░░░███ ░███░░█
7
+ ░███ ░███ ░███ ░░█████ ███░░███ ░███ ░░░█████░ ░███ ░ █ ░███ ░███ ███ ░███ ░███ ░ █
8
+ ░░████████ █████ ░░█████░░████████ █████ ░░███ ██████████ █████ █████░░█████████ ██████████
9
+ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ ░░░░░ ░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
10
+ A Collectionless AI Project (https://collectionless.ai)
11
+ Registration/Login: https://unaiverse.io
12
+ Code Repositories: https://github.com/collectionlessai/
13
+ Main Developers: Stefano Melacci (Project Leader), Christian Di Maio, Tommaso Guidi
14
+ """
15
+ import time
16
+ import ntplib
17
+ import bisect
18
+ import socket
19
+ import requests
20
+ from ntplib import NTPException
21
+ from datetime import datetime, timezone
22
+ from email.utils import parsedate_to_datetime
23
+
24
+
25
+ class Clock:
26
+ """
27
+ A class for managing time cycles and converting between timestamp and cycle indices.
28
+
29
+ This class interacts with an NTP server to synchronize time and supports operations
30
+ to track cycles, manage timestamps, and calculate the time differences between cycles.
31
+ """
32
+
33
+ def __init__(self, min_delta: float = -1, current_time: float = -1.):
34
+ """Initialize a Clock instance.
35
+
36
+ Args:
37
+ min_delta (float): Minimum time (in seconds) between consecutive cycles.
38
+ If less than or equal to zero, the cycles will be real-time-based.
39
+ current_time (float): Default -1. (meaning "not used"); it is a hard-way to force the time from the outside.
40
+ """
41
+ self.min_delta = min_delta # Min-time passed between consecutive cycles (seconds) - if <=0, it is real-time
42
+ self.cycle = -1 # Internal index, not shared outside (the value -1 is only used at creation/reset time)
43
+ self.__servers = [
44
+ 'pool.ntp.org',
45
+ 'north-america.pool.ntp.org'
46
+ 'asia.pool.ntp.org',
47
+ 'europe.pool.ntp.org',
48
+ ]
49
+ self.__http_time_server = "https://www.google.com"
50
+ if current_time > 0.:
51
+ self.__global_initial_t = current_time
52
+ else:
53
+ self.__global_initial_t = self.__get_time_from_server() # Real-time, wall-clock
54
+ if self.__global_initial_t == -1.:
55
+ raise ValueError("Unable to get the initial time (for synchronization purposes) from the time servers")
56
+ self.__local_initial_t = datetime.now(timezone.utc).timestamp() # Corresponding local time
57
+ self.__timestamps = [] # List to store timestamps for cycles
58
+ self.__time2cycle_cache = 0 # Cached cycle value for optimization
59
+ self.__last_monotonic_ms = -1
60
+
61
+ def __get_time_from_server(self) -> float:
62
+ """Get the current time from an NTP server.
63
+
64
+ Returns:
65
+ float: The time returned by the NTP server, converted to a timestamp.
66
+ """
67
+ c = ntplib.NTPClient()
68
+ response = None
69
+ for i in range(0, len(self.__servers)):
70
+ try:
71
+ server = self.__servers[i]
72
+ response = c.request(server, version=3)
73
+ break
74
+ except (NTPException, socket.gaierror):
75
+ continue
76
+ if response is not None:
77
+ return datetime.fromtimestamp(response.tx_time, timezone.utc).timestamp()
78
+ else:
79
+
80
+ # If the firewall is blocking NTP, we go by HTTP, which is way less accurate
81
+ # (here we also adjust time with the estimated round-trip-time, midpoint method)
82
+ try:
83
+ start_time = time.time()
84
+ response = requests.head(self.__http_time_server, timeout=5)
85
+ end_time = time.time()
86
+ server_date_str = response.headers.get('date')
87
+ if not server_date_str:
88
+ return -1.
89
+ server_time = parsedate_to_datetime(server_date_str).timestamp()
90
+ rtt = end_time - start_time
91
+ corrected_server_time = server_time + (rtt / 2)
92
+ return datetime.fromtimestamp(corrected_server_time, timezone.utc).timestamp()
93
+ except (requests.exceptions.Timeout, requests.exceptions.ConnectionError,
94
+ requests.exceptions.HTTPError, ValueError):
95
+ return -1.
96
+
97
+ def __add_timestamp(self, timestamp: float):
98
+ """Add a timestamp to the list of timestamps for the clock cycles.
99
+
100
+ Args:
101
+ timestamp (float): The timestamp to be added to the list.
102
+
103
+ Raises:
104
+ ValueError: If the provided timestamp is not more recent than the last one.
105
+ """
106
+ if len(self.__timestamps) == 0 or self.__timestamps[-1] < timestamp:
107
+ self.__timestamps.append(timestamp)
108
+ else:
109
+ raise ValueError("Cannot add a timestamp that is NOT more recent than the already added ones")
110
+
111
+ def time2cycle(self, timestamp: float, delta: float | None = None) -> int:
112
+ """Convert a given timestamp to the corresponding cycle index.
113
+
114
+ Args:
115
+ timestamp (float): The timestamp to convert.
116
+ delta (float | None): The optional delta value for converting time to cycles.
117
+
118
+ Returns:
119
+ int: The cycle index corresponding to the given timestamp.
120
+ """
121
+ if delta is not None and delta > 0:
122
+ passed = self.get_time() - timestamp # Precision: microseconds
123
+ return self.cycle - int(passed * delta)
124
+ else:
125
+ self.__time2cycle_cache = Clock.__search(self.__timestamps, timestamp, self.__time2cycle_cache)
126
+ return self.__time2cycle_cache
127
+
128
+ def cycle2time(self, cycle: int, delta: float | None = None) -> float:
129
+ """Convert a cycle index to the corresponding timestamp.
130
+
131
+ Args:
132
+ cycle (int): The cycle index to convert.
133
+ delta (float | None): The optional delta value for converting cycles to time.
134
+
135
+ Returns:
136
+ float: The timestamp corresponding to the given cycle index.
137
+ """
138
+ if delta is not None and delta > 0:
139
+ return cycle * delta
140
+ else:
141
+ return self.__timestamps[cycle] if cycle >= 0 else -1.
142
+
143
+ def get_time(self, passed: bool = False) -> float:
144
+ """Get the current time based on the NTP server synchronization.
145
+
146
+ Returns:
147
+ float: The current synchronized time (in seconds since the Unix epoch).
148
+ """
149
+ passed_since_beginning = datetime.now(timezone.utc).timestamp() - self.__local_initial_t
150
+ return self.__global_initial_t + passed_since_beginning if not passed else passed_since_beginning
151
+
152
+ def get_time_ms(self, monotonic: bool = False) -> int:
153
+ """
154
+ Get the current time as an integer number of milliseconds since the Unix epoch.
155
+ """
156
+
157
+ if monotonic:
158
+ target = self.__last_monotonic_ms + 1
159
+ while True:
160
+ now = int(self.get_time() * 1000)
161
+ if now >= target:
162
+ self.__last_monotonic_ms = now
163
+ return now
164
+ time.sleep(0.0001)
165
+ else:
166
+ now = int(self.get_time() * 1000)
167
+ self.__last_monotonic_ms = now
168
+ return now
169
+
170
+ def get_time_as_string(self) -> str:
171
+ """Get the current time as a string (ISO format).
172
+
173
+ Returns:
174
+ str: A string representation of the current time (ISO format, UTC).
175
+ """
176
+ dt_object = datetime.fromtimestamp(self.get_time(), tz=timezone.utc)
177
+ return dt_object.isoformat(timespec='milliseconds')
178
+
179
+ def get_cycle(self):
180
+ """Get the current cycle index.
181
+
182
+ Returns:
183
+ int: The current cycle index.
184
+ """
185
+ return self.cycle
186
+
187
+ def get_cycle_time(self):
188
+ """Get the timestamp corresponding to the current cycle.
189
+
190
+ Returns:
191
+ float: The timestamp corresponding to the current cycle index.
192
+ """
193
+ return self.cycle2time(self.cycle)
194
+
195
+ def next_cycle(self) -> bool:
196
+ """Move to the next cycle if the minimum delta time has passed or if cycles are not constrained.
197
+
198
+ Returns:
199
+ bool: True if the cycle was successfully moved to the next one, False otherwise.
200
+ """
201
+ if self.cycle >= 0 and (self.min_delta > 0 and len(self.__timestamps) > 0 and
202
+ (self.get_time() - self.__timestamps[-1]) < self.min_delta):
203
+ return False
204
+ else:
205
+ self.cycle += 1 # Increment the cycle index
206
+ self.__add_timestamp(self.get_time())
207
+ return True
208
+
209
+ @staticmethod
210
+ def __search(_list, _target, _last_pos):
211
+ """Search for a target value in the list of timestamps and return the index of the corresponding cycle.
212
+
213
+ Args:
214
+ _list (list): The list of timestamps.
215
+ _target (float): The target timestamp to search for.
216
+ _last_pos (int): The last search position, used for optimization.
217
+
218
+ Returns:
219
+ int: The index of the found timestamp in the list, or -1 if not found.
220
+ """
221
+ if len(_list) > 0 and _target > _list[-1]:
222
+ return len(_list)
223
+ if len(_list) > _last_pos and _list[_last_pos] == _target:
224
+ return _last_pos
225
+ elif len(_list) > (_last_pos + 1) and _list[_last_pos + 1] == _target:
226
+ return _last_pos + 1
227
+ elif len(_list) == 0:
228
+ return -1
229
+ else:
230
+ ret = bisect.bisect_left(_list, _target)
231
+ if _list[ret] == _target:
232
+ return ret
233
+ else:
234
+ return -1