add hook.py: terminal demo + claim + logo reveal opening scene (~7s)

This commit is contained in:
ViperEkura 2026-05-19 16:08:12 +08:00
parent 12d587aa92
commit d471cfa276
3 changed files with 100 additions and 0 deletions

View File

@ -32,6 +32,7 @@ Output goes to `output/videos/`.
Files are at the repo root, **not** under `promo/` despite what `README.md` and `PROMO_GUIDE.md` reference in some spots.
```
hook.py # Scene: Hook
architecture.py # Scene: Architecture
continuous_batching.py # Scene: ContinuousBatching
cta.py # Scene: CTA
@ -46,6 +47,7 @@ README.md # Quick-start docs (may reference stale promo/ paths)
| File | Class | Content | Est. duration |
|------|-------|---------|---------------|
| `hook.py` | `Hook` | Terminal demo + GPU comparison + logo reveal | ~18s |
| `transformer.py` | `Transformer` | GQA attention (Q/K/V → RoPE → Attention → O) + spec card | ~35s |
| `continuous_batching.py` | `ContinuousBatching` | 4-stage pipeline + throughput comparison (1.0x vs 3.4x) | ~30s |
| `paged_cache.py` | `PrefixCache` | Paged KV cache: page table, on-demand growth, O(1) free | ~30s |

97
hook.py Normal file
View File

@ -0,0 +1,97 @@
"""AstrAI promo: Hook — terminal demo + GPU comparison + logo reveal (~8s)."""
from manim import *
Text.set_default(font="Times New Roman")
class Hook(Scene):
def construct(self):
BG = "#0d1117"
self.camera.background_color = BG
TERM = "#39ff14"
# ════ 0. Terminal (0.0 2.8s) ════
tw, th = 10.0, 4.8
term_frame = Rectangle(
width=tw, height=th, color=WHITE, stroke_width=1.2,
fill_opacity=0.03, fill_color=TERM,
)
term_frame.to_edge(UP, buff=0.2)
lx = term_frame.get_left()[0] + 0.45
ty = term_frame.get_top()[1] - 0.45
prompt = Text("$ ", font_size=20, color=TERM, font="Consolas")
prompt.move_to([lx, ty, 0], aligned_edge=LEFT)
chat = Text("Hey, write a quicksort for me.",
font_size=18, color=WHITE, font="Consolas")
chat.next_to(prompt, RIGHT, buff=0.08).align_to(prompt, DOWN)
resp = Text(">> ", font_size=18, color=GRAY, font="Consolas")
resp.next_to(prompt, DOWN, buff=0.55).align_to(prompt, LEFT)
hint = Text("Here is the implementation:",
font_size=14, color=GRAY, font="Consolas")
hint.next_to(resp, DOWN, buff=0.20).align_to(prompt, LEFT)
INDENT = 0.27
code_lines = [
("def quicksort(arr):", 0),
("if len(arr) <= 1:", 1),
("return arr", 2),
("pivot = arr[len(arr)//2]", 1),
("left = [x for x in arr if x < pivot]", 1),
("right = [x for x in arr if x >= pivot]", 1),
("return quicksort(left) + [pivot] + quicksort(right)", 1),
]
code_vg = VGroup()
prev = hint
for text, level in code_lines:
cl = Text(text, font_size=13, color=TERM, font="Consolas")
cl.next_to(prev, DOWN, buff=0.08).align_to(prompt, LEFT).shift(RIGHT * level * INDENT)
code_vg.add(cl)
prev = cl
self.play(FadeIn(term_frame), run_time=0.3)
self.play(Write(prompt), run_time=0.1)
self.play(AddTextLetterByLetter(chat, time_per_char=0.018))
self.play(Write(resp), run_time=0.12)
self.play(Write(hint, lag_ratio=1.0), run_time=0.15)
self.play(Write(code_vg, lag_ratio=1.0), run_time=1.2)
self.play(
FadeOut(term_frame), FadeOut(prompt), FadeOut(chat),
FadeOut(resp), FadeOut(hint), FadeOut(code_vg),
run_time=0.3,
)
# ════ 1. Statement (2.8 4.0s) ════
s1 = Text("LLMs Are Powerful", font_size=44, color=WHITE)
s2 = Text("but do they really need dozens of GPUs?",
font_size=28, color=GRAY)
VGroup(s1, s2).arrange(DOWN, buff=0.25).move_to(UP * 1.0)
self.play(Write(s1), run_time=0.35)
self.play(Write(s2), run_time=0.3)
self.wait(0.25)
self.play(FadeOut(s1), FadeOut(s2), run_time=0.25)
# ════ 2. Logo (4.0 7.0s) ════
logo = Text("AstrAI", font_size=80, color=BLUE)
glow = Text("AstrAI", font_size=80, color=BLUE_A, fill_opacity=0.3)
glow.move_to(logo).shift(UP * 0.015 + RIGHT * 0.015)
info = VGroup(
Text("1B Params · Single GPU · Open Source",
font_size=22, color=GRAY),
Text("github.com/ViperEkura/AstrAI", font_size=17, color=YELLOW),
).arrange(DOWN, buff=0.18)
everything = VGroup(VGroup(glow, logo), info).arrange(DOWN, buff=0.45)
everything.move_to(ORIGIN)
self.play(Write(logo), run_time=0.45)
self.play(Write(glow), run_time=0.08)
self.play(Write(info), run_time=0.3)
self.wait(1.8)
self.play(FadeOut(everything), run_time=0.4)

View File

@ -8,6 +8,7 @@ from pathlib import Path
ROOT = Path(__file__).parent
SCENES = [
("hook.py", "Hook"),
("transformer.py", "Transformer"),
("architecture.py", "Architecture"),
("continuous_batching.py", "ContinuousBatching"),