vlalab 0.1.0__py3-none-any.whl → 0.1.1__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.
- vlalab/__init__.py +8 -1
- vlalab/apps/streamlit/app.py +310 -37
- vlalab/apps/streamlit/pages/eval_viewer.py +374 -0
- vlalab/cli.py +1 -1
- vlalab/eval/__init__.py +15 -0
- vlalab/eval/adapters/__init__.py +14 -0
- vlalab/eval/adapters/dp_adapter.py +279 -0
- vlalab/eval/adapters/groot_adapter.py +253 -0
- vlalab/eval/open_loop_eval.py +542 -0
- vlalab/eval/policy_interface.py +155 -0
- {vlalab-0.1.0.dist-info → vlalab-0.1.1.dist-info}/METADATA +12 -70
- {vlalab-0.1.0.dist-info → vlalab-0.1.1.dist-info}/RECORD +16 -9
- {vlalab-0.1.0.dist-info → vlalab-0.1.1.dist-info}/WHEEL +0 -0
- {vlalab-0.1.0.dist-info → vlalab-0.1.1.dist-info}/entry_points.txt +0 -0
- {vlalab-0.1.0.dist-info → vlalab-0.1.1.dist-info}/licenses/LICENSE +0 -0
- {vlalab-0.1.0.dist-info → vlalab-0.1.1.dist-info}/top_level.txt +0 -0
vlalab/__init__.py
CHANGED
|
@@ -38,7 +38,7 @@ Advanced API:
|
|
|
38
38
|
logger.close()
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
__version__ = "0.1.
|
|
41
|
+
__version__ = "0.1.1"
|
|
42
42
|
|
|
43
43
|
# Simple API
|
|
44
44
|
from vlalab.core import (
|
|
@@ -59,6 +59,9 @@ from vlalab.core import (
|
|
|
59
59
|
from vlalab.logging import RunLogger
|
|
60
60
|
from vlalab.schema import StepRecord, RunMeta, ImageRef
|
|
61
61
|
|
|
62
|
+
# Evaluation API
|
|
63
|
+
from vlalab.eval import EvalPolicy, ModalityConfig, OpenLoopEvaluator
|
|
64
|
+
|
|
62
65
|
__all__ = [
|
|
63
66
|
# Version
|
|
64
67
|
"__version__",
|
|
@@ -79,4 +82,8 @@ __all__ = [
|
|
|
79
82
|
"StepRecord",
|
|
80
83
|
"RunMeta",
|
|
81
84
|
"ImageRef",
|
|
85
|
+
# Evaluation API
|
|
86
|
+
"EvalPolicy",
|
|
87
|
+
"ModalityConfig",
|
|
88
|
+
"OpenLoopEvaluator",
|
|
82
89
|
]
|
vlalab/apps/streamlit/app.py
CHANGED
|
@@ -16,6 +16,204 @@ st.set_page_config(
|
|
|
16
16
|
initial_sidebar_state="expanded",
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
+
# Custom CSS for styling and hiding default navigation
|
|
20
|
+
st.markdown("""
|
|
21
|
+
<style>
|
|
22
|
+
/* Hide default Streamlit page navigation */
|
|
23
|
+
[data-testid="stSidebarNav"] {
|
|
24
|
+
display: none !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Hide hamburger menu on pages */
|
|
28
|
+
header[data-testid="stHeader"] {
|
|
29
|
+
background: transparent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Sidebar styling */
|
|
33
|
+
[data-testid="stSidebar"] {
|
|
34
|
+
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[data-testid="stSidebar"] .stMarkdown,
|
|
38
|
+
[data-testid="stSidebar"] .stMarkdown p,
|
|
39
|
+
[data-testid="stSidebar"] .stMarkdown h1,
|
|
40
|
+
[data-testid="stSidebar"] .stMarkdown h2,
|
|
41
|
+
[data-testid="stSidebar"] .stMarkdown h3,
|
|
42
|
+
[data-testid="stSidebar"] .stMarkdown h4 {
|
|
43
|
+
color: #e8e8e8 !important;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
[data-testid="stSidebar"] label,
|
|
47
|
+
[data-testid="stSidebar"] .stTextInput label,
|
|
48
|
+
[data-testid="stSidebar"] .stSelectbox label,
|
|
49
|
+
[data-testid="stSidebar"] .stMultiSelect label {
|
|
50
|
+
color: #d0d0d0 !important;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
[data-testid="stSidebar"] .stCaption,
|
|
54
|
+
[data-testid="stSidebar"] small {
|
|
55
|
+
color: #a0a0a0 !important;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Sidebar title */
|
|
59
|
+
.sidebar-title {
|
|
60
|
+
font-size: 1.8rem;
|
|
61
|
+
font-weight: 700;
|
|
62
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
63
|
+
-webkit-background-clip: text;
|
|
64
|
+
-webkit-text-fill-color: transparent;
|
|
65
|
+
background-clip: text;
|
|
66
|
+
margin-bottom: 0.5rem;
|
|
67
|
+
letter-spacing: -0.5px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.sidebar-subtitle {
|
|
71
|
+
color: #a0a0a0;
|
|
72
|
+
font-size: 0.85rem;
|
|
73
|
+
margin-bottom: 1.5rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* Navigation styling */
|
|
77
|
+
[data-testid="stSidebar"] .stRadio > label {
|
|
78
|
+
color: #ffffff !important;
|
|
79
|
+
font-weight: 500;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[data-testid="stSidebar"] .stRadio > div {
|
|
83
|
+
gap: 0.3rem;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
[data-testid="stSidebar"] .stRadio > div > label {
|
|
87
|
+
padding: 0.6rem 0.8rem;
|
|
88
|
+
border-radius: 8px;
|
|
89
|
+
transition: all 0.2s ease;
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
color: #e8e8e8 !important;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
[data-testid="stSidebar"] .stRadio > div > label span,
|
|
95
|
+
[data-testid="stSidebar"] .stRadio > div > label p {
|
|
96
|
+
color: #e8e8e8 !important;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
[data-testid="stSidebar"] .stRadio > div > label:hover {
|
|
100
|
+
background: rgba(102, 126, 234, 0.25);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
[data-testid="stSidebar"] .stRadio > div > label[data-checked="true"] {
|
|
104
|
+
background: linear-gradient(135deg, rgba(102, 126, 234, 0.4) 0%, rgba(118, 75, 162, 0.4) 100%);
|
|
105
|
+
border-left: 3px solid #667eea;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
[data-testid="stSidebar"] .stRadio > div > label[data-checked="true"] span,
|
|
109
|
+
[data-testid="stSidebar"] .stRadio > div > label[data-checked="true"] p {
|
|
110
|
+
color: #ffffff !important;
|
|
111
|
+
font-weight: 600;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Main content area */
|
|
115
|
+
.main .block-container {
|
|
116
|
+
padding-top: 2rem;
|
|
117
|
+
max-width: 1400px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Home page styling */
|
|
121
|
+
.hero-title {
|
|
122
|
+
font-size: 3rem;
|
|
123
|
+
font-weight: 800;
|
|
124
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
|
|
125
|
+
-webkit-background-clip: text;
|
|
126
|
+
-webkit-text-fill-color: transparent;
|
|
127
|
+
background-clip: text;
|
|
128
|
+
margin-bottom: 0.5rem;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.hero-subtitle {
|
|
132
|
+
font-size: 1.2rem;
|
|
133
|
+
color: #666;
|
|
134
|
+
margin-bottom: 2rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Feature cards */
|
|
138
|
+
.feature-card {
|
|
139
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
|
|
140
|
+
border-radius: 12px;
|
|
141
|
+
padding: 1.5rem;
|
|
142
|
+
margin: 0.5rem 0;
|
|
143
|
+
border-left: 4px solid #667eea;
|
|
144
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.feature-card:hover {
|
|
148
|
+
transform: translateY(-2px);
|
|
149
|
+
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.feature-card h4 {
|
|
153
|
+
color: #1a1a2e;
|
|
154
|
+
margin-bottom: 0.5rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.feature-card p {
|
|
158
|
+
color: #555;
|
|
159
|
+
font-size: 0.9rem;
|
|
160
|
+
margin: 0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Status badges */
|
|
164
|
+
.status-badge {
|
|
165
|
+
display: inline-block;
|
|
166
|
+
padding: 0.2rem 0.6rem;
|
|
167
|
+
border-radius: 20px;
|
|
168
|
+
font-size: 0.75rem;
|
|
169
|
+
font-weight: 600;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.status-supported {
|
|
173
|
+
background: #d4edda;
|
|
174
|
+
color: #155724;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Footer */
|
|
178
|
+
.sidebar-footer {
|
|
179
|
+
color: #666;
|
|
180
|
+
font-size: 0.75rem;
|
|
181
|
+
padding: 1rem 0;
|
|
182
|
+
border-top: 1px solid rgba(255,255,255,0.1);
|
|
183
|
+
margin-top: 2rem;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* Tabs styling */
|
|
187
|
+
.stTabs [data-baseweb="tab-list"] {
|
|
188
|
+
gap: 8px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.stTabs [data-baseweb="tab"] {
|
|
192
|
+
border-radius: 8px 8px 0 0;
|
|
193
|
+
padding: 0.5rem 1rem;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Metrics */
|
|
197
|
+
[data-testid="stMetric"] {
|
|
198
|
+
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
|
199
|
+
padding: 1rem;
|
|
200
|
+
border-radius: 10px;
|
|
201
|
+
border: 1px solid #dee2e6;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* Info boxes */
|
|
205
|
+
.stAlert {
|
|
206
|
+
border-radius: 10px;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Dataframe */
|
|
210
|
+
.stDataFrame {
|
|
211
|
+
border-radius: 10px;
|
|
212
|
+
overflow: hidden;
|
|
213
|
+
}
|
|
214
|
+
</style>
|
|
215
|
+
""", unsafe_allow_html=True)
|
|
216
|
+
|
|
19
217
|
# Setup matplotlib fonts
|
|
20
218
|
try:
|
|
21
219
|
from vlalab.viz.mpl_fonts import setup_matplotlib_fonts
|
|
@@ -25,18 +223,26 @@ except Exception:
|
|
|
25
223
|
|
|
26
224
|
|
|
27
225
|
def main():
|
|
28
|
-
|
|
29
|
-
st.sidebar.markdown("
|
|
226
|
+
# Sidebar header
|
|
227
|
+
st.sidebar.markdown("""
|
|
228
|
+
<div class="sidebar-title">🤖 VLA-Lab</div>
|
|
229
|
+
<div class="sidebar-subtitle">VLA 部署追踪与可视化</div>
|
|
230
|
+
""", unsafe_allow_html=True)
|
|
30
231
|
|
|
31
232
|
# Navigation
|
|
32
233
|
pages = {
|
|
33
|
-
"🏠
|
|
34
|
-
"🔬
|
|
35
|
-
"📊
|
|
36
|
-
"📈
|
|
234
|
+
"🏠 首页": "home",
|
|
235
|
+
"🔬 推理回放": "inference",
|
|
236
|
+
"📊 数据集浏览": "dataset",
|
|
237
|
+
"📈 延迟分析": "latency",
|
|
238
|
+
"🎯 开环评估": "eval",
|
|
37
239
|
}
|
|
38
240
|
|
|
39
|
-
selection = st.sidebar.radio(
|
|
241
|
+
selection = st.sidebar.radio(
|
|
242
|
+
"导航",
|
|
243
|
+
list(pages.keys()),
|
|
244
|
+
label_visibility="collapsed",
|
|
245
|
+
)
|
|
40
246
|
|
|
41
247
|
page_name = pages[selection]
|
|
42
248
|
|
|
@@ -51,52 +257,119 @@ def main():
|
|
|
51
257
|
elif page_name == "latency":
|
|
52
258
|
from vlalab.apps.streamlit.pages import latency_viewer
|
|
53
259
|
latency_viewer.render()
|
|
260
|
+
elif page_name == "eval":
|
|
261
|
+
from vlalab.apps.streamlit.pages import eval_viewer
|
|
262
|
+
eval_viewer.render()
|
|
54
263
|
|
|
55
264
|
# Footer
|
|
56
|
-
st.sidebar.markdown("
|
|
57
|
-
|
|
265
|
+
st.sidebar.markdown("""
|
|
266
|
+
<div class="sidebar-footer">
|
|
267
|
+
VLA-Lab v0.1.1<br>
|
|
268
|
+
<a href="https://github.com/VLA-Lab/VLA-Lab" style="color: #667eea;">GitHub</a>
|
|
269
|
+
</div>
|
|
270
|
+
""", unsafe_allow_html=True)
|
|
58
271
|
|
|
59
272
|
|
|
60
273
|
def show_home_page():
|
|
61
|
-
|
|
274
|
+
# Hero section
|
|
62
275
|
st.markdown("""
|
|
63
|
-
|
|
276
|
+
<div class="hero-title">VLA-Lab</div>
|
|
277
|
+
<div class="hero-subtitle">
|
|
278
|
+
专为 VLA (Vision-Language-Action) 模型设计的实机部署追踪与可视化工具箱
|
|
279
|
+
</div>
|
|
280
|
+
""", unsafe_allow_html=True)
|
|
281
|
+
|
|
282
|
+
st.divider()
|
|
283
|
+
|
|
284
|
+
# Features section
|
|
285
|
+
st.markdown("### ✨ 核心功能")
|
|
64
286
|
|
|
65
|
-
|
|
287
|
+
col1, col2 = st.columns(2)
|
|
66
288
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
289
|
+
with col1:
|
|
290
|
+
st.markdown("""
|
|
291
|
+
<div class="feature-card">
|
|
292
|
+
<h4>🔬 推理回放 Inference Replay</h4>
|
|
293
|
+
<p>
|
|
294
|
+
逐帧回放策略推理过程,支持多相机视角、3D 轨迹可视化、延迟诊断。
|
|
295
|
+
快速定位部署问题。
|
|
296
|
+
</p>
|
|
297
|
+
</div>
|
|
298
|
+
""", unsafe_allow_html=True)
|
|
299
|
+
|
|
300
|
+
st.markdown("""
|
|
301
|
+
<div class="feature-card">
|
|
302
|
+
<h4>📊 数据集浏览 Dataset Viewer</h4>
|
|
303
|
+
<p>
|
|
304
|
+
可视化 Zarr 格式训练数据集,支持 Episode 导航、图像网格、动作轨迹分析。
|
|
305
|
+
</p>
|
|
306
|
+
</div>
|
|
307
|
+
""", unsafe_allow_html=True)
|
|
71
308
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
309
|
+
with col2:
|
|
310
|
+
st.markdown("""
|
|
311
|
+
<div class="feature-card">
|
|
312
|
+
<h4>📈 延迟分析 Latency Analysis</h4>
|
|
313
|
+
<p>
|
|
314
|
+
深度分析控制回路时延:传输延迟、推理延迟、端到端回路时间。
|
|
315
|
+
多运行对比,识别性能瓶颈。
|
|
316
|
+
</p>
|
|
317
|
+
</div>
|
|
318
|
+
""", unsafe_allow_html=True)
|
|
319
|
+
|
|
320
|
+
st.markdown("""
|
|
321
|
+
<div class="feature-card">
|
|
322
|
+
<h4>🎯 开环评估 Open-Loop Eval</h4>
|
|
323
|
+
<p>
|
|
324
|
+
对比模型预测动作与真实动作,计算 MSE/MAE 指标,
|
|
325
|
+
多维度动作可视化。
|
|
326
|
+
</p>
|
|
327
|
+
</div>
|
|
328
|
+
""", unsafe_allow_html=True)
|
|
76
329
|
|
|
77
|
-
|
|
78
|
-
- Transport latency (network)
|
|
79
|
-
- Inference latency (GPU)
|
|
80
|
-
- End-to-end loop time
|
|
330
|
+
st.markdown("### 🔧 支持的框架")
|
|
81
331
|
|
|
82
|
-
|
|
332
|
+
col1, col2, col3 = st.columns([1, 1, 2])
|
|
83
333
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
334
|
+
with col1:
|
|
335
|
+
st.markdown("""
|
|
336
|
+
**RealWorld-DP**
|
|
337
|
+
<span class="status-badge status-supported">✅ 已支持</span>
|
|
338
|
+
""", unsafe_allow_html=True)
|
|
88
339
|
|
|
89
|
-
|
|
340
|
+
with col2:
|
|
341
|
+
st.markdown("""
|
|
342
|
+
**Isaac-GR00T**
|
|
343
|
+
<span class="status-badge status-supported">✅ 已支持</span>
|
|
344
|
+
""", unsafe_allow_html=True)
|
|
90
345
|
|
|
91
|
-
|
|
92
|
-
2. **Browse datasets**: Select "📊 Dataset Viewer" from the sidebar
|
|
93
|
-
3. **Analyze latency**: Select "📈 Latency Analysis" from the sidebar
|
|
346
|
+
st.markdown("### 🚀 快速开始")
|
|
94
347
|
|
|
95
|
-
|
|
348
|
+
st.code("""
|
|
349
|
+
# 1. 安装
|
|
350
|
+
pip install vlalab
|
|
351
|
+
|
|
352
|
+
# 2. 在推理代码中集成日志
|
|
353
|
+
import vlalab
|
|
354
|
+
|
|
355
|
+
logger = vlalab.init(
|
|
356
|
+
project="my_project",
|
|
357
|
+
model="gr00t-n1",
|
|
358
|
+
task="pick_and_place",
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# 3. 记录每步数据
|
|
362
|
+
logger.log_step(
|
|
363
|
+
obs={"images": [img], "state": state},
|
|
364
|
+
action={"values": action},
|
|
365
|
+
timing={"inference_latency_ms": latency},
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# 4. 启动可视化
|
|
369
|
+
# vlalab view
|
|
370
|
+
""", language="python")
|
|
96
371
|
|
|
97
|
-
|
|
98
|
-
🐛 [Report Issues](https://github.com/VLA-Lab/VLA-Lab/issues)
|
|
99
|
-
""")
|
|
372
|
+
st.info("👈 从左侧导航栏选择功能开始使用")
|
|
100
373
|
|
|
101
374
|
|
|
102
375
|
if __name__ == "__main__":
|