minimind-o/index.html

739 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MiniMind-O - Train a Tiny Omni Model from Scratch</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
:root {
--mc-grass: #5fa824;
--mc-stone: #7f8c8d;
--mc-wood: #8b5a3c;
--mc-sand: #d4a574;
--mc-gold: #ffd700;
--mc-dark: #1e1e1e;
--mc-light: #f5f5f5;
--primary: #5e72e4;
--accent: #11cdef;
}
* {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.pixel-font {
font-family: 'Press Start 2P', 'Courier New', monospace;
}
body {
background: linear-gradient(180deg, #87ceeb 0%, #e0f6ff 50%, #d4a574 100%);
min-height: 100vh;
padding: 20px;
margin: 0;
}
.container-main {
background: var(--mc-light);
border: 4px solid;
border-color: #fff #ccc #999 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.5),
inset -1px -1px 0 rgba(0,0,0,.5),
3px 3px 0 rgba(0,0,0,.3);
padding: 40px;
max-width: 1200px;
margin: 0 auto;
image-rendering: pixelated;
image-rendering: -moz-crisp-edges;
image-rendering: crisp-edges;
}
/* Logo */
.logo {
max-width: 80%;
height: auto;
image-rendering: pixelated;
display: block;
}
/* Badge Container - between logo and title */
.badge-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
margin: 12px 0 15px 0;
}
.badge-container img {
height: 22px;
}
/* Title Section */
.title-section {
text-align: center;
background: var(--mc-grass);
color: white;
padding: 20px 20px;
border: 3px solid;
border-color: #fff #777 #777 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.3);
margin-bottom: 20px;
}
.title-section h1 {
display: none;
}
.subtitle {
display: none;
}
.tagline {
font-size: 0.85rem;
color: #fff;
margin: 0;
line-height: 1.4;
}
/* Stats Section */
.stats-section {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 12px;
margin: 20px 0;
}
.stat-box {
background: var(--mc-sand);
border: 3px solid;
border-color: #fff #888 #888 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.3),
2px 2px 0 rgba(0,0,0,.2);
padding: 15px;
text-align: center;
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
}
.stat-box h3 {
margin: 0;
font-size: 1.4rem;
color: #333;
text-shadow: 1px 1px 0 rgba(255,255,255,.8);
}
.stat-box p {
margin: 6px 0 0 0;
font-size: 0.7rem;
color: #555;
font-weight: bold;
}
/* Feature Cards */
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 15px;
margin: 25px 0;
}
.feature-card {
background: var(--mc-light);
border: 3px solid;
border-color: #fff #888 #888 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.5),
inset -1px -1px 0 rgba(0,0,0,.2),
3px 3px 0 rgba(0,0,0,.2);
padding: 15px;
background: linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%);
transition: transform 0.1s, box-shadow 0.1s;
}
.feature-card:hover {
transform: translate(-2px, -2px);
box-shadow: inset 1px 1px 0 rgba(255,255,255,.5),
inset -1px -1px 0 rgba(0,0,0,.2),
5px 5px 0 rgba(0,0,0,.3);
}
.feature-card h3 {
margin: 0 0 8px 0;
color: var(--mc-grass);
font-size: 0.9rem;
}
.feature-card p {
margin: 0;
color: #555;
font-size: 0.75rem;
line-height: 1.4;
}
/* Section Headers */
.section-header {
background: var(--mc-stone);
color: white;
padding: 12px 15px;
border: 3px solid;
border-color: #fff #555 #555 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.3);
margin: 25px 0 15px 0;
font-size: 1rem;
font-weight: bold;
text-shadow: 1px 1px 0 rgba(0,0,0,.5);
}
/* Models Table */
.models-table {
margin: 18px 0;
overflow-x: auto;
}
.models-table table {
width: 100%;
border-collapse: collapse;
border: 3px solid;
border-color: #fff #888 #888 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.3);
background: var(--mc-light);
}
.models-table thead {
background: var(--mc-wood);
color: white;
}
.models-table thead th {
padding: 10px;
text-align: center;
font-weight: bold;
font-size: 0.8rem;
text-shadow: 1px 1px 0 rgba(0,0,0,.5);
border-right: 2px solid rgba(0,0,0,.2);
}
.models-table tbody tr {
border-bottom: 2px solid #ddd;
}
.models-table tbody tr:nth-child(even) {
background: #f0f0f0;
}
.models-table td {
padding: 8px 10px;
text-align: center;
font-size: 0.8rem;
border-right: 2px solid #ddd;
}
.models-table td:last-child {
border-right: none;
}
.models-table tbody tr:hover {
background: #fffacd !important;
}
/* Changelog */
.changelog-section {
margin: 18px 0;
}
.changelog-item {
background: var(--mc-light);
border: 3px solid;
border-color: #fff #888 #888 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.2),
2px 2px 0 rgba(0,0,0,.15);
padding: 0;
margin: 8px 0;
}
.changelog-header {
background: var(--mc-gold);
color: #333;
padding: 10px 15px;
cursor: pointer;
font-weight: bold;
user-select: none;
display: flex;
justify-content: space-between;
align-items: center;
transition: background 0.1s;
border-bottom: 2px solid #ddd;
font-size: 0.85rem;
}
.changelog-header:hover {
background: #ffed4e;
}
.changelog-header.open {
background: #ffd700;
}
.toggle-icon {
font-size: 0.9rem;
}
.changelog-content {
padding: 12px 15px;
display: none;
background: #fafafa;
font-size: 0.8rem;
}
.changelog-item.open .changelog-content {
display: block;
}
.changelog-content ul {
list-style: none;
padding-left: 0;
margin: 0;
}
.changelog-content li {
padding: 4px 0;
padding-left: 20px;
position: relative;
color: #333;
line-height: 1.3;
}
.changelog-content li:before {
content: "▸";
position: absolute;
left: 0;
color: var(--mc-grass);
font-weight: bold;
}
/* Links Section */
.links-section {
background: var(--mc-grass);
color: white;
padding: 25px;
border: 3px solid;
border-color: #fff #555 #555 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.2),
inset -1px -1px 0 rgba(0,0,0,.3),
3px 3px 0 rgba(0,0,0,.3);
margin: 25px 0;
}
.links-section h2 {
text-align: center;
margin-bottom: 15px;
font-size: 1rem;
text-shadow: 1px 1px 0 rgba(0,0,0,.5);
}
.links-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
}
.pixel-button {
background: var(--mc-sand);
color: #333;
border: 3px solid;
border-color: #fff #888 #888 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.2),
2px 2px 0 rgba(0,0,0,.2);
padding: 8px 14px;
text-decoration: none;
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
transition: all 0.1s;
font-size: 0.75rem;
}
.pixel-button:hover {
border-color: #888 #fff #fff #888;
box-shadow: inset -1px -1px 0 rgba(255,255,255,.3),
inset 1px 1px 0 rgba(0,0,0,.2),
1px 1px 0 rgba(0,0,0,.1);
transform: translate(2px, 2px);
color: #333;
text-decoration: none;
}
.pixel-button:active {
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.2);
transform: translate(3px, 3px);
}
/* Why Section */
.why-section {
background: var(--mc-light);
border: 3px solid;
border-color: #fff #888 #888 #fff;
box-shadow: inset 1px 1px 0 rgba(255,255,255,.3),
inset -1px -1px 0 rgba(0,0,0,.2);
padding: 20px;
margin: 22px 0;
}
.why-section h2 {
color: var(--mc-wood);
margin-bottom: 15px;
font-size: 1rem;
}
.why-section ul {
list-style: none;
padding-left: 0;
margin: 0;
}
.why-section li {
padding: 4px 0;
padding-left: 22px;
position: relative;
color: #333;
line-height: 1.4;
font-size: 0.8rem;
}
.why-section li:before {
content: "→";
position: absolute;
left: 0;
color: var(--mc-grass);
font-weight: bold;
font-size: 0.9rem;
}
.quote {
font-style: italic;
color: #666;
border-left: 4px solid var(--mc-grass);
padding-left: 12px;
margin: 15px 0;
font-size: 0.85rem;
}
/* Visuals */
.visuals-container {
display: flex;
overflow-x: auto;
gap: 12px;
padding: 15px;
background: var(--mc-light);
border: 3px solid #ddd;
margin: 20px 0;
border-radius: 2px;
}
.visuals-container img {
width: auto;
height: auto;
max-height: 450px;
border: 2px solid #999;
image-rendering: auto;
flex-shrink: 0;
object-fit: contain;
}
.visuals-container::-webkit-scrollbar {
height: 10px;
}
.visuals-container::-webkit-scrollbar-track {
background: #e0e0e0;
}
.visuals-container::-webkit-scrollbar-thumb {
background: #999;
border: 1px solid #777;
}
/* Footer */
.footer {
text-align: center;
padding-top: 20px;
border-top: 3px solid #ccc;
margin-top: 25px;
color: #666;
font-size: 0.75rem;
}
.footer a {
color: var(--mc-grass);
text-decoration: none;
font-weight: bold;
}
.footer a:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.container-main {
padding: 20px;
}
.title-section h1 {
font-size: 2.2rem;
}
.stats-section {
grid-template-columns: repeat(2, 1fr);
}
.features-grid {
grid-template-columns: 1fr;
}
.visuals-container {
flex-wrap: wrap;
}
.visuals-container img {
max-width: 100%;
height: auto;
}
}
</style>
</head>
<body>
<div class="container-main">
<!-- Logo -->
<div align="center" style="padding: 30px 0;">
<img src="./images/logo.png" alt="MiniMind-O Logo" class="logo"/>
</div>
<!-- Badges -->
<div class="badge-container">
<img src="https://visitor-badge.laobi.icu/badge?page_id=jingyaogong/minimind-o" alt="Visitor Badge">
<img src="https://img.shields.io/github/stars/jingyaogong/minimind-o?style=social" alt="GitHub Stars">
<img src="https://img.shields.io/github/license/jingyaogong/minimind-o" alt="License">
<img src="https://img.shields.io/github/last-commit/jingyaogong/minimind-o" alt="Last Commit">
</div>
<!-- Title Section -->
<div class="title-section">
<p class="tagline pixel-font">
Train a 0.1B Omni Model from scratch.<br/>
Text. Image. Audio. Streaming Voice.<br/>
Hear the World.
</p>
</div>
<!-- Key Stats -->
<div class="stats-section">
<div class="stat-box">
<h3>0.1B</h3>
<p>Active Parameters</p>
</div>
<div class="stat-box">
<h3>3O</h3>
<p>Text · Image · Audio</p>
</div>
<div class="stat-box">
<h3>MTP</h3>
<p>8-codebook Prediction</p>
</div>
<div class="stat-box">
<h3>24kHz</h3>
<p>Streaming Voice</p>
</div>
</div>
<!-- What You Get -->
<div class="section-header pixel-font">✨ What You Get</div>
<div class="features-grid">
<div class="feature-card">
<h3>🎧 Omni Interaction</h3>
<p>Text, image and audio inputs with streaming speech output.</p>
</div>
<div class="feature-card">
<h3>🧠 Thinker–Talker</h3>
<p>Multimodal understanding and speech generation are decoupled.</p>
</div>
<div class="feature-card">
<h3>⚡ Multi-Token Prediction</h3>
<p>Predict Mimi codebooks in parallel for lower streaming latency.</p>
</div>
<div class="feature-card">
<h3>🎙️ Voice Cloning Beta</h3>
<p>In-context speaker control with reference Mimi codes and CAM++.</p>
</div>
<div class="feature-card">
<h3>🧩 Full Pipeline</h3>
<p>Code, weights and main training data are released together.</p>
</div>
<div class="feature-card">
<h3><EFBFBD> Readable Baseline</h3>
<p>A compact Omni system designed for study and modification.</p>
</div>
</div>
<!-- Models -->
<div class="section-header pixel-font">📦 Models</div>
<div class="models-table">
<table>
<thead>
<tr>
<th>Model</th>
<th>Parameters</th>
<th>Inference Memory</th>
<th>Release</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>minimind-3o-moe</strong></td>
<td>312M-A115M</td>
<td>~1.5 GB</td>
<td>2026.05</td>
</tr>
<tr>
<td><strong>minimind-3o</strong></td>
<td>115M</td>
<td>~1.0 GB</td>
<td>2026.05</td>
</tr>
<tr>
<td><strong>PyTorch weights</strong></td>
<td>Dense / MoE</td>
<td>Training</td>
<td>Released</td>
</tr>
<tr>
<td><strong>Transformers format</strong></td>
<td>Dense / MoE</td>
<td>Inference</td>
<td>Released</td>
</tr>
</tbody>
</table>
</div>
<!-- What's New / Changelog -->
<div class="section-header pixel-font">📰 What's New</div>
<div class="changelog-section">
<div class="changelog-item open">
<div class="changelog-header open" onclick="toggleChangelog(this)">
<span>🔥 2026-05-05</span>
<span class="toggle-icon">−</span>
</div>
<div class="changelog-content">
<ul>
<li>MiniMind-O is open-sourced for the first time, with minimind-3o (115M) and minimind-3o-moe (312M-A115M) released.</li>
<li>Thinker–Talker dual-path architecture: Talker uses MTP to predict multi-layer Mimi codes, supporting 24 kHz streaming voice generation and barge-in interruption.</li>
<li>Audio codec uses Mimi (8 codebooks, 12.5 Hz, 24 kHz); Talker uses a shared backbone with lightweight adapters at the codebook interface.</li>
<li>Speech and vision features are encoded by frozen SenseVoice-Small and SigLIP2, then injected into the MiniMind hidden space through two-layer MLP projectors.</li>
<li>Both mini and full training datasets are released; the mini setup can run through the full Thinker–Talker pipeline on a single RTX 3090 in about 2 hours.</li>
<li>Built-in 5 voice prompts and 7 unseen voice prompts, with voice cloning and phone-mode WebUI support.</li>
</ul>
</div>
</div>
</div>
<!-- Visuals -->
<div class="section-header pixel-font">🎮 Inside MiniMind-O</div>
<div align="center">
<div class="visuals-container">
<img src="./images/architecture.jpg" alt="MiniMind-O Architecture">
<img src="./images/qual_a2a.jpg" alt="A2A Qualitative Examples">
<img src="./images/image2audio_qualitative.jpg" alt="Image to Audio Examples">
</div>
</div>
<!-- Try It Links -->
<div class="links-section">
<h2 class="pixel-font">🎯 Try It Online</h2>
<div class="links-grid">
<a href="https://modelscope.cn/studios/gongjy/MiniMind-O" class="pixel-button">
💬 Online Demo
</a>
<a href="https://www.bilibili.com/video/BV1V1RsBcEMX" class="pixel-button">
🎬 Video Intro
</a>
<a href="http://arxiv.org/abs/2605.03937" class="pixel-button">
📄 Technical Report
</a>
<a href="https://github.com/jingyaogong/minimind-o" class="pixel-button">
🔗 GitHub
</a>
<a href="https://huggingface.co/collections/jingyaogong/minimind-o" class="pixel-button">
🤗 HuggingFace
</a>
</div>
<div style="border-top: 3px solid rgba(255,255,255,.3); margin: 25px 0;"></div>
<h2 class="pixel-font">📦 Get the Code</h2>
<div class="links-grid">
<a href="https://github.com/jingyaogong/minimind-o" class="pixel-button">
GitHub Repo
</a>
<a href="https://huggingface.co/collections/jingyaogong/minimind-o" class="pixel-button">
🤗 HuggingFace
</a>
<a href="https://modelscope.cn/collections/gongjy/MiniMind-O" class="pixel-button">
ModelScope
</a>
</div>
</div>
<!-- Why MiniMind-O -->
<div class="why-section">
<h2>💡 Why MiniMind-O?</h2>
<ul>
<li>Build a complete Omni pipeline around a 0.1B-scale model</li>
<li>Understand Thinker–Talker decoupling from readable code</li>
<li>Study Mimi codebook prediction and streaming voice generation</li>
<li>Experiment with in-context voice cloning in a small system</li>
<li>Reproduce training with released weights and main datasets</li>
<li>Use it as a compact baseline for education and research</li>
</ul>
<p class="quote">
💭 "A tiny Omni baseline, small enough to inspect and complete enough to learn from."
</p>
</div>
<!-- Footer -->
<div class="footer">
<p>
MiniMind-O is a compact Omni baseline for study and reproduction.<br/>
Text, image, audio input · streaming voice output<br/>
Apache-2.0 License ·
<a href="https://github.com/jingyaogong/minimind-o">GitHub</a>
</p>
</div>
</div>
<script>
function toggleChangelog(element) {
const item = element.parentElement;
item.classList.toggle('open');
const icon = element.querySelector('.toggle-icon');
if (item.classList.contains('open')) {
icon.textContent = '−';
} else {
icon.textContent = '+';
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
</body>
</html>