Jacid23's picture
Upload 344 files
cf1f373 verified
Raw
History Blame Contribute Delete
5.44 kB
import base64
from pathlib import Path
import gradio as gr
CSS = """
:root {
color-scheme: dark;
}
.gradio-container {
min-height: 100vh;
background:
radial-gradient(circle at 18% 8%, rgba(0, 122, 204, 0.20), transparent 28rem),
radial-gradient(circle at 90% 16%, rgba(80, 180, 150, 0.12), transparent 24rem),
linear-gradient(145deg, #0b0f14 0%, #121821 48%, #070a0f 100%) !important;
color: #eef3f8;
font-family: Inter, Segoe UI, Arial, sans-serif;
}
.main {
max-width: 1120px;
margin: 0 auto;
padding: 36px 20px 44px;
}
.hero {
display: grid;
grid-template-columns: minmax(0, 1.25fr) minmax(280px, 0.75fr);
gap: 28px;
align-items: center;
padding: 24px 0 34px;
}
.eyebrow {
margin: 0 0 12px;
color: #7bb9e8;
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.hero h1 {
margin: 0;
color: #ffffff;
font-size: clamp(2.5rem, 7vw, 5.4rem);
line-height: 0.94;
letter-spacing: 0;
}
.lead {
max-width: 680px;
margin: 22px 0 0;
color: #b8c6d5;
font-size: 1.08rem;
line-height: 1.65;
}
.hero-card,
.panel {
border: 1px solid rgba(180, 198, 213, 0.16);
border-radius: 8px;
background: rgba(13, 19, 28, 0.74);
box-shadow: 0 22px 70px rgba(0, 0, 0, 0.36);
}
.hero-card {
display: grid;
gap: 16px;
padding: 22px;
}
.app-mark {
width: 90px;
height: 90px;
border-radius: 22px;
background: #0f1620;
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.hero-card h2,
.panel h2 {
margin: 0;
color: #ffffff;
font-size: 1.15rem;
}
.hero-card p,
.panel p {
margin: 0;
color: #b8c6d5;
line-height: 1.55;
}
.chips {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 4px;
}
.chip {
border: 1px solid rgba(123, 185, 232, 0.28);
border-radius: 999px;
padding: 6px 10px;
color: #d9ecfb;
background: rgba(0, 122, 204, 0.14);
font-size: 0.86rem;
}
.grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
margin-top: 18px;
}
.panel {
padding: 18px;
}
.section-title {
margin: 36px 0 12px;
color: #ffffff;
font-size: 1.35rem;
}
.flow {
display: grid;
gap: 8px;
padding: 18px;
border: 1px solid rgba(180, 198, 213, 0.14);
border-radius: 8px;
background: rgba(255, 255, 255, 0.045);
color: #d5e2ec;
font-family: Consolas, Monaco, monospace;
font-size: 0.92rem;
}
.flow span {
display: block;
}
.footer-note {
margin-top: 28px;
color: #8393a2;
font-size: 0.92rem;
}
@media (max-width: 820px) {
.hero,
.grid {
grid-template-columns: 1fr;
}
}
"""
def _image_data_uri(path: str) -> str:
image_path = Path(path)
if not image_path.exists():
return ""
encoded = base64.b64encode(image_path.read_bytes()).decode("ascii")
return f"data:image/png;base64,{encoded}"
ICON_URI = _image_data_uri("src/Reachy_OpenWebUI/static/assets/reachy-conversation-app.png")
HTML = f"""
<main class="main">
<section class="hero">
<div>
<p class="eyebrow">Reachy Mini + OpenWebUI</p>
<h1>Reachy OpenWebUI</h1>
<p class="lead">
A phone-style conversation app for Reachy Mini. OpenWebUI handles the model,
transcription, user context, and TTS; the Reachy app handles the robot runtime,
settings UI, local tools, avatars, chat state, and movement.
</p>
</div>
<aside class="hero-card">
<img class="app-mark" src="{ICON_URI}" alt="">
<h2>Project Page</h2>
<p>
This Space is a lightweight overview. The real app runs in the Reachy Mini
app environment where it can access robot audio, camera, speaker, and motion.
</p>
<div class="chips">
<span class="chip">Phone UI</span>
<span class="chip">OpenWebUI TTS</span>
<span class="chip">Robot tools</span>
<span class="chip">Attitudes</span>
</div>
</aside>
</section>
<h2 class="section-title">What It Does</h2>
<section class="grid">
<div class="panel">
<h2>Contacts</h2>
<p>OpenWebUI models and workspaces appear as phone contacts with cached avatars.</p>
</div>
<div class="panel">
<h2>Conversations</h2>
<p>Saved OpenWebUI chat ids can be selected from a phone-style conversation list.</p>
</div>
<div class="panel">
<h2>Motion</h2>
<p>Speech-reactive head movement blends with Reachy-side dances and recorded emotions.</p>
</div>
</section>
<h2 class="section-title">Runtime Flow</h2>
<div class="flow" aria-label="Runtime flow">
<span>Reachy microphone</span>
<span>-> VAD and OpenWebUI transcription</span>
<span>-> OpenWebUI chat completion with Reachy tool specs</span>
<span>-> optional local Reachy tool execution</span>
<span>-> OpenWebUI speech</span>
<span>-> Reachy speaker output plus motion</span>
</div>
<p class="footer-note">
Install from the repository and launch through Reachy Mini Apps for the full robot runtime.
This hosted Space intentionally does not attempt to control hardware.
</p>
</main>
"""
with gr.Blocks(title="Reachy OpenWebUI") as demo:
gr.HTML(HTML)
if __name__ == "__main__":
demo.launch(css=CSS)