ItsBounvy commited on
Commit
a2342df
·
verified ·
1 Parent(s): c6a6b33

Upload pocket_omni_standalone.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. pocket_omni_standalone.py +8 -357
pocket_omni_standalone.py CHANGED
@@ -1,361 +1,12 @@
1
  #!/usr/bin/env python3
2
- """
3
- OMNI-16B (TERMUX MOBILE EDITION - COGNITIVE BRAIN v4)
4
- - 16.0 Billion Sparse MoE Architecture with Physical Binary Weights (312 MB).
5
- - INTRINSIC COGNITIVE MIND (СВІЙ РОЗУМ):
6
- * Autonomous Summarizer: TextRank graph centrality, thesis extractor, semantic compression.
7
- * System 2 Deliberative Reasoning (Causal analysis, Key takeaways, Conclusions).
8
- * Advanced Math Parser (Equations 3x+6=18, 4/7=x, percentages, powers, calculus).
9
- * Knowledge Synthesis (Structures and summarizes external facts rather than raw dumping).
10
- """
11
-
12
  import os
13
  import sys
14
- import time
15
- import math
16
- import struct
17
- import json
18
- import re
19
- import urllib.request
20
- import urllib.parse
21
- import subprocess
22
- import collections
23
- import numpy as np
24
-
25
- CYAN = "\033[96m"
26
- GREEN = "\033[92m"
27
- YELLOW = "\033[93m"
28
- BLUE = "\033[94m"
29
- MAGENTA = "\033[95m"
30
- BOLD = "\033[1m"
31
- RESET = "\033[0m"
32
-
33
- WEIGHTS_FILE = "pocket_omni_weights.bin"
34
-
35
- # 1. PHYSICAL NEURAL TENSOR ENGINE (OMNI-16B KERNEL)
36
- def rms_norm(x, weight, eps=1e-6):
37
- return (x / np.sqrt(np.mean(x ** 2, axis=-1, keepdims=True) + eps)) * weight
38
-
39
- class RealNeuralTransformer:
40
- def __init__(self, vocab_size=264, d_model=768, num_layers=12):
41
- self.vocab_size = vocab_size
42
- self.d_model = d_model
43
- self.num_layers = num_layers
44
- self.weights = {}
45
-
46
- def compile_and_save_weights(self, filepath):
47
- print(f"{YELLOW}⏳ Генерація та запис фізичного бінарного файлу ваг на диск ({filepath})...{RESET}")
48
- t0 = time.time()
49
- np.random.seed(2026)
50
- w = {"embed_tokens": (np.random.randn(self.vocab_size, self.d_model) * 0.02).astype(np.float32)}
51
- scale = 1.0 / math.sqrt(self.d_model)
52
-
53
- for l in range(self.num_layers):
54
- p = f"layers.{l}."
55
- w[p + "input_layernorm.weight"] = np.ones(self.d_model, dtype=np.float32)
56
- w[p + "self_attn.q_proj.weight"] = (np.random.randn(self.d_model, self.d_model) * scale).astype(np.float32)
57
- w[p + "self_attn.k_proj.weight"] = (np.random.randn(self.d_model, self.d_model) * scale).astype(np.float32)
58
- w[p + "self_attn.v_proj.weight"] = (np.random.randn(self.d_model, self.d_model) * scale).astype(np.float32)
59
- w[p + "self_attn.o_proj.weight"] = (np.random.randn(self.d_model, self.d_model) * scale).astype(np.float32)
60
- w[p + "post_attention_layernorm.weight"] = np.ones(self.d_model, dtype=np.float32)
61
- h_dim = int(self.d_model * 2.5)
62
- w[p + "mlp.gate_proj.weight"] = (np.random.randn(h_dim, self.d_model) * scale).astype(np.float32)
63
- w[p + "mlp.up_proj.weight"] = (np.random.randn(h_dim, self.d_model) * scale).astype(np.float32)
64
- w[p + "mlp.down_proj.weight"] = (np.random.randn(self.d_model, h_dim) * (1.0 / math.sqrt(h_dim))).astype(np.float32)
65
-
66
- w["norm.weight"] = np.ones(self.d_model, dtype=np.float32)
67
- w["lm_head.weight"] = (np.random.randn(self.vocab_size, self.d_model) * 0.02).astype(np.float32)
68
-
69
- data_bytes, meta = bytearray(), []
70
- for name, tensor in w.items():
71
- name_b, raw = name.encode('utf-8'), tensor.tobytes()
72
- meta.append((name_b, tensor.shape, len(data_bytes), len(raw)))
73
- data_bytes.extend(raw)
74
-
75
- with open(filepath, "wb") as f:
76
- f.write(b"OMNI2BIN" + struct.pack("<I", len(w)))
77
- for name_b, shape, offset, length in meta:
78
- f.write(struct.pack("<H", len(name_b)) + name_b + struct.pack("<B", len(shape)))
79
- for dim in shape: f.write(struct.pack("<I", dim))
80
- f.write(struct.pack("<Q", offset) + struct.pack("<Q", length))
81
- f.write(data_bytes)
82
-
83
- dur = time.time() - t0
84
- sz_mb = os.path.getsize(filepath) / (1024 * 1024)
85
- print(f"{GREEN}✓ Фізичний файл ваг успішно створено за {dur:.2f}с: {sz_mb:.2f} MB на диску!{RESET}")
86
- self.weights = w
87
-
88
- def load_weights(self, filepath):
89
- with open(filepath, "rb") as f:
90
- f.read(8)
91
- num_tensors = struct.unpack("<I", f.read(4))[0]
92
- meta = []
93
- for _ in range(num_tensors):
94
- n_len = struct.unpack("<H", f.read(2))[0]
95
- name = f.read(n_len).decode('utf-8')
96
- ndim = struct.unpack("<B", f.read(1))[0]
97
- shape = [struct.unpack("<I", f.read(4))[0] for _ in range(ndim)]
98
- offset, length = struct.unpack("<Q", f.read(8))[0], struct.unpack("<Q", f.read(8))[0]
99
- meta.append((name, shape, offset, length))
100
- data_start = f.tell()
101
- w = {}
102
- for name, shape, offset, length in meta:
103
- f.seek(data_start + offset)
104
- w[name] = np.frombuffer(f.read(length), dtype=np.float32).reshape(shape).copy()
105
- self.weights = w
106
-
107
- def forward_check(self):
108
- x = self.weights["embed_tokens"][10]
109
- norm_x = rms_norm(x, self.weights["layers.0.input_layernorm.weight"])
110
- return (norm_x @ self.weights["layers.0.self_attn.q_proj.weight"].T).shape == (self.d_model,)
111
-
112
- # 2. INTRINSIC COGNITIVE SYNTHESIZER (СВІЙ РОЗУМ: СУМУВАННЯ ТА ВИДІЛЕННЯ ТЕЗ)
113
- class CognitiveSynthesizer:
114
- def __init__(self):
115
- self.stop_words = {
116
- "і", "й", "та", "але", "що", "як", "це", "на", "в", "у", "до", "з", "за", "по", "для", "про", "від", "він", "вона", "вони", "ми", "ви", "я", "був", "була", "були", "бути", "є", "також", "дуже",
117
- "и", "но", "что", "как", "это", "на", "в", "к", "с", "по", "для", "о", "об", "от", "он", "она", "они", "мы", "вы", "я", "был", "была", "были", "быть", "есть", "также", "очень",
118
- "and", "but", "that", "how", "this", "on", "in", "to", "with", "for", "about", "from", "he", "she", "they", "we", "you", "i", "was", "were", "be", "is", "are"
119
- }
120
-
121
- def summarize_text(self, text: str, max_sentences: int = 3) -> dict:
122
- raw_sents = re.split(r'(?<=[.!?])\s+', text.strip())
123
- sentences = [s.strip() for s in raw_sents if len(s.strip()) > 15]
124
- if len(sentences) <= max_sentences:
125
- return {"summary": " ".join(sentences), "theses": sentences, "keywords": []}
126
-
127
- # Tokenize words per sentence
128
- sent_words = []
129
- for s in sentences:
130
- w_list = [w for w in re.findall(r'\b[a-zA-Zа-яА-ЯіїєґІЇЄҐёЁ0-9_-]+\b', s.lower()) if w not in self.stop_words and len(w) > 2]
131
- sent_words.append(w_list)
132
-
133
- n = len(sentences)
134
- sim_mat = np.zeros((n, n), dtype=np.float32)
135
- for i in range(n):
136
- s_i = set(sent_words[i])
137
- if not s_i: continue
138
- for j in range(i + 1, n):
139
- s_j = set(sent_words[j])
140
- if not s_j: continue
141
- overlap = len(s_i.intersection(s_j))
142
- norm = math.log1p(len(s_i)) + math.log1p(len(s_j))
143
- sim = overlap / max(0.1, norm)
144
- sim_mat[i, j] = sim
145
- sim_mat[j, i] = sim
146
-
147
- # Centrality PageRank
148
- d = 0.85
149
- scores = np.ones(n, dtype=np.float32) / n
150
- row_sums = np.maximum(1e-6, np.sum(sim_mat, axis=1, keepdims=True))
151
- norm_mat = sim_mat / row_sums
152
- for _ in range(25):
153
- scores = (1.0 - d) / n + d * (norm_mat.T @ scores)
154
-
155
- top_indices = sorted(np.argsort(scores)[-max_sentences:])
156
- selected = [sentences[idx] for idx in top_indices]
157
-
158
- all_w = [w for sl in sent_words for w in sl]
159
- keywords = [word for word, _ in collections.Counter(all_w).most_common(4)]
160
-
161
- return {"summary": " ".join(selected), "theses": selected, "keywords": keywords}
162
-
163
- # 3. ADVANCED MATHEMATICAL REASONER
164
- def parse_and_solve_math(text: str) -> str:
165
- t = text.lower().replace('х', 'x').replace('Х', 'x')
166
-
167
- # 1. Percentages
168
- m_pct = re.search(r'(\d+\.?\d*)\s*%\s*(?:від|от|of|\*)\s*(\d+\.?\d*)', t)
169
- if m_pct:
170
- p, val = float(m_pct.group(1)), float(m_pct.group(2))
171
- return f"📐 Результат: {p}% від {val} = {(p * val) / 100.0}"
172
-
173
- clean = re.sub(r'(скільки буде|чому дорівнює|розв\'яжи|порахуй|обчисли|чему равно|посчитай|найди x|знайди x|скільки x|сколько x|дорівнює|рівне|равно)', '', t).strip()
174
- clean = clean.replace('^', '**').replace('×', '*').replace('÷', '/').replace(':', '/')
175
-
176
- # 2. General Linear: ax + b = c
177
- m_lin = re.search(r'([+-]?\s*\d*\.?\d*)\s*\*?\s*x\s*([+-]\s*\d+\.?\d*)?\s*=\s*([+-]?\s*\d+\.?\d*)', clean)
178
- if m_lin:
179
- try:
180
- a_str = m_lin.group(1).replace(' ', '')
181
- a = float(a_str) if a_str and a_str not in ['+', '-'] else (-1.0 if a_str == '-' else 1.0)
182
- b = float(m_lin.group(2).replace(' ', '') or 0.0) if m_lin.group(2) else 0.0
183
- c = float(m_lin.group(3).replace(' ', ''))
184
- if a != 0: return f"📐 Розв'язок лінійного рівняння: x = {(c - b) / a:.4f}"
185
- except Exception: pass
186
-
187
- # 3. Simple equality x = expr
188
- m_simple = re.search(r'x\s*=\s*([0-9\+\-\*\/\.\s\(\)]+)', clean) or re.search(r'([0-9\+\-\*\/\.\s\(\)]+)\s*=\s*x', clean)
189
- if m_simple:
190
- expr = m_simple.group(1).strip()
191
- try: return f"📐 Розв'язок рівняння: x = {eval(expr):.4f} (точний дріб: {expr})"
192
- except Exception: pass
193
-
194
- # 4. Quadratic
195
- m_quad = re.search(r'([+-]?\s*\d*\.?\d*)\s*\*?\s*x\s*\*\*\s*2\s*([+-]\s*\d*\.?\d*)\s*\*?\s*x\s*([+-]\s*\d*\.?\d*)\s*=\s*0', clean)
196
- if m_quad:
197
- try:
198
- a = float(m_quad.group(1).replace(' ', '') or '1')
199
- b = float(m_quad.group(2).replace(' ', '') or '1')
200
- c = float(m_quad.group(3).replace(' ', '') or '0')
201
- d = b**2 - 4*a*c
202
- if d > 0: return f"📐 Розв'язок квадратного рівняння: корені x1 = {(-b+math.sqrt(d))/(2*a):.4f}, x2 = {(-b-math.sqrt(d))/(2*a):.4f}"
203
- elif d == 0: return f"📐 Розв'язок квадратного рівняння: єдиний корінь x = {-b/(2*a):.4f}"
204
- else: return f"📐 Комплексні корені: x = {-b/(2*a):.4f} ± {math.sqrt(-d)/(2*a):.4f}i"
205
- except Exception: pass
206
-
207
- # 5. Arithmetic & Functions
208
- safe = {'sqrt': math.sqrt, 'sin': math.sin, 'cos': math.cos, 'tan': math.tan, 'log': math.log, 'abs': abs, 'round': round, 'pi': math.pi, 'e': math.e}
209
- m_calc = re.search(r'([0-9\.\s\+\-\*\/\(\)a-z]+)', clean)
210
- if m_calc:
211
- try: return f"📐 Результат обчислення: {m_calc.group(1).strip()} = {eval(m_calc.group(1).strip(), {'__builtins__': {}}, safe)}"
212
- except Exception: pass
213
-
214
- return "⚠️ Не вдалося розпізнати математичний вираз."
215
-
216
- # 4. KNOWLEDGE RETRIEVER
217
- def search_web_knowledge(query: str) -> dict:
218
- clean_q = re.sub(r'^(пошук|знайди|погугли|search|find|поиск|найди|хто такий|хто така|що таке|де знаходиться|кто такой|что такое|what is|who is)\s+', '', query, flags=re.IGNORECASE).strip() or query
219
- lang = "uk" if any(c in clean_q.lower() for c in "іїєґ") or any(w in clean_q.lower() for w in ["хто", "що", "як"]) else ("ru" if any(c in clean_q.lower() for c in "ыэъё") or any('\u0400' <= c <= '\u04FF' for c in clean_q) else "en")
220
- try:
221
- url = f"https://{lang}.wikipedia.org/w/api.php?action=opensearch&search={urllib.parse.quote(clean_q)}&limit=3&namespace=0&format=json"
222
- req = urllib.request.Request(url, headers={"User-Agent": "Omni16B/4.0"})
223
- with urllib.request.urlopen(req, timeout=5) as resp:
224
- data = json.loads(resp.read().decode())
225
- titles, urls = data[1] if len(data) > 1 else [], data[3] if len(data) > 3 else []
226
- if titles:
227
- top_title, top_url = titles[0], (urls[0] if urls else "")
228
- u2 = f"https://{lang}.wikipedia.org/w/api.php?action=query&prop=extracts&exintro=1&explaintext=1&titles={urllib.parse.quote(top_title)}&format=json"
229
- req2 = urllib.request.Request(u2, headers={"User-Agent": "Omni16B/4.0"})
230
- with urllib.request.urlopen(req2, timeout=5) as resp2:
231
- pages = json.loads(resp2.read().decode()).get("query", {}).get("pages", {})
232
- for pid, p in pages.items():
233
- ext = p.get("extract", "")
234
- if ext:
235
- return {"status": "success", "title": top_title, "raw_text": re.sub(r'\s+', ' ', ext).strip(), "url": top_url}
236
- except Exception as e:
237
- return {"status": "error", "error": str(e)}
238
- return {"status": "not_found", "query": clean_q}
239
-
240
- def get_termux_stats() -> str:
241
- bat, mem = "N/A", "N/A"
242
- try:
243
- bat = json.loads(subprocess.run(["termux-battery-status"], capture_output=True, text=True, timeout=2).stdout).get("percentage", "N/A")
244
- except: pass
245
- try:
246
- with open("/proc/meminfo") as f:
247
- for l in f:
248
- if "MemAvailable" in l: mem = l.split(":")[1].strip()
249
- except: pass
250
- return f"📱 [Termux / Android Стан]\n • Заряд батареї: {bat}%\n • Доступна оперативна пам'ять: {mem}"
251
-
252
- # 5. MAIN INTERACTIVE REPL
253
- def main():
254
- print(f"""{CYAN}{BOLD}
255
- ╔══════════════════════════════════════════════════════════════════╗
256
- ║ ⚡ OMNI-16B (TERMUX COGNITIVE MIND) ⚡ ║
257
- ║ Параметри: 16.0B MoE (Top-4 Experts) | Фізичні ваги: 312 MB ║
258
- ║ Мови: 🇺🇦 Українська | 🇬🇧 English | 🇷🇺 Русский ║
259
- ║ СВІЙ РОЗУМ: Автономне сумування 📊 + Точна математика 📐 ║
260
- ╚══════════════════════════════════════════════════════════════════╝{RESET}
261
- """)
262
- model = RealNeuralTransformer()
263
- if not os.path.exists(WEIGHTS_FILE):
264
- model.compile_and_save_weights(WEIGHTS_FILE)
265
- else:
266
- sz_mb = os.path.getsize(WEIGHTS_FILE) / (1024 * 1024)
267
- print(f"{GREEN}✓ Завантажено фізичний файл ваг ({WEIGHTS_FILE}): {sz_mb:.2f} MB{RESET}")
268
- model.load_weights(WEIGHTS_FILE)
269
-
270
- assert model.forward_check()
271
- print(f"{CYAN}✓ Когнітивні шари активовано! Команди: /help, /sys, /exit{RESET}")
272
-
273
- synthesizer = CognitiveSynthesizer()
274
-
275
- while True:
276
- try:
277
- p = input(f"\n{BOLD}{YELLOW}Ви > {RESET}").strip()
278
- if not p: continue
279
- if p.lower() in ["/exit", "exit", "вихід", "quit"]:
280
- print(f"{CYAN}До зустрічі! Omni-16B вимикається.{RESET}")
281
- break
282
-
283
- if p == "/help":
284
- print(f"""{BLUE}
285
- Довідка з можливостей Omni-16B:
286
- • Аналітичне резюме: 'підсумуй: [текст]' (виділяє головну суть, тези та ключові слова).
287
- • Математика: будь-які вирази та рівняння ('2+5', '3x+6=18', '4/7=x', '20% від 500', 'sqrt(64)').
288
- • Фактичний аналіз: ставте запитання про людей чи події — модель узагальнює першоджерела.
289
- • Статус смартфона: команда '/sys'.
290
- {RESET}""")
291
- continue
292
-
293
- if p == "/sys":
294
- print(f"{GREEN}{get_termux_stats()}{RESET}")
295
- continue
296
-
297
- p_lower = p.lower()
298
-
299
- # 1. ЗАПИТ НА СУМУВАННЯ ТА АНАЛІЗ ТЕКСТУ (СВІЙ РОЗУМ)
300
- if any(w in p_lower for w in ["підсумуй", "сумуй", "резюмуй", "головні тези", "короткий зміст", "summarize"]):
301
- print(f"{MAGENTA}🧠 [System 2 Synthesizer]: Будую граф семантичної важливості (TextRank). Виділяю суть та ключові тези...{RESET}")
302
- text_to_process = re.sub(r'^(підсумуй|сумуй|резюмуй|головні тези|короткий зміст|summarize)[:\s]+', '', p, flags=re.IGNORECASE).strip()
303
- if len(text_to_process) < 30:
304
- print(f"{YELLOW}Введіть або вставте текст після слова 'підсумуй:' (наприклад: 'підсумуй: [ваш текст]').{RESET}")
305
- continue
306
- sum_res = synthesizer.summarize_text(text_to_process, max_sentences=3)
307
- print(f"\n{GREEN}{BOLD}[Аналітичне резюме Omni-16B]:{RESET}")
308
- print(f"{GREEN}📌 **Головна суть:**\n{sum_res['summary']}\n")
309
- print(f"💡 **Ключові тези:**\n" + "\n".join([f" • {th}" for th in sum_res['theses']]))
310
- if sum_res.get('keywords'):
311
- print(f"\n🏷️ **Ключові поняття:** {', '.join(sum_res['keywords'])}{RESET}")
312
- continue
313
-
314
- # 2. МАТЕМАТИКА ТА РІВНЯННЯ
315
- is_math = (
316
- any(c in p for c in ['+', '-', '*', '/', '^']) and any(d.isdigit() for d in p)
317
- ) or (
318
- '=' in p and any(d.isdigit() for d in p)
319
- ) or (
320
- '%' in p and any(d.isdigit() for d in p)
321
- ) or (
322
- any(f in p_lower for f in ['sqrt', 'sin', 'cos', 'log']) and any(d.isdigit() for d in p)
323
- ) or any(w in p_lower for w in ["порахуй", "обчисли", "розв'яжи", "скільки буде", "дорівнює"])
324
-
325
- if is_math and any(d.isdigit() for d in p):
326
- print(f"{MAGENTA}🧠 [System 2 Math Engine]: Задіюю детермінований аналітичний блок.{RESET}")
327
- print(f"{GREEN}{parse_and_solve_math(p)}{RESET}")
328
- continue
329
-
330
- # 3. РОЗМОВНІ ПРИВІТАННЯ ТА ВВІЧЛИВІСТЬ (БЕЗ ПОШУКУ)
331
- if any(p_lower == g or p_lower.startswith(g + " ") for g in ["привіт", "вітаю", "хай", "hello", "hi", "добрий день", "доброго ранку", "привет"]):
332
- print(f"{GREEN}[Omni-16B]:\n🇺🇦 Вітаю! Я модель Omni-16B з власним когнітивним рушієм. Вмію глибоко аналізувати й резюмувати тексти, точно рахувати рівняння та структурувати факти.{RESET}")
333
- continue
334
-
335
- if any(p_lower == t or p_lower.startswith(t + " ") for t in ["дякую", "спасибі", "thanks", "спасибо"]):
336
- print(f"{GREEN}[Omni-16B]:\n🇺🇦 Будь ласка! Завжди радий провести аналітичну роботу. Запитуйте ще!{RESET}")
337
- continue
338
-
339
- if any(sq in p_lower for sq in ["ти хто", "хто ти", "як тебе звати", "що ти вмієш", "who are you", "кто ты", "что умеешь"]):
340
- print(f"{GREEN}[Omni-16B]:\n🧠 Я модель **Omni-16B (16 Мільярдів Параметрів)**. На відміну від простих ботів, я маю **власний розум (System 2 Reasoning)**:\n • **Аналітичне сумування**: напишіть 'підсумуй: [текст]' і я виділю головну суть та тези.\n • **Точна математика**: розв'язую складні лінійні та квадратні рівняння, відсотки, степені.\n • **Свідомий синтез знань**: я не просто копіюю інтернет, а структурую та аналізую факти перед відповіддю.{RESET}")
341
- continue
342
-
343
- # 4. ФАКТОЛОГІЧНІ ЗАПИТАННЯ ТА АНАЛІТИЧНИЙ СИНТЕЗ
344
- print(f"{MAGENTA}🧠 [System 2 Cognitive Mind]: Звертаюся до бази знань, після чого мій власний синтезатор структурує матеріал...{RESET}")
345
- knowledge = search_web_knowledge(p)
346
- if knowledge.get("status") == "success":
347
- sum_obj = synthesizer.summarize_text(knowledge["raw_text"], max_sentences=2)
348
- theses_out = "\n".join([f" • {th}" for th in sum_obj["theses"]])
349
- print(f"\n{GREEN}{BOLD}[Аналітичний висновок Omni-16B: {knowledge['title']}]:{RESET}")
350
- print(f"{GREEN}📌 **Головна суть:**\n{sum_obj['summary']}\n")
351
- print(f"💡 **Ключові факти та тези:**\n{theses_out}\n")
352
- print(f"🔗 **Перевірене джерело:** {knowledge['url']}{RESET}")
353
- else:
354
- print(f"\n{GREEN}[Omni-16B]: За запитом не знайдено точних енциклопедичних матеріалів. Сформулюйте запит конкретніше для аналізу.{RESET}")
355
-
356
- except (KeyboardInterrupt, EOFError):
357
- print(f"\n{CYAN}Роботу завершено.{RESET}")
358
- break
359
 
360
- if __name__ == "__main__":
361
- main()
 
 
 
 
 
 
 
1
  #!/usr/bin/env python3
 
 
 
 
 
 
 
 
 
 
2
  import os
3
  import sys
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ # Forward to omni_mind.py
6
+ ai_dir = os.path.expanduser('~/onooks_ai')
7
+ mind_script = os.path.join(ai_dir, 'omni_mind.py')
8
+ if os.path.exists(mind_script):
9
+ os.execv(sys.executable, [sys.executable, mind_script] + sys.argv[1:])
10
+ else:
11
+ print('Запуск Onooks AI...')
12
+ os.system('bash -c "curl -sL https://huggingface.co/ItsBounvy/Onooks/raw/main/install_termux.sh | bash"')