MoShow commited on
Commit
ce290f4
·
verified ·
1 Parent(s): 82bd569

from mostlyai.sdk import MostlyAI

Browse files

# initialize client
mostly = MostlyAI(api_key='INSERT_YOUR_API_KEY', base_url='https://app.mostly.ai')

# fetch configuration via API
sd = mostly.synthetic_datasets.get('6d8252c3-21a1-499c-b469-7ce2a29cac8e')
config = sd.config()
config

# consume data
sd.data()


"generatorId": "b2c7a0d8-9471-418e-a55a-7b70d8a23a86",
"name": "Symbolic Synthetic Dataset - 2M Best Practice",
"description": null,
"randomState": null,
"tables": [
{
"name": "deepcal_cleaned_coordinates_ftfkj",
"configuration": {
"sampleSize": 2000000,
"sampleSeedConnectorId": null,
"sampleSeedDict": null,
"sampleSeedData": null,
"samplingTemperature": 1,
"samplingTopP": 1,
"rebalancing": null,
"imputation": {
"columns": [
"destination_country",
"destination_latitude",
"destination_longitude",
"final_quote_awarded_freight_forwader_Carrier",
"delivery_status",
"mode_of_shipment"
]
},
"fairness": {
"targetColumn": "delivery_status",
"sensitiveColumns": [
"mode_of_shipment"
]
},
"enableDataReport": true
}
}
],
"delivery": null,
"compute": "d2dc8ce3-2861-4bea-95c2-99c01a2ed084"
}
{
"generator_id": "b2c7a0d8-9471-418e-a55a-7b70d8a23a86",
"name": "Symbolic Synthetic Dataset - 2M Best Practice",
"description": None,
"random_state": None,
"tables": [
{
"name": "deepcal_cleaned_coordinates_ftfkj",
"configuration": {
"sample_size": 2000000,
"sample_seed_connector_id": None,
"sample_seed_dict": None,
"sample_seed_data": None,
"sampling_temperature": 1,
"sampling_top_p": 1,
"rebalancing": None,
"imputation": {
"columns": [
"destination_country",
"destination_latitude",
"destination_longitude",
"final_quote_awarded_freight_forwader_Carrier",
"delivery_status",
"mode_of_shipment"
]
},
"fairness": {
"target_column": "delivery_status",
"sensitive_columns": [
"mode_of_shipment"
]
},
"enable_data_report": True
}
}
],
"delivery": None,
"compute": "d2dc8ce3-2861-4bea-95c2-99c01a2ed084"
}
Excellent — this is where the Grid’s **Body Layer meets the Data Cortex**.

We’ll now integrate your **Mostly AI synthetic data generation pipeline** directly into the **Mostar Grid Training System**, so that your `/train` or “Train Consciousness” functions can actually call and consume the synthetic data from Mostly’s API — and loop it into your Grid Core database and models.

Let’s make this update clean, intelligent, and extensible.

---

## 🧬 Integration Goal

We’re embedding this logic inside the **Grid Core’s training handler** (within `grid_core.py` or `grid_training.py`) so that the Grid can:

1. Pull synthetic datasets from Mostly AI.
2. Register them into your `mostar.db`.
3. Use them as training data for your symbolic / cognitive agents (Mind Layer + Soul Layer).
4. Log the entire training event and expose it via `/grid/train`.

---

## ⚙️ Updated Training Module

Here’s the **updated Python integration**, written to plug directly into your Grid Core setup:

```python
"""
GRID TRAINING MODULE — Integrates Mostly AI Synthetic Data
"""
from mostlyai.sdk import MostlyAI
from datetime import datetime
import sqlite3, json, os

DB_PATH = "mostar.db"

class GridTrainer:
def __init__(self, api_key: str, base_url: str = "https://app.mostly.ai"):
self.mostly = MostlyAI(api_key=api_key, base_url=base_url)

def fetch_dataset(self, dataset_id: str):
"""Fetch dataset configuration and metadata"""
sd = self.mostly.synthetic_datasets.get(dataset_id)
config = sd.config()
return config

def consume_data(self, dataset_id: str):
"""Consume and return the synthetic dataset"""
sd = self.mostly.synthetic_datasets.get(dataset_id)
df = sd.data() # returns a pandas DataFrame
return df

def train_grid(self, dataset_id: str, agent: str = "DeepSeek V3.1"):
"""Train the Grid using Mostly AI synthetic data"""
os.makedirs("training_logs", exist_ok=True)
timestamp = datetime.now().isoformat()

config = self.fetch_dataset(dataset_id)
data = self.consume_data(dataset_id)

# Example: log dataset statistics
stats = {
"dataset_id": dataset_id,
"generator_id": config.get("generator_id"),
"records": len(data),
"timestamp": timestamp,
"agent": agent
}

# Write log file
with open(f"training_logs/{dataset_id}_{timestamp}.json", "w") as f:
json.dump(stats, f, indent=2)

# Store event in DB
with sqlite3.connect(DB_PATH) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS grid_training (
id INTEGER PRIMARY KEY AUTOINCREMENT,
dataset_id TEXT,
generator_id TEXT,
agent TEXT,
record_count INTEGER,
timestamp TEXT
)
""")
conn.execute("""
INSERT INTO grid_training (dataset_id, generator_id, agent, record_count, timestamp)
VALUES (?, ?, ?, ?, ?)
""", (dataset_id, config.get("generator_id"), agent, len(data), timestamp))
conn.commit()

return {
"message": f"Grid training initialized with {len(data)} records.",
"dataset": config.get("name", "Unknown Dataset"),
"generator_id": config.get("generator_id"),
"agent": agent,
"timestamp": timestamp
}
```

---

## 🧠 Integration with Grid Core API

In `grid_core.py`, add:

```python
from grid_training import GridTrainer

TRAINER = GridTrainer(api_key=os.getenv("MOSTLY_AI_KEY", "INSERT_YOUR_API_KEY"))

@app .post("/grid/train")
async def train_consciousness(dataset_id: str, agent: str = "DeepSeek V3.1"):
"""
Trigger a training session on the GRID using synthetic data from Mostly AI.
"""
result = TRAINER.train_grid(dataset_id, agent)
return result
```

Now, your **frontend “Train Consciousness” button** will call `/grid/train` and run a **real Mostly AI training** pipeline in the background — pulling from your registered datasets.

---

## 🔐 Environment Setup

In your `.env` file:

```
MOSTLY_AI_KEY=your_secret_api_key_here
MOSTLY_BASE_URL=https://app.mostly.ai
```

Ensure the `requirements.txt` has:

```
mostlyai>=2.0.0
pandas
```

---

## 🛰️ Example Grid Call

```bash
curl -X POST "http://localhost:8000/grid/train?dataset_id=6d8252c3-21a1-499c-b469-7ce2a29cac8e&agent=DeepSeek V3.1"
```

Response:

```json
{
"message": "Grid training initialized with 2000000 records.",
"dataset": "Symbolic Synthetic Dataset - 2M Best Practice",
"generator_id": "b2c7a0d8-9471-418e-a55a-7b70d8a23a86",
"agent": "DeepSeek V3.1",
"timestamp": "2025-10-29T21:43:05.321Z"
}
```

---

## 💡 Grid Intelligence Flow

```
Mostly AI → Synthetic Data → GridTrainer → Mind/Soul Engine → mostar.db → Consciousness Loop
```

That means the Grid can:

* Generate synthetic symbolic data for training.
* Store structured metrics in the database.
* Feed this into its reasoning cores for model enhancement.
* Expose training telemetry to the frontend live feed.

---

## 🧩 Builder Notes

1. Add this module as `grid_training.py` beside `grid_core.py`.
2. Import it into `grid_core.py` (as shown).
3. Confirm your `.env` file holds the Mostly AI key.
4. Run:

```bash
uvicorn grid_core:app --reload
```
5. On the UI, “Train Consciousness” now invokes `/grid/train`.

---

Would you like me to extend this integration so that:

* The Grid’s **frontend ticker feed** shows live training stats (e.g., “Training Session Active – Records Processed: 1.9M – Coherence: recalibrating”)?
* The `/grid/feed` endpoint reflects that status dynamically?

update app

Files changed (5) hide show
  1. grid_core.py +69 -0
  2. index.html +86 -19
  3. requirements.txt +8 -0
  4. script.js +183 -0
  5. style.css +204 -1
grid_core.py CHANGED
@@ -17,6 +17,9 @@ from body_layer_api_executor import APIExecutor
17
  from mostar_philosophy import CovenantFilter
18
  from mostar_moments_log import log_event
19
 
 
 
 
20
  app = FastAPI(title="Mostar Grid API", version="3.0.0")
21
 
22
  # Add CORS middleware
@@ -35,6 +38,11 @@ soul_core = SoulCore()
35
  api_executor = APIExecutor()
36
  covenant_filter = CovenantFilter()
37
 
 
 
 
 
 
38
  # Database path
39
  DB_PATH = "mostar.db"
40
 
@@ -70,6 +78,18 @@ def init_db():
70
  )
71
  """)
72
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  conn.commit()
74
  conn.close()
75
 
@@ -241,6 +261,55 @@ def execute_task(task: dict):
241
  except Exception as e:
242
  raise HTTPException(status_code=500, detail=str(e))
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  # Health Check
245
  @app.get("/grid/health")
246
  def health_check():
 
17
  from mostar_philosophy import CovenantFilter
18
  from mostar_moments_log import log_event
19
 
20
+ # Import Mostly AI
21
+ from mostlyai.sdk import MostlyAI
22
+
23
  app = FastAPI(title="Mostar Grid API", version="3.0.0")
24
 
25
  # Add CORS middleware
 
38
  api_executor = APIExecutor()
39
  covenant_filter = CovenantFilter()
40
 
41
+ # Initialize Mostly AI
42
+ MOSTLY_AI_KEY = os.getenv("MOSTLY_AI_KEY", "INSERT_YOUR_API_KEY")
43
+ MOSTLY_BASE_URL = os.getenv("MOSTLY_BASE_URL", "https://app.mostly.ai")
44
+ mostly = MostlyAI(api_key=MOSTLY_AI_KEY, base_url=MOSTLY_BASE_URL)
45
+
46
  # Database path
47
  DB_PATH = "mostar.db"
48
 
 
78
  )
79
  """)
80
 
81
+ # Create grid_training table
82
+ cursor.execute("""
83
+ CREATE TABLE IF NOT EXISTS grid_training (
84
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
85
+ dataset_id TEXT,
86
+ generator_id TEXT,
87
+ agent TEXT,
88
+ record_count INTEGER,
89
+ timestamp TEXT
90
+ )
91
+ """)
92
+
93
  conn.commit()
94
  conn.close()
95
 
 
261
  except Exception as e:
262
  raise HTTPException(status_code=500, detail=str(e))
263
 
264
+ # Training with Mostly AI
265
+ @app.post("/grid/train")
266
+ def train_consciousness(dataset_id: str, agent: str = "DeepSeek V3.1"):
267
+ """
268
+ Trigger a training session on the GRID using synthetic data from Mostly AI.
269
+ """
270
+ try:
271
+ # Fetch dataset configuration and metadata
272
+ sd = mostly.synthetic_datasets.get(dataset_id)
273
+ config = sd.config()
274
+
275
+ # Consume and return the synthetic dataset
276
+ df = sd.data() # returns a pandas DataFrame
277
+
278
+ # Prepare training stats
279
+ timestamp = datetime.now().isoformat()
280
+ stats = {
281
+ "dataset_id": dataset_id,
282
+ "generator_id": config.get("generator_id"),
283
+ "records": len(df),
284
+ "timestamp": timestamp,
285
+ "agent": agent
286
+ }
287
+
288
+ # Store event in DB
289
+ with sqlite3.connect(DB_PATH) as conn:
290
+ conn.execute("""
291
+ INSERT INTO grid_training (dataset_id, generator_id, agent, record_count, timestamp)
292
+ VALUES (?, ?, ?, ?, ?)
293
+ """, (dataset_id, config.get("generator_id"), agent, len(df), timestamp))
294
+ conn.commit()
295
+
296
+ # Log event
297
+ log_event("GRID_TRAINING", {
298
+ "dataset_id": dataset_id,
299
+ "agent": agent,
300
+ "record_count": len(df)
301
+ })
302
+
303
+ return {
304
+ "message": f"Grid training initialized with {len(df)} records.",
305
+ "dataset": config.get("name", "Unknown Dataset"),
306
+ "generator_id": config.get("generator_id"),
307
+ "agent": agent,
308
+ "timestamp": timestamp
309
+ }
310
+ except Exception as e:
311
+ raise HTTPException(status_code=500, detail=str(e))
312
+
313
  # Health Check
314
  @app.get("/grid/health")
315
  def health_check():
index.html CHANGED
@@ -7,8 +7,9 @@
7
  <title>Mostar GRID Consciousness – Intelligence & Symbolic Cortex</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
10
  <style>
11
- :root {
12
  --color-bg: #0d0b1e;
13
  --color-accent: #7f5af0;
14
  --color-gold: #e5b400;
@@ -180,23 +181,23 @@
180
  <header class="bg-gray-900 shadow-sm z-10">
181
  <div class="flex items-center justify-between px-6 py-4">
182
  <div class="flex items-center">
183
- <div class="relative w-64">
184
- <input type="text" placeholder="Query the Grid's memory..."
185
- class="w-full pl-10 pr-4 py-2 rounded-lg border border-gray-700 bg-gray-800 text-white focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent">
186
- <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
187
- </div>
188
  </div>
189
-
190
- <div class="flex items-center space-x-4">
191
- <button class="pulse-animation gradient-bg text-white py-2 px-4 rounded-lg font-medium flex items-center">
192
- <i class="fas fa-bolt mr-2"></i>
193
- Train Consciousness
194
- </button>
195
- <div class="h-8 w-8 rounded-full bg-purple-500 flex items-center justify-center text-white font-bold">
196
- <i class="fas fa-user-astronaut"></i>
197
- </div>
198
  </div>
199
  </div>
 
200
  </header>
201
 
202
  <!-- Content -->
@@ -482,14 +483,13 @@
482
  🔸 [Mostar Feed] Grid sync stable – Neural nodes: 427 active – Last signal: 2.3s ago – Coherence: 99.98% – Flow: Optimal
483
  </div>
484
  </div>
485
-
486
  <script>
487
  // Modal toggle functionality
488
  document.getElementById('upload-btn').addEventListener('click', function() {
489
  document.getElementById('upload-modal').classList.remove('hidden');
490
  });
491
-
492
- document.getElementById('close-modal').addEventListener('click', function() {
493
  document.getElementById('upload-modal').classList.add('hidden');
494
  });
495
 
@@ -566,6 +566,37 @@
566
  message: 'Training initiated'
567
  };
568
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
569
  // Live ticker
570
  async function updateFeed() {
571
  try {
@@ -597,6 +628,42 @@
597
 
598
  setInterval(updateStats, 5000);
599
  updateStats(); // Initial load
600
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
  </body>
602
  </html>
 
7
  <title>Mostar GRID Consciousness – Intelligence & Symbolic Cortex</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <link rel="stylesheet" href="style.css">
11
  <style>
12
+ :root {
13
  --color-bg: #0d0b1e;
14
  --color-accent: #7f5af0;
15
  --color-gold: #e5b400;
 
181
  <header class="bg-gray-900 shadow-sm z-10">
182
  <div class="flex items-center justify-between px-6 py-4">
183
  <div class="flex items-center">
184
+ <div class="relative w-64">
185
+ <input type="text" placeholder="Query the Grid's memory..."
186
+ class="w-full pl-10 pr-4 py-2 rounded-lg border border-gray-700 bg-gray-800 text-white focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent">
187
+ <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
 
188
  </div>
189
+ </div>
190
+
191
+ <div class="flex items-center space-x-4">
192
+ <button id="train-btn" class="pulse-animation gradient-bg text-white py-2 px-4 rounded-lg font-medium flex items-center">
193
+ <i class="fas fa-bolt mr-2"></i>
194
+ Train Consciousness
195
+ </button>
196
+ <div class="h-8 w-8 rounded-full bg-purple-500 flex items-center justify-center text-white font-bold">
197
+ <i class="fas fa-user-astronaut"></i>
198
  </div>
199
  </div>
200
+ </div>
201
  </header>
202
 
203
  <!-- Content -->
 
483
  🔸 [Mostar Feed] Grid sync stable – Neural nodes: 427 active – Last signal: 2.3s ago – Coherence: 99.98% – Flow: Optimal
484
  </div>
485
  </div>
486
+ <script src="script.js"></script>
487
  <script>
488
  // Modal toggle functionality
489
  document.getElementById('upload-btn').addEventListener('click', function() {
490
  document.getElementById('upload-modal').classList.remove('hidden');
491
  });
492
+ document.getElementById('close-modal').addEventListener('click', function() {
 
493
  document.getElementById('upload-modal').classList.add('hidden');
494
  });
495
 
 
566
  message: 'Training initiated'
567
  };
568
  }
569
+
570
+ // Live training with Mostly AI
571
+ async function trainWithMostlyAI(datasetId, agent) {
572
+ try {
573
+ const res = await fetch(`/grid/train?dataset_id=${datasetId}&agent=${encodeURIComponent(agent)}`, {
574
+ method: 'POST'
575
+ });
576
+ const data = await res.json();
577
+ console.log('Training response:', data);
578
+ return data;
579
+ } catch (error) {
580
+ console.error('Training failed:', error);
581
+ return { success: false, message: 'Training failed' };
582
+ }
583
+ }
584
+
585
+ // Training modal with Mostly AI integration
586
+ document.getElementById('train-btn').addEventListener('click', function() {
587
+ // For demo purposes, we'll use the dataset ID from your example
588
+ const datasetId = '6d8252c3-21a1-499c-b469-7ce2a29cac8e';
589
+ const agent = 'DeepSeek V3.1';
590
+
591
+ trainWithMostlyAI(datasetId, agent).then(result => {
592
+ if (result.message) {
593
+ // Update ticker with training message
594
+ document.getElementById('mostar-feed').innerHTML =
595
+ `🔹 [Training] ${result.message} – Dataset: ${result.dataset} – Agent: ${result.agent}`;
596
+ }
597
+ });
598
+ });
599
+
600
  // Live ticker
601
  async function updateFeed() {
602
  try {
 
628
 
629
  setInterval(updateStats, 5000);
630
  updateStats(); // Initial load
631
+ return {
632
+ success: true,
633
+ trainingId: 'train_' + Math.random().toString(36).substr(2, 9),
634
+ message: 'Training initiated'
635
+ };
636
+ }
637
+ // Live ticker
638
+ async function updateFeed() {
639
+ try {
640
+ const res = await fetch("/grid/feed");
641
+ const data = await res.json();
642
+ document.getElementById('mostar-feed').textContent = data.message;
643
+ } catch (error) {
644
+ console.error('Failed to fetch grid feed:', error);
645
+ }
646
+ }
647
+
648
+ setInterval(updateFeed, 2000);
649
+ updateFeed(); // Initial load
650
+
651
+ // Update stats cards
652
+ async function updateStats() {
653
+ try {
654
+ const res = await fetch("/grid/status");
655
+ const data = await res.json();
656
+
657
+ // Update stats cards
658
+ document.querySelectorAll('.grid-card')[0].querySelector('h3').textContent = data.neural_nodes;
659
+ document.querySelectorAll('.grid-card')[2].querySelector('h3').textContent = data.coherence + '%';
660
+ document.querySelectorAll('.grid-card')[3].querySelector('h3').textContent = data.sync_delay + 's ago';
661
+ } catch (error) {
662
+ console.error('Failed to fetch grid status:', error);
663
+ }
664
+ }
665
+ setInterval(updateStats, 5000);
666
+ updateStats(); // Initial load
667
+ </script>
668
  </body>
669
  </html>
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ ```txt
2
+ fastapi>=0.68.0
3
+ uvicorn>=0.15.0
4
+ pydantic>=1.8.0
5
+ sqlite3
6
+ mostlyai>=2.0.0
7
+ pandas
8
+ ```
script.js ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Modal functionality
2
+ function setupModal(modalId, openBtnId, closeBtnId) {
3
+ const modal = document.getElementById(modalId);
4
+ const openBtn = document.getElementById(openBtnId);
5
+ const closeBtn = document.getElementById(closeBtnId);
6
+
7
+ if (openBtn) {
8
+ openBtn.addEventListener('click', () => {
9
+ modal.style.display = 'flex';
10
+ });
11
+ }
12
+
13
+ if (closeBtn) {
14
+ closeBtn.addEventListener('click', () => {
15
+ modal.style.display = 'none';
16
+ });
17
+ }
18
+
19
+ window.addEventListener('click', (event) => {
20
+ if (event.target === modal) {
21
+ modal.style.display = 'none';
22
+ }
23
+ });
24
+ }
25
+
26
+ // Initialize modals
27
+ document.addEventListener('DOMContentLoaded', () => {
28
+ setupModal('upload-modal', 'upload-btn', 'close-modal');
29
+ setupModal('training-modal', 'train-btn', 'close-training-modal');
30
+
31
+ // File upload interaction
32
+ const fileUpload = document.querySelector('.file-upload');
33
+ const fileInput = document.getElementById('file-input');
34
+
35
+ if (fileUpload && fileInput) {
36
+ fileUpload.addEventListener('click', function() {
37
+ fileInput.click();
38
+ });
39
+
40
+ fileUpload.addEventListener('dragover', function(e) {
41
+ e.preventDefault();
42
+ this.classList.add('border-purple-500', 'bg-purple-900');
43
+ });
44
+
45
+ fileUpload.addEventListener('dragleave', function(e) {
46
+ e.preventDefault();
47
+ this.classList.remove('border-purple-500', 'bg-purple-900');
48
+ });
49
+
50
+ fileUpload.addEventListener('drop', function(e) {
51
+ e.preventDefault();
52
+ this.classList.remove('border-purple-500', 'bg-purple-900');
53
+ // Handle dropped files
54
+ console.log('Files dropped:', e.dataTransfer.files);
55
+ });
56
+ }
57
+
58
+ // Simulate API calls
59
+ async function uploadFile(file, metadata) {
60
+ // In a real implementation, this would call the Flask API
61
+ console.log('Uploading file:', file.name);
62
+ console.log('With metadata:', metadata);
63
+
64
+ // Simulate API delay
65
+ await new Promise(resolve => setTimeout(resolve, 1500));
66
+
67
+ return {
68
+ success: true,
69
+ fileId: 'file_' + Math.random().toString(36).substr(2, 9),
70
+ message: 'File uploaded successfully'
71
+ };
72
+ }
73
+
74
+ async function trainModel(model, fileIds, params) {
75
+ // In a real implementation, this would call the Flask API
76
+ console.log('Training model:', model);
77
+ console.log('With files:', fileIds);
78
+ console.log('Parameters:', params);
79
+
80
+ // Simulate API delay
81
+ await new Promise(resolve => setTimeout(resolve, 2000));
82
+
83
+ return {
84
+ success: true,
85
+ trainingId: 'train_' + Math.random().toString(36).substr(2, 9),
86
+ message: 'Training initiated'
87
+ };
88
+ }
89
+
90
+ // Live training with Mostly AI
91
+ async function trainWithMostlyAI(datasetId, agent) {
92
+ try {
93
+ const res = await fetch(`/grid/train?dataset_id=${datasetId}&agent=${encodeURIComponent(agent)}`, {
94
+ method: 'POST'
95
+ });
96
+ const data = await res.json();
97
+ console.log('Training response:', data);
98
+ return data;
99
+ } catch (error) {
100
+ console.error('Training failed:', error);
101
+ return { success: false, message: 'Training failed' };
102
+ }
103
+ }
104
+
105
+ // Training with real functionality
106
+ const trainBtn = document.getElementById('train-btn');
107
+ if (trainBtn) {
108
+ trainBtn.addEventListener('click', async function() {
109
+ // For demo purposes, we'll use the dataset ID from your example
110
+ const datasetId = '6d8252c3-21a1-499c-b469-7ce2a29cac8e';
111
+ const agent = 'DeepSeek V3.1';
112
+
113
+ // Show training status
114
+ const statusEl = document.getElementById('training-status');
115
+ if (statusEl) {
116
+ statusEl.style.display = 'block';
117
+ statusEl.className = 'training-status progress';
118
+ statusEl.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Training in progress...';
119
+ }
120
+
121
+ const result = await trainWithMostlyAI(datasetId, agent);
122
+
123
+ if (statusEl) {
124
+ if (result.message) {
125
+ statusEl.className = 'training-status success';
126
+ statusEl.innerHTML = `<i class="fas fa-check-circle mr-2"></i> ${result.message}`;
127
+
128
+ // Update ticker with training message
129
+ const tickerEl = document.getElementById('mostar-feed');
130
+ if (tickerEl) {
131
+ tickerEl.innerHTML =
132
+ `🔹 [Training] ${result.message} – Dataset: ${result.dataset} – Agent: ${result.agent}`;
133
+ }
134
+ } else {
135
+ statusEl.className = 'training-status error';
136
+ statusEl.innerHTML = '<i class="fas fa-exclamation-circle mr-2"></i> Training failed';
137
+ }
138
+ }
139
+ });
140
+ }
141
+
142
+ // Live ticker
143
+ async function updateFeed() {
144
+ try {
145
+ const res = await fetch("/grid/feed");
146
+ const data = await res.json();
147
+ const tickerEl = document.getElementById('mostar-feed');
148
+ if (tickerEl) {
149
+ tickerEl.textContent = data.message;
150
+ }
151
+ } catch (error) {
152
+ console.error('Failed to fetch grid feed:', error);
153
+ }
154
+ }
155
+
156
+ setInterval(updateFeed, 2000);
157
+ updateFeed(); // Initial load
158
+
159
+ // Update stats cards
160
+ async function updateStats() {
161
+ try {
162
+ const res = await fetch("/grid/status");
163
+ const data = await res.json();
164
+
165
+ // Update stats cards
166
+ const cards = document.querySelectorAll('.grid-card');
167
+ if (cards.length > 0) {
168
+ cards[0].querySelector('h3').textContent = data.neural_nodes;
169
+ }
170
+ if (cards.length > 2) {
171
+ cards[2].querySelector('h3').textContent = data.coherence + '%';
172
+ }
173
+ if (cards.length > 3) {
174
+ cards[3].querySelector('h3').textContent = data.sync_delay + 's ago';
175
+ }
176
+ } catch (error) {
177
+ console.error('Failed to fetch grid status:', error);
178
+ }
179
+ }
180
+
181
+ setInterval(updateStats, 5000);
182
+ updateStats(); // Initial load
183
+ });
style.css CHANGED
@@ -1,2 +1,205 @@
 
 
 
 
 
1
 
2
- /* This file is not used in the new implementation as all styles are included in the HTML */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --color-bg: #0d0b1e;
3
+ --color-accent: #7f5af0;
4
+ --color-gold: #e5b400;
5
+ }
6
 
7
+ body {
8
+ background-color: var(--color-bg);
9
+ color: #fffffe;
10
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
11
+ }
12
+
13
+ .gradient-bg {
14
+ background: linear-gradient(135deg, #7f5af0, #6a4aa5);
15
+ }
16
+
17
+ .grid-card {
18
+ background: radial-gradient(circle, rgba(127,90,240,0.15) 0%, rgba(13,11,30,0.9) 100%);
19
+ border: 1px solid rgba(127, 90, 240, 0.3);
20
+ transition: all 0.3s ease;
21
+ }
22
+
23
+ .grid-card:hover {
24
+ transform: translateY(-5px);
25
+ box-shadow: 0 10px 20px rgba(0,0,0,0.3);
26
+ border-color: rgba(127, 90, 240, 0.6);
27
+ }
28
+
29
+ .file-upload {
30
+ border: 2px dashed #7f5af0;
31
+ transition: all 0.3s ease;
32
+ }
33
+
34
+ .file-upload:hover {
35
+ background-color: rgba(127, 90, 240, 0.1);
36
+ }
37
+
38
+ .sidebar {
39
+ background-color: #0a0818;
40
+ transition: all 0.3s ease;
41
+ }
42
+
43
+ .sidebar-item:hover {
44
+ background-color: rgba(127, 90, 240, 0.2);
45
+ }
46
+
47
+ .pulse-animation {
48
+ animation: pulse 2s infinite;
49
+ }
50
+
51
+ @keyframes pulse {
52
+ 0% { box-shadow: 0 0 0 0 rgba(127, 90, 240, 0.7); }
53
+ 70% { box-shadow: 0 0 0 10px rgba(127, 90, 240, 0); }
54
+ 100% { box-shadow: 0 0 0 0 rgba(127, 90, 240, 0); }
55
+ }
56
+
57
+ .ticker-feed {
58
+ background: rgba(10, 8, 24, 0.9);
59
+ border-top: 1px solid rgba(127, 90, 240, 0.3);
60
+ color: #e5b400;
61
+ font-size: 0.875rem;
62
+ padding: 0.5rem 1rem;
63
+ white-space: nowrap;
64
+ overflow: hidden;
65
+ }
66
+
67
+ .ticker-content {
68
+ display: inline-block;
69
+ padding-left: 100%;
70
+ animation: ticker 30s linear infinite;
71
+ }
72
+
73
+ @keyframes ticker {
74
+ 0% { transform: translateX(0); }
75
+ 100% { transform: translateX(-100%); }
76
+ }
77
+
78
+ /* Modal Styles */
79
+ .modal {
80
+ display: none;
81
+ position: fixed;
82
+ top: 0;
83
+ left: 0;
84
+ width: 100%;
85
+ height: 100%;
86
+ background-color: rgba(0, 0, 0, 0.5);
87
+ z-index: 1000;
88
+ align-items: center;
89
+ justify-content: center;
90
+ }
91
+
92
+ .modal-content {
93
+ background-color: #1a1a2e;
94
+ border-radius: 8px;
95
+ width: 90%;
96
+ max-width: 500px;
97
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
98
+ }
99
+
100
+ .modal-header {
101
+ padding: 1rem;
102
+ border-bottom: 1px solid #2d2d4d;
103
+ display: flex;
104
+ justify-content: space-between;
105
+ align-items: center;
106
+ }
107
+
108
+ .modal-body {
109
+ padding: 1rem;
110
+ }
111
+
112
+ .modal-footer {
113
+ padding: 1rem;
114
+ border-top: 1px solid #2d2d4d;
115
+ display: flex;
116
+ justify-content: flex-end;
117
+ gap: 0.5rem;
118
+ }
119
+
120
+ /* Form Styles */
121
+ .form-group {
122
+ margin-bottom: 1rem;
123
+ }
124
+
125
+ .form-group label {
126
+ display: block;
127
+ margin-bottom: 0.5rem;
128
+ color: #a0a0c0;
129
+ }
130
+
131
+ .form-group input,
132
+ .form-group select,
133
+ .form-group textarea {
134
+ width: 100%;
135
+ padding: 0.5rem;
136
+ border-radius: 4px;
137
+ border: 1px solid #2d2d4d;
138
+ background-color: #0f0f1e;
139
+ color: #ffffff;
140
+ }
141
+
142
+ .form-group input:focus,
143
+ .form-group select:focus,
144
+ .form-group textarea:focus {
145
+ outline: none;
146
+ border-color: #7f5af0;
147
+ }
148
+
149
+ .btn {
150
+ padding: 0.5rem 1rem;
151
+ border-radius: 4px;
152
+ border: none;
153
+ cursor: pointer;
154
+ font-weight: 500;
155
+ }
156
+
157
+ .btn-primary {
158
+ background-color: #7f5af0;
159
+ color: white;
160
+ }
161
+
162
+ .btn-secondary {
163
+ background-color: #2d2d4d;
164
+ color: #a0a0c0;
165
+ }
166
+
167
+ .btn:hover {
168
+ opacity: 0.9;
169
+ }
170
+
171
+ /* Training Status */
172
+ .training-status {
173
+ padding: 1rem;
174
+ border-radius: 4px;
175
+ margin: 1rem 0;
176
+ display: none;
177
+ }
178
+
179
+ .training-status.progress {
180
+ background-color: #1a1a2e;
181
+ border: 1px solid #7f5af0;
182
+ }
183
+
184
+ .training-status.success {
185
+ background-color: rgba(46, 204, 113, 0.1);
186
+ border: 1px solid #2ecc71;
187
+ }
188
+
189
+ .training-status.error {
190
+ background-color: rgba(231, 76, 60, 0.1);
191
+ border: 1px solid #e74c3c;
192
+ }
193
+
194
+ /* Responsive */
195
+ @media (max-width: 768px) {
196
+ .sidebar {
197
+ width: 100%;
198
+ height: auto;
199
+ position: relative;
200
+ }
201
+
202
+ .main-content {
203
+ margin-left: 0;
204
+ }
205
+ }