Project Info
Inspiration
Percept started with a small family business. Someone close to Dean was trying to grow their restaurant with video ads. From the outside, the process looked simple: make a short ad, choose a budget, launch it, and wait. But from the inside, it felt like guessing in the dark. The budget was tight. Every ad had to count. A failed campaign meant less room for the next idea, less confidence in the next launch, and another week spent wondering what went wrong. When the results finally came back, they were blunt but incomplete. Low clicks. Weak watch time. Poor conversion. The dashboard could say the ad failed, but it could not explain the moment people stopped caring. That gap became our project. Small businesses are not short on effort. They are short on signal. They need a way to understand which video is worth showing before the budget is already gone. So we built Percept: a system that researches, generates, scores, and improves video ads before they go live.
What it does
Percept is a self-improving video ad system. A user enters a product, audience, brand, and goal. For example: Make a 15-second TikTok ad for a high-protein iced coffee aimed at college students before class. Percept then runs a loop: Research the product, audience, and short-form ad patterns. Store that research and iteration history in Redis. Create a structured creative plan. Generate a short-form video using custom skills from the Pika MCP. Predict attention using TRIBE v2. Score the video based on the predicted response over time. Rewrite one part of the creative plan and generate again. The user does not just get one AI-generated video. They get a ranked set of versions, an attention score for each one, and a clear reason for what changed. For example, Percept might find that version one waits too long to show the product. The next version moves the product into the opening shot, keeps the rest of the structure mostly fixed, and runs the scoring loop again. That is the core idea: not just generation, but generation with feedback.
How we built it
Redis and Pika are the backbone of Percept. Redis gives Percept memory. We use Redis for vector retrieval, research storage, caching, and iteration history. When Percept researches a product or audience, that context is saved. When it generates a video, the score is saved. When it rewrites the next version, the change is saved too. That lets Percept track a real creative path: what research shaped the first idea what video was generated how that video scored what changed in the next version whether the score improved or dropped Without Redis, each generation would be isolated. With Redis, every attempt becomes part of the loop. Pika gives Percept production. We use custom skills from the Pika MCP to turn creative plans into real short-form videos. The plan includes the hook, visual beats, product timing, pacing, emotional angle, and call to action. Pika lets us move from text strategy to an actual video that can be scored and improved. TRIBE v2 gives Percept a prediction layer. TRIBE v2 takes video, audio, and language and predicts neural response over time. It does not output “good ad” or “bad ad.” It outputs a time series of predicted brain activity. So we built the scoring layer ourselves. Our score uses three signals: Response strength — how strong the predicted response is overall. Peak response — where the strongest moment happens. Temporal drop-off — where the response fades or flattens. This matters because two videos can have the same average score but feel completely different. One might start strong and die in the middle. Another might build steadily and hold attention until the end. Percept looks at the shape of the response, not just one number. Then an LLM agent receives: the current creative plan the TRIBE v2 score breakdown the prior version history from Redis the allowed creative levers it can change To keep the loop interpretable, the agent changes one main lever at a time: hook, product timing, pacing, visual motion, or call to action. That way, when the score moves, we can understand what likely caused it. Please check out our repo for more details on the Redis memory layer, Pika MCP pipeline, TRIBE v2 scoring code, and generation loop.
Challenges we ran into
The hardest challenge was not making a video. It was knowing what to do after the video was made. Most AI video tools stop at generation. Percept had to evaluate the output and decide what to change next. TRIBE v2 made that possible, but it was not plug-and-play. The model gives predicted neural activity, not marketing advice. We had to build the layer that turns a brain-response time series into a practical attention score. The second challenge was speed. A loop only matters if it can run more than once. Video generation takes time, and TRIBE v2 is heavy. Redis helped us keep the system usable by caching expensive outputs, storing research, and carrying memory across iterations. The third challenge was avoiding fake improvement. Early versions changed too many things at once. If the score went up, we could not tell why. If it dropped, we did not know what broke. So we constrained each rewrite to one main creative lever. Instead of changing the entire ad, Percept makes one targeted move, scores again, and stores the result. That made the system easier to inspect, easier to debug, and more credible as a creative tool.
Accomplishments we're proud of
We built a working loop that closes. Percept researches, creates, predicts, remembers, and tries again. It does not just produce more content. It gives each version a measurable signal and uses that signal to guide the next attempt. We are proud that Redis and Pika became core to the product, not side integrations. Redis is the memory and retrieval layer. Pika is the production layer. Together, they make the loop possible. We are also proud that we got TRIBE v2 running as part of an actual creative workflow. The model’s output is complex, so turning it into a score that can guide iteration was one of the most technically important parts of the project. The moment the product clicked was when one targeted change moved the result: The first ad opened slowly. Percept moved the product earlier. The next version scored higher. That does not guarantee the ad would win in the market. But it does prove the loop works: generate a version, measure a signal, make a controlled change, and run again.
What we learned
We learned that generation is only half the problem. AI can already make more videos than any team can reasonably review. The harder question is which version deserves attention, time, and budget. We also learned that attention has a shape. A video can start strong and fade. It can reveal the product too late. It can look polished and still feel flat. That is why Percept does not only return a score. It tracks how attention moves through the video and uses that pattern to decide what to change next. We also learned to be careful about what the score means. TRIBE v2 gives us a predicted attention proxy, not guaranteed campaign performance. Percept uses that signal as an early creative guide, and the next step is validating it against human preference and real ad metrics.
What's next
Next, we want to make the attention curve visible directly on the video. A user should be able to see where attention rises, where it falls, and what changed between versions. We also want more direct human feedback. During the hackathon, we had dozens of friends try Percept, compare generated versions, and tell us which videos felt more engaging. That gave us an early sanity check, but we want to scale it into a real feedback system: more users, more comparisons, and a stronger link between Percept’s attention score and what people actually choose to watch. Longer term, we want to connect that feedback to real campaign metrics like watch time, click-through rate, and conversion. TRIBE v2 gives us an early predicted attention signal, but the goal is to keep improving that signal with human preference and real-world outcomes. We are starting with short-form ads because the pain is immediate. A small business should not have to spend its budget just to find out that a video did not work. But the same loop can apply to product demos, launch videos, trailers, thumbnails, pitch videos, and education. Generative AI is making it effortless to create more content. That will not be the advantage for long. The advantage will be knowing what is worth showing. Percept is built for that future: creative generation with memory, production, feedback, and judgment.
percept
An interactive explorer for population-average cortical-response predictions from video.
percept turns an uploaded video into a time-scrubbable view of Meta's TRIBE v2 cortical-response predictions. It pairs an anatomical WebGL cortex with frame-level response charts, cortical proxy summaries, and a compact video timeline — and closes the loop by feeding those neuro-signals back into a Redis-native engine that generates and continuously improves short-form video ads.
🔴 Redis is the brain of percept
Submission for "Best Use of Redis." Redis is not a cache we bolted on. It is the entire memory, retrieval, and learning substrate of percept — the connective tissue of a closed-loop, self-improving creative engine. Pull Redis out and there is no product: no grounding, no memory, no learning, no video delivery.
percept uses Redis as a real-time context engine across four Redis vector indexes, a reward-weighted property graph, per-session conversation memory, a semantic LLM cache, and a binary video store — exercising hashes, sets, sorted sets, lists, RedisVL vector search, hybrid tag-filtered search, ranking queries, and atomic reinforcement counters. One database does the work most stacks split across Pinecone + Postgres + Neo4j + a blob store + Redis.
The whole stack on one engine
| Redis capability | Where we use it | What it powers |
|---|---|---|
| Vector search (RedisVL, cosine, flat) | 4 indexes: ad-knowledge, prompt-cache, graph nodes, video frames | Semantic RAG over proven ad science, cache lookup, GraphRAG entry points, natural-language video search |
| Hybrid search (vector + tag filters) | industry, graph, video_id, objects tags | "Beverage principles only", "frames of a person holding a phone in this video" |
Sorted sets (ZADD/ZREVRANGE/ZINCRBY) | Reward-weighted graph adjacency | Beam-search graph traversal and the reinforcement-learning signal |
Atomic counters (HINCRBYFLOAT) | Node performance scores | Creative patterns that win get measurably stronger over time |
Lists (RPUSH/LRANGE/LTRIM + TTL) | Per-session working memory, global agent log | Conversation history that makes re-optimization context-aware |
| Semantic cache (vector distance threshold) | LLM response cache | ~40–77s → ~1s on a similar brief; skips the Opus call entirely |
Binary blob store (SET/GET bytes) | Rendered MP4s served via HTTP Range | The video player streams directly out of Redis |
| Sets + hashes (registries, dedup) | Video/object node registries, edge metadata | Idempotent re-ingestion, multi-tenancy, cross-plugin linking |
1 · Retrieval-Augmented Generation, grounded in Redis Vector Search
Every ad percept generates is grounded in a research-backed corpus of proven advertising science (attention, memory, peak-end, brand distinctiveness, short-form structure, model-specific craft) stored as 59+ vectors in the RedisVL index cerebra_ad_knowledge.
- Query is embedded, not keyword-matched. The brief, product, and industry are embedded with
sentence-transformers/all-MiniLM-L6-v2(384-dim) and run through a RedisVLVectorQuery— cosine distance, flat index, top-k —pipeline/redis_store.py › AdKnowledgeStore.search(). - Hybrid retrieval. Industry is applied as a RedisVL
Tagfilter (Tag("industry") == [industry, "general"]) so retrieval stays on-topic while still surfacing universal principles. - Live research compounds the index. When enabled, Opus 4.8 web-researches winning ads in the space, structures the findings, and upserts them back into the same Redis index — so the knowledge base grows every time it runs (
pipeline/research.py). - Provenance is auditable. Every response carries a
RAGTrace— endpoint, index, embedding model, dimensions, distance metric, retrieved IDs, and live cosine scores — so the UI can prove the creative was grounded in Redis Vector Search, not hallucinated. The Studio panel renders this as "REDIS VECTOR RETRIEVAL" with the real scores.
brief ─► embed (384-d) ─► Redis VectorQuery (cosine + tag filter) ─► top-k ad science ─► Opus 4.8 ─► optimized creative
2 · Semantic Caching — meaning, not strings
Opus optimization is slow and expensive. percept fronts it with a semantic cache (pipeline/redis_store.py › PromptCache, index cerebra_prompt_cache_verified_rag_v4): the brief is embedded and matched against prior briefs by cosine distance under a 0.12 threshold. A semantically similar brief — even reworded — returns the cached, fully-assembled creative without touching the LLM.
- Measured in our live demo: ~40–77s (fresh Opus call) → ~1s (cache hit).
- Cache keys are generation-profile-aware (model, resolution, duration, aspect) so a cached prompt can never leak across incompatible render settings.
3 · Conversation Memory — a creative session that remembers
percept is iterative: a brief becomes a creative, a render, a critique, a re-optimization. Redis gives that loop a memory (pipeline/redis_store.py › SessionMemory).
- Each turn is
RPUSHed to a per-session listcerebra:session:{id}, capped and given a 24h TTL so sessions self-expire. - Prior turns are replayed into Opus's context ("CONVERSATION SO FAR…"), so refinements build on history instead of starting cold.
- A global agent-memory log (
cerebra:runs,LPUSH+LTRIMto 500) records every optimization across all sessions — long-term institutional memory for the system.
4 · The video itself lives in Redis
Stage 2 renders 1080p audio-video through Seedance 2.0. Redis is the delivery layer:
- Prompt→URL generation cache (
cerebra:gen:seedance2:{hash}) means an identical creative never re-renders. - Full MP4 bytes are stored in Redis (
cerebra:vid:{hash}) and streamed to the browser with HTTP Range support straight from Redis — the<video>element scrubs against Redis-backed bytes, with CDN self-healing if a key is evicted (pipeline/pika.py).
🧩 Two Redis-native MCP plugins
We packaged percept's most novel Redis work as two installable MCP servers — so any agent (Claude included) can use Redis as a graph + vision substrate.
Plugin 1 — Percept Context: GraphRAG on Redis
A reward-weighted property graph built entirely from Redis primitives — no graph database. It treats Redis as a learning knowledge graph of creative strategy.
- Nodes are a RedisVL vector index (
percept_nodes, 384-dim, cosine) — every principle, technique, video, and object is semantically searchable. - Edges are sorted sets:
percept:adj:{graph}:out:{src}:{type}with the edge weight as the score. Traversal is aZREVRANGE(highest-weight neighbors first) — beam search in one command. A reversein:index makes it bidirectional; aSADDedge-type registry enumerates relations. - GraphRAG retrieval = vector search for entry nodes → multi-hop sorted-set traversal → assembled subgraph context (
graph_rag_query,compose_brief). - It learns.
record_outcome(path, reward)walks a winning creative's path and doesZINCRBYon every edge andHINCRBYFLOATon every node score. Strategies that produce high-performing ads literally gain weight in Redis, sotop_performers(a RedisVLFilterQuerysorted by score) surfaces what actually works. This is where the TRIBE v2 neuro-score closes the loop — the reward signal that reinforces the graph. - Multi-tenant by a
graphtag, so isolated projects share one Redis without collision.
MCP tools:
graph_rag_query,search_nodes,add_node,link_nodes,neighbors,record_outcome,top_performers,graph_stats,compose_brief,seed_demo_graph.
Plugin 2 — Percept Vision: video understanding as Redis vectors
Turns any video into searchable moments in Redis.
- Frames are sampled, YOLO-detected for objects, and CLIP ViT-B-32 embedded (512-dim) into the RedisVL index
percept_frames. - Natural-language moment search is a
VectorQueryover frame embeddings with hybrid tag filters onvideo_idand pipe-separatedobjects— e.g. "the moment someone smiles holding the can" returns timestamps, deep-links (#t=seconds), thumbnails, and similarity scores (search_moments,ask_video). - Video metadata (
pv:video:{id}), an object-count hash, and apv:videosset registry round out the store. - Cross-plugin magic: ingestion writes video and object nodes into Percept Context's graph and links them with
CONTAINSedges weighted by detection count — deduped through Redis hash registries. So GraphRAG over creative strategy can now reason over what's actually on screen in real footage. Two plugins, one Redis graph.
MCP tools:
ingest_video,search_moments,ask_video,list_video_objects,list_videos,vision_stats.
Why this is the Best Use of Redis
percept is a closed neuro-optimized loop and Redis is every link in it:
brief ─► Redis Vector RAG (ad science) ─► Opus creative ─► Seedance render (stored in Redis)
▲ │
│ ▼
Redis reward-weighted graph ◄─ TRIBE v2 neuro-score ◄─ Percept Vision (Redis frame vectors)
(ZINCRBY / HINCRBYFLOAT: the system gets smarter every cycle)
- Breadth: vector search, hybrid search, sorted-set graph traversal, atomic reinforcement counters, lists + TTL, sets, hashes, and binary blob streaming — in one app.
- Depth: a learning graph (sorted sets as a trainable weight matrix) and a semantic cache that turns 40–77s into 1s.
- Creativity: Redis as a GraphRAG engine and a video frame store and a self-improving knowledge graph — wrapped as reusable MCP plugins.
- Verifiable: every generation ships a Redis
RAGTraceproving the grounding is real.
Quick proof, live:
# RAG is real (cosine scores from Redis, not keyword matching)
curl -s localhost:8100/optimize -d '{"brief":"15s cold-brew ad","industry":"beverage","session_id":"s1"}' \
-H 'content-type: application/json' | python3 -m json.tool # → rag.backend: "redis"
# Conversation memory is in Redis
redis-cli LRANGE cerebra:session:s1 0 -1 # the turns
redis-cli TTL cerebra:session:s1 # 24h auto-expiry
# Semantic cache hit (same call again returns cached:true in ~1s)
redis-cli FT.INFO cerebra_prompt_cache_verified_rag_v4 | grep num_docs
What it includes
- Video upload, playback, and frame-accurate timeline scrubbing
- Live WebGL view of the fsaverage5 pial cortical surface
- Four explicitly labelled cortical surface-proxy summaries
- Response charts, proxy breakdowns, and a model-provenance audit strip
- Multiple visual colour schemes
How it works
With the local worker running, percept sends an uploaded video to facebook/tribev2. The model extracts video, audio, and language features and returns predicted average-subject fMRI-style responses on the fsaverage5 cortical mesh. The worker then aggregates the surface output over four manually defined display regions for the browser.
The interface also works without the worker as a clearly labelled visual preview using synthetic data.
Run locally
One-command setup
Requirements: Node.js 20+, Python 3.11 or 3.12, and ffmpeg.
chmod +x run.sh
./run.sh
The launcher creates a local Python environment, installs worker dependencies as needed, finds free ports, starts the TRIBE v2 worker and Next.js app, and connects them automatically.
TRIBE v2's language feature path can require access to Meta's gated meta-llama/Llama-3.2-3B model. Add a Hugging Face read token if needed:
HF_TOKEN=hf_your_token ./run.sh
For a persistent local setup, put HF_TOKEN in .env.local; that file is ignored by Git.
Run the frontend only
npm install
npm run dev
Without TRIBEV2_API_URL, the UI remains usable in visual-preview mode.
Run the worker in Docker
cd worker
docker build -t cerebra-tribev2 .
docker run --rm -p 8000:8000 \
-e HF_TOKEN=your_huggingface_read_token \
-v tribev2-cache:/data/cache cerebra-tribev2
Then set TRIBEV2_API_URL=http://localhost:8000 in .env.local and restart the frontend.
Scientific scope
TRIBE v2 predicts population-average cortical responses to naturalistic stimuli. percept's four surface regions are manually defined display proxies. They are not direct measurements of emotion, reward, desire, intent, self-relevance, memory encoding, subcortical activity, an individual viewer's mental state, or health.
percept is a research/visualization interface—not an fMRI scanner, diagnostic tool, or behavioral truth machine.
Development checks
npm run lint
npm run build
Analysis
View
Metric
- 76
- 53
- 23
- 7
- 3
- 2
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FastAPIIn code
- Next.jsIn code
- OpenAIIn code
- PythonIn code
- ReactIn code
- RedisIn code
- SQLIn code
- SupabaseIn code
- Tailwind CSSIn code
- TypeScriptIn code
- Node.jsClaimed
12 of 13 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeConfig · Commits
- CodexConfig
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
674 KB
Source files
95
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
edrlu/Percept
723 files · 852.2 MB · @ 000f26d
Structure
Interface
14 files · 2%Screens, components and styles rendered to the user.
API & routing
14 files · 2%Request entry points: routes, handlers and controllers.
Application logic
236 files · 33%Domain rules, services and shared utilities.
+40 moreBackground jobs
6 files · 1%Work run outside a request: tasks, workers and schedules.
Data & schema
1 file · 0%Schema definitions, migrations and data access.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python33%
- TypeScript33%
- Markdown22%
- CSS10%
- Shell2%
- SQL0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
package.json
npm · 13- @types/three
- next
- react
- react-dom
- three
- +8 more
percept-vision/pyproject.toml
pypi · 11- mcp
- numpy
- opencv-python-headless
- pillow
- python-dotenv
- redis
- redisvl
- sentence-transformers
- supabase
- ultralytics
- +1 more
pipeline/requirements.txt
pypi · 9- anthropic
- fastapi
- hiredis
- openai
- pydantic
- python-multipart
- redisvl
- sentence-transformers
- uvicorn[standard]
percept-context/pyproject.toml
pypi · 8- mcp
- numpy
- python-dotenv
- redis
- redisvl
- sentence-transformers
- +2 more
terac/package.json
npm · 7- next
- react
- react-dom
- +4 more
worker/requirements.txt
pypi · 6- fastapi
- git
- mne
- nilearn
- python-multipart
- uvicorn[standard]
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.