Riset produk TikTok β prompt video, KREA yang urus. (TikTok product research β video prompt, KREA handles it.)
KREA is an agentic AI assistant for TikTok creators. It has one job: help you find a product worth making content about, then hand you a ready-to-paste video prompt that you drop into Gemini. KREA does not generate the video itself β that part is yours.
The app is deliberately lean for personal use: one model, two tools, no database, no login. (KREA's user-facing language is Indonesian; this README and the code comments are in English.)
- Concept: the 3-part flow
- AI model
- Architecture
- End-to-end flow of one message
- Project structure
- Setup & running
- Configuration (.env)
- TikTok API (RapidAPI)
- Tool reference
- API & streaming event reference
- Notes & limitations
A single session with KREA runs sequentially through three parts:
| # | Part | What happens |
|---|---|---|
| 1 | Riset Produk (Product Research) | You name a field/niche (e.g. "skincare", "kitchen gadgets"). KREA calls the search_tiktok tool to see what's trending on TikTok, summarizes it, then suggests concrete products with reasons. You brainstorm with KREA until you pick one product. |
| 2 | Prompt Video (Video Prompt) | Once a product is chosen, KREA calls the make_video_prompt tool and produces a single cinematic video prompt ready to paste. The frontend renders it as a card with a Copy button. |
| 3 | Copy ke Gemini (Copy to Gemini) | KREA does not create the video. You copy the prompt and paste it into Gemini to generate the video yourself. |
The persona and rules for these three parts are injected as the model's
system_instruction (KREA_PERSONA in backend/agents/orchestrator.py) β all of
KREA's output is in Indonesian.
KREA runs on a single model: Google Gemma 4 31B (gemma-4-31b-it), via the
official google-genai SDK, using a Google AI Studio API key (free tier, no
credit card).
This model supports system_instruction, function calling (tools), and
streaming. Because of that, the orchestrator runs a manual function-calling
loop (with automatic_function_calling disabled) so KREA can actually call the
TikTok API and emit card events to the frontend mid-stream.
Browser (React + Vite)
β POST /api/chat (proxied to :8000)
βΌ
FastAPI (backend/main.py)
β StreamingResponse (NDJSON)
βΌ
Orchestrator (backend/agents/orchestrator.py)
β manual function-calling loop βββΊ Google Gemma 4 31B (google-genai, streaming)
β
βββ tool search_tiktok β backend/tiktok.py β RapidAPI TikTok scraper (part 1)
βββ tool make_video_prompt β emit "video_prompt" event to the frontend (part 2)
- No database. Conversation history is kept in-memory per
session_id(theSESSIONSdict in the orchestrator). Restarting the server clears history. Good enough for personal / single-user use. - No authentication. No login/users. All secrets (Google & RapidAPI keys) are
read from
.env; nothing is hardcoded. - NDJSON streaming. The backend streams events line by line; the frontend parses them and updates the timeline in real time.
What happens when you type a message and hit Kirim (Send):
- Frontend (
App.jsx) shows the user bubble, then callsstreamChat()(api.js) βPOST /api/chatwith{ message, session_id }. - Vite dev server proxies
/api/*to FastAPI athttp://localhost:8000. - FastAPI (
main.py) receives the request and returns aStreamingResponsedriven by thestream_chat()generator. - Orchestrator appends the message to the session history, builds the
GenerateContentConfig(persona + tools), and enters the loop:- It streams the model's reply. Each text chunk is emitted as a
{"type":"text"}event ("thought"/reasoning parts are skipped, so they never leak to the user). - If the model requests a function call, KREA executes it:
search_tiktokβ callsbackend/tiktok.py(hits RapidAPI); the result is returned to the model as afunction_responseto continue from.make_video_promptβ emits a{"type":"video_prompt", ...}event to the frontend (the card) and returns a short confirmation to the model.
- The loop continues as long as the model keeps requesting tools; it stops when only text remains.
- It streams the model's reply. Each text chunk is emitted as a
- Frontend accumulates events:
textis appended to KREA's bubble,video_promptrenders aVideoPromptCardwith a Copy button,errorshows aβ οΈ message, anddonestores thesession_idfor the next message.
.
βββ backend/
β βββ main.py # FastAPI: /health + /chat (NDJSON StreamingResponse)
β βββ config.py # Settings from .env (model, tokens, RapidAPI, CORS)
β βββ tiktok.py # TikTok RapidAPI client (search) + defensive parsing
β βββ agents/
β βββ orchestrator.py # Agent loop, 3-part persona, 2 tool schemas, in-memory sessions
βββ frontend/
β βββ index.html
β βββ vite.config.js # proxy /api β :8000
β βββ package.json
β βββ src/
β βββ main.jsx
β βββ App.jsx # chat timeline + composer
β βββ VideoPromptCard.jsx # video-prompt card + Copy button
β βββ api.js # streamChat(): fetch + NDJSON parser
β βββ Markdown.jsx # markdown rendering (react-markdown + remark-gfm)
β βββ styles.css
βββ docs/ # design specs (e.g. UI reskin)
βββ .env.example
βββ requirements.txt
βββ README.md
- Python 3.11+ (developed & tested on 3.12)
- Node.js 18+ (for the frontend)
- Google AI Studio API key (required, free) β https://aistudio.google.com/apikey
- RapidAPI key + a TikTok scraper API subscription (optional; for real-time product research)
python -m venv venv
# Windows PowerShell:
venv\Scripts\Activate.ps1
# macOS/Linux:
# source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # Windows: copy .env.example .env
# Fill in GOOGLE_API_KEY (required) and RAPIDAPI_KEY (optional) in .env
uvicorn backend.main:app --reload --port 8000Verify: open http://localhost:8000/health β
{ "status": "ok", "model": "gemma-4-31b-it", "api_key_set": true, "rapidapi_set": false }cd frontend
npm install
npm run devOpen http://localhost:5173. The dev server automatically proxies /api/* to the
backend on port 8000, so you don't need to configure CORS for local development.
All configuration is via environment variables (see .env.example):
| Variable | Required | Default | Purpose |
|---|---|---|---|
GOOGLE_API_KEY |
β | β | Google AI Studio API key. The alias GEMINI_API_KEY is also accepted. |
MODEL |
gemma-4-31b-it |
The single model KREA uses. | |
MAX_TOKENS |
8192 |
Max output tokens per model turn. | |
RAPIDAPI_KEY |
(empty) | RapidAPI key. Empty = Product Research falls back to brainstorming. | |
RAPIDAPI_HOST |
tiktok-scraper7.p.rapidapi.com |
TikTok scraper provider host. | |
TIKTOK_SEARCH_PATH |
/feed/search |
Search endpoint path. | |
TIKTOK_QUERY_PARAM |
keywords |
Keyword parameter name (keywords or keyword). |
|
TIKTOK_REGION |
ID |
Search region. | |
CORS_ORIGINS |
http://localhost:5173 |
Allowed origins (comma-separated). |
Part 1 (Product Research) calls a TikTok scraper on RapidAPI through
backend/tiktok.py. The client is defensive by design:
- Never raises β on any problem it returns
{"error": "..."}so the agent can recover (e.g. continue brainstorming and remind you to setRAPIDAPI_KEY). - Flexible parsing β
_extract_videos()walks several common JSON shapes (data.videos,aweme_list,item_list,list,items, etc.) and_simplify()normalizes fields (title, author, plays/likes/comments/shares) across providers. - Env-configurable β host, path, parameter name, and region can be changed without touching the code, to match different providers.
β οΈ Important gotcha: RapidAPI sits behind Cloudflare, which blocks the defaulturllibUser-Agent (error code: 1010). Sotiktok.pymust send a browser User-Agent header β this is already handled in the code.
If you don't have a key yet: find one at https://rapidapi.com, subscribe to a TikTok
scraper API, then set RAPIDAPI_KEY. Without a key, KREA still works β Product
Research automatically falls back to brainstorming from the model's general knowledge.
The orchestrator exposes two tools to the model (schemas in TOOLS_JSON):
Searches live TikTok content for a niche/keyword and returns simplified trending videos with engagement stats.
| Param | Type | Required | Notes |
|---|---|---|---|
keywords |
string | β | Search keywords / niche, e.g. "skincare viral". |
count |
integer | Number of videos (default 15, max 30). |
Produces the final, ready-to-paste video prompt for the chosen product. Does not generate a video β just prompt text. Triggers the card on the frontend.
| Param | Type | Required | Notes |
|---|---|---|---|
product |
string | β | The chosen product. |
video_prompt |
string | β | The full cinematic prompt for Gemini. |
concept |
string | One-line concept/angle of the video. |
| Method | Path | Purpose |
|---|---|---|
POST |
/chat |
Streams KREA's reply as NDJSON. Body: { "message": str, "session_id"?: str }. |
GET |
/health |
Status + model + whether the Google/RapidAPI keys are set. |
Note: the frontend calls these via
/api/chatand/api/healthbecause of the Vite proxy; the backend itself only exposes/chatand/health.
type |
Fields | Meaning |
|---|---|---|
text |
text |
A chunk of KREA's reply (streaming). |
video_prompt |
product, concept, video_prompt |
A ready-to-copy video-prompt card. |
error |
error |
An error message (e.g. key not set, Gemini/TikTok error). |
done |
session_id |
End-of-turn marker; store session_id for the next message. |
KREA deploys as two free services: frontend on Netlify, backend on Hugging
Face Spaces (Docker). The browser talks to the backend directly via
VITE_API_BASE, so streaming is not proxied (and not buffered/timed out).
- Create a new Space β SDK Docker (free CPU tier, no credit card).
- Push this repo to the Space (the root
Dockerfile+ README frontmatter make it build automatically; it listens on port7860). - In Settings β Variables and secrets, add:
GOOGLE_API_KEY(secret, required)RAPIDAPI_KEY(secret, optional β for live TikTok research)CORS_ORIGINS= your Netlify URL, e.g.https://your-site.netlify.app
- Note the Space URL:
https://<user>-<space>.hf.space.
- New site from Git β pick this GitHub repo (
netlify.tomlconfigures the build). - Set Environment variable
VITE_API_BASEto your HF Space URL (or edit it innetlify.toml). No trailing slash, no/api. - Deploy. Then set the backend's
CORS_ORIGINSto the resulting Netlify URL.
- Personal MVP: no authentication, no database. History is in-memory per
session_idand is lost when the server restarts. - Secrets stay safe: Google & RapidAPI keys are read from
.env, not hardcoded..envis not committed (see.gitignore). - Google AI Studio free tier has per-minute/per-day request limits. Data on the free tier may be used by Google to improve their products β if sensitive, consider a paid tier.
- KREA does not create videos. The final output is always a prompt that you copy into Gemini yourself.
