From 2d67046140ee28e0defed7121df2f3f769686888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=90=EC=84=B1=EC=A4=80?= Date: Fri, 3 Jul 2026 11:24:35 +0900 Subject: [PATCH] Add launch video demo script --- docs/launch/demo_video.md | 94 +++++++++++++++++++ docs/launch/promotion_playbook.md | 15 +-- docs/launch/show_hn_draft.md | 2 +- examples/launch_demo.py | 146 ++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+), 7 deletions(-) create mode 100644 docs/launch/demo_video.md create mode 100644 examples/launch_demo.py diff --git a/docs/launch/demo_video.md b/docs/launch/demo_video.md new file mode 100644 index 0000000..f2f99f1 --- /dev/null +++ b/docs/launch/demo_video.md @@ -0,0 +1,94 @@ +# Demo Video Plan + +Goal: a 60-75 second terminal-first video that makes Synaptic Memory's position +obvious without requiring a long explanation. + +Core message: + +> Synaptic Memory is not a vector database replacement. It is the graph, tool, +> and memory layer around documents, SQL rows, embeddings, and RAG agents. + +--- + +## Recommended Video + +Title: + +> Synaptic Memory in 60 seconds + +Recording command: + +```bash +uv run python examples/launch_demo.py +``` + +Fast verification command: + +```bash +uv run python examples/launch_demo.py --no-pause +``` + +Optional recording tools: + +```bash +# Terminal recording +asciinema rec docs/launch/synaptic-memory.cast \ + -c 'uv run python examples/launch_demo.py' + +# GIF export if agg is installed +agg docs/launch/synaptic-memory.cast docs/launch/synaptic-memory.gif +``` + +GUI screen recording also works. Use a large terminal, 120 columns, and a dark +theme. Zoom the terminal enough that text is readable on mobile. + +--- + +## Shot List + +| Time | Screen | Voiceover / caption | +|------|--------|---------------------| +| 0-5s | Title lines | "Synaptic Memory is graph memory for RAG agents." | +| 5-15s | Build graph | "It indexes documents and structured rows without LLM calls by default." | +| 15-35s | Search results | "A query can hit both policy text and support-ticket rows." | +| 35-50s | Feedback | "When evidence helps, record feedback instead of losing that signal." | +| 50-65s | Health metadata | "Events, scores, and health signals live as metadata, not prompt bulk." | +| 65-75s | Closing line | "Start local, then swap backend to PostgreSQL, Kuzu, Qdrant, or MinIO." | + +--- + +## Exact Caption Copy + +Use these short captions if editing the video: + +1. "LLM-free indexing by default" +2. "Documents + SQL rows become one graph" +3. "Search returns evidence, not just chunks" +4. "Feedback becomes memory metadata" +5. "Local first. Infra-ready when you grow." + +--- + +## Social Post With Video + +```text +Synaptic Memory in 60 seconds: + +- build a graph from docs + SQL rows +- search with agent-ready evidence +- record feedback when evidence helps +- inspect memory health metadata +- start local, swap to PostgreSQL/Kuzu/Qdrant later + +https://github.com/PlateerLab/synaptic-memory +``` + +--- + +## Production Notes + +- Keep the recording under 75 seconds. +- Do not show API keys or local private paths. +- Prefer the `--no-pause` run for CI checks, and the default paused run for + screen recording. +- Avoid benchmark claims in the video. Link reports in the post text instead. diff --git a/docs/launch/promotion_playbook.md b/docs/launch/promotion_playbook.md index a0d8413..d13ab22 100644 --- a/docs/launch/promotion_playbook.md +++ b/docs/launch/promotion_playbook.md @@ -48,12 +48,12 @@ Must-have: quickstart. - GitHub topics and description. - GitHub release notes. +- 60-second demo plan and recording command: `docs/launch/demo_video.md`. - Show HN draft: `docs/launch/show_hn_draft.md`. Nice-to-have: -- 30-60 second terminal GIF: - `pip install`, `synaptic-quickstart --json`, `from_data()`, `search()`. +- Exported terminal GIF or short MP4 from `examples/launch_demo.py`. - Architecture image showing documents/SQL -> graph -> EvidenceSearch -> MCP agent tools. - Short Korean post for GeekNews / LinkedIn. @@ -77,6 +77,8 @@ memory health signals. Highlights: - `synaptic-quickstart` for a 5-minute local smoke test. +- `examples/launch_demo.py` for a 60-second launch video over documents, SQL + rows, retrieval feedback, and memory health metadata. - `SynapticGraph.from_data()`, `from_chunks()`, and `from_database()` presets: `local`, `rag`, `agent`, `scale`. - Infrastructure paths for SQLite, PostgreSQL + pgvector, Kuzu, Qdrant, and @@ -164,10 +166,11 @@ https://github.com/PlateerLab/synaptic-memory 1. GitHub release. 2. PyPI release metadata check. -3. HN Show HN. -4. Korean mirror post: GeekNews / LinkedIn. -5. Reddit posts only where allowed. -6. Follow-up technical blog post: +3. Record the 60-second terminal demo from `docs/launch/demo_video.md`. +4. HN Show HN. +5. Korean mirror post: GeekNews / LinkedIn. +6. Reddit posts only where allowed. +7. Follow-up technical blog post: "Why RAG agents need graph tools, not only vector search." --- diff --git a/docs/launch/show_hn_draft.md b/docs/launch/show_hn_draft.md index a56d8b3..4c111fa 100644 --- a/docs/launch/show_hn_draft.md +++ b/docs/launch/show_hn_draft.md @@ -128,7 +128,7 @@ Blockers: Nice-to-have: -- [ ] 30-60 second terminal GIF or asciinema recording. +- [ ] 60-second terminal GIF or MP4 from `docs/launch/demo_video.md`. - [ ] One architecture image for social posts. - [ ] Korean mirror post for GeekNews / LinkedIn. - [ ] A small "RAG vs Synaptic" diagram in the docs. diff --git a/examples/launch_demo.py b/examples/launch_demo.py new file mode 100644 index 0000000..9c75ae4 --- /dev/null +++ b/examples/launch_demo.py @@ -0,0 +1,146 @@ +"""Launch video demo for Synaptic Memory. + +This script is intentionally small and dependency-light so it can be recorded +as a 60-second terminal demo: + + uv run python examples/launch_demo.py + +It demonstrates the launch message: +- mixed documents + structured rows +- deterministic, LLM-free default indexing +- search with event recording +- feedback + memory health metadata +""" + +from __future__ import annotations + +import argparse +import asyncio +import time + +from synaptic import FeedbackSignal, MemoryScope, NodeKind, SynapticGraph +from synaptic.extensions.table_ingester import TableIngester + + +def _pause(enabled: bool, seconds: float = 0.9) -> None: + if enabled: + time.sleep(seconds) + + +def _section(title: str) -> None: + print(f"\n# {title}") + + +async def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + "--no-pause", + action="store_true", + help="Run without recording-friendly pauses.", + ) + args = parser.parse_args() + pause = not args.no_pause + + print("Synaptic Memory") + print("Graph memory for RAG agents: docs + SQL rows + feedback") + print("Default path: no LLM calls at indexing time") + _pause(pause, 1.1) + + graph = SynapticGraph.memory() + await graph.connect() + + try: + _section("1. Build a tiny mixed graph") + await graph.add( + "Refund Policy", + "Refund exceptions require manager approval. VIP customers may receive " + "expedited handling when the original order is delayed.", + kind=NodeKind.RULE, + source="policy/refunds.md", + properties={"source": "policy/refunds.md", "page": "1"}, + ) + await graph.add( + "Shipping Policy", + "Delayed orders over 7 days should be escalated before a refund is denied.", + kind=NodeKind.RULE, + source="policy/shipping.md", + properties={"source": "policy/shipping.md", "page": "2"}, + ) + + await TableIngester().ingest( + graph, + "ticket", + columns=[ + {"name": "id", "type": "str"}, + {"name": "customer", "type": "str"}, + {"name": "tier", "type": "str"}, + {"name": "issue", "type": "str"}, + {"name": "days_delayed", "type": "int"}, + ], + rows=[ + { + "id": "T-1001", + "customer": "Acme Korea", + "tier": "VIP", + "issue": "refund exception for delayed shipment", + "days_delayed": "9", + }, + { + "id": "T-1002", + "customer": "Blue Shop", + "tier": "standard", + "issue": "address change request", + "days_delayed": "1", + }, + ], + primary_key="id", + source_url="demo://support", + ) + + stats = await graph.stats() + print(f"Created graph: {stats.get('total_nodes', 0)} nodes") + print("Sources: 2 policy docs + 2 support ticket rows") + _pause(pause) + + _section("2. Search and record retrieval") + scope = MemoryScope(workspace_id="launch-demo", user_id="support-agent") + result = await graph.search( + "VIP refund exception delayed shipment", + limit=4, + record=True, + scope=scope, + ) + print(f"event_id: {result.event_id}") + for idx, activated in enumerate(result.nodes[:4], 1): + node = activated.node + table = node.properties.get("_table_name", "document") + source = node.properties.get("source", node.source or table) + print(f"{idx}. {node.title:<28} score={activated.activation:.3f} source={source}") + _pause(pause) + + _section("3. Feed back that the evidence helped") + top_node_ids = [activated.node.id for activated in result.nodes[:2]] + await graph.record_feedback( + event_id=result.event_id, + signal=FeedbackSignal.EXPLICIT_POSITIVE, + success=True, + node_ids=top_node_ids, + scope=scope, + ) + print("Recorded explicit positive feedback for the top evidence.") + _pause(pause) + + _section("4. Inspect memory health metadata") + health = await graph.memory_health(scope=scope, persist_signals=False) + print(f"memory_events: {health.memory_events}") + print(f"retrieval_events:{health.retrieval_events}") + print(f"memory_scores: {health.memory_score_count}") + print(f"health_signals: {health.signal_count}") + print("\nNo raw provenance was appended to Node.content.") + print("Swap the backend to PostgreSQL/Kuzu/Qdrant when the corpus grows.") + finally: + await graph.close() + + +if __name__ == "__main__": + asyncio.run(main())