tensorus commited on
Commit
96091c2
·
verified ·
1 Parent(s): 0ac2a45

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -56
app.py CHANGED
@@ -1,58 +1,83 @@
1
- # app.py
2
- """
3
- Streamlit frontend application for the Tensorus platform.
4
- New UI structure with top navigation and Nexus Dashboard.
5
- """
6
 
 
7
  import streamlit as st
8
- import json
9
- import time
10
- import requests # Needed for ui_utils functions if integrated
11
- import logging # Needed for ui_utils functions if integrated
12
- import torch # Needed for integrated tensor utils
13
- import os
14
- from pathlib import Path
15
- from typing import List, Dict, Any, Optional, Union, Tuple # Needed for integrated tensor utils
16
- from pages.pages_shared_utils import get_api_status, get_agent_status, get_datasets # Updated imports
17
-
18
- # Work around a Streamlit bug where inspecting `torch.classes` during module
19
- # watching can raise a `RuntimeError`. Removing the module from `sys.modules`
20
- # prevents Streamlit's watcher from trying to access it.
21
- import sys
22
- if "torch.classes" in sys.modules:
23
- del sys.modules["torch.classes"]
24
-
25
- # Ensure Streamlit uses a writable configuration directory.
26
- # Some container environments set $HOME to '/' which is read-only.
27
- # Redirect to '/tmp' and create the '.streamlit' directory if needed.
28
- home = Path(os.environ.get("HOME", "/tmp"))
29
- if home == Path("/"):
30
- home = Path("/tmp")
31
- os.environ["HOME"] = str(home)
32
- (home / ".streamlit").mkdir(parents=True, exist_ok=True)
33
-
34
- # --- Page Configuration ---
35
- st.set_page_config(
36
- page_title="Tensorus Platform",
37
- page_icon="🧊",
38
- layout="wide",
39
- initial_sidebar_state="collapsed" # Collapse sidebar as nav is now at top
40
- )
41
-
42
- # --- Configure Logging (Optional but good practice) ---
43
- logging.basicConfig(level=logging.INFO)
44
- logger = logging.getLogger(__name__)
45
-
46
- # --- Integrated Tensor Utilities (Preserved) ---
47
-
48
- def _validate_tensor_data(data: List[Any], shape: List[int]):
49
- """
50
- Validates if the nested list structure of 'data' matches the 'shape'.
51
- Raises ValueError on mismatch. (Optional validation)
52
- """
53
- if not shape:
54
- if not isinstance(data, (int, float)): raise ValueError("Scalar tensor data must be a single number.")
55
- return True
56
- if not isinstance(data, list): raise ValueError(f"Data for shape {shape} must be a list.")
57
- expected_len = shape[0]
58
- if len(data) != expected_len: raise ValueError(f"Dimension 0 mismatch: Expected {expected_len}, got {len(data)} for shape {shape}.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import json
 
 
 
3
 
4
+ import pandas as pd
5
  import streamlit as st
6
+ from tensorus.mcp_client import TensorusMCPClient, DEFAULT_MCP_URL
7
+
8
+ st.title("Tensorus MCP Client Demo")
9
+ st.markdown("Interact with a Tensorus MCP server without writing any code.")
10
+
11
+ mcp_url = st.text_input("MCP server URL", DEFAULT_MCP_URL)
12
+
13
+
14
+ def run_async(coro):
15
+ return asyncio.run(coro)
16
+
17
+
18
+ st.header("Datasets")
19
+ if st.button("List datasets"):
20
+
21
+ async def _list():
22
+ async with TensorusMCPClient.from_http(url=mcp_url) as client:
23
+ return await client.list_datasets()
24
+
25
+ result = run_async(_list())
26
+ if result:
27
+ st.write(pd.DataFrame(result.datasets, columns=["Datasets"]))
28
+
29
+ create_name = st.text_input("New dataset name")
30
+ if st.button("Create dataset") and create_name:
31
+
32
+ async def _create():
33
+ async with TensorusMCPClient.from_http(url=mcp_url) as client:
34
+ return await client.create_dataset(create_name)
35
+
36
+ res = run_async(_create())
37
+ if res:
38
+ st.success(res.message or "Dataset created")
39
+
40
+ st.header("Ingest Tensor")
41
+ with st.form("ingest"):
42
+ ingest_ds = st.text_input("Dataset", key="ingest_ds")
43
+ tensor_shape = st.text_input("Tensor shape", value="2,2")
44
+ tensor_dtype = st.text_input("Tensor dtype", value="float32")
45
+ tensor_data = st.text_area("Tensor data (JSON)", value="[[0, 0], [1, 1]]")
46
+ metadata = st.text_area("Metadata (JSON)", value="{}")
47
+ submitted = st.form_submit_button("Ingest")
48
+
49
+ if submitted:
50
+ try:
51
+ shape = [int(x) for x in tensor_shape.split(",") if x.strip()]
52
+ data = json.loads(tensor_data)
53
+ meta = json.loads(metadata) if metadata.strip() else None
54
+
55
+ async def _ingest():
56
+ async with TensorusMCPClient.from_http(url=mcp_url) as client:
57
+ return await client.ingest_tensor(
58
+ dataset_name=ingest_ds,
59
+ tensor_shape=shape,
60
+ tensor_dtype=tensor_dtype,
61
+ tensor_data=data,
62
+ metadata=meta,
63
+ )
64
+
65
+ response = run_async(_ingest())
66
+ st.write(response)
67
+ st.success(f"Ingested tensor {response.id}")
68
+ except Exception as e:
69
+ st.error(f"Failed to ingest: {e}")
70
+
71
+ st.header("Run NQL Query")
72
+ query = st.text_input("Query", key="nql_query")
73
+ if st.button("Execute") and query:
74
+
75
+ async def _query():
76
+ async with TensorusMCPClient.from_http(url=mcp_url) as client:
77
+ return await client.execute_nql_query(query)
78
+
79
+ result = run_async(_query())
80
+ if isinstance(result.results, list):
81
+ st.write(pd.DataFrame(result.results))
82
+ else:
83
+ st.json(result.results)