new-term-radar
신규 AI 용어를 매일 추적, X·Hugging Face·GitHub 등에서 모델·제품·레포 이름을 빠르게 수집
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Tracks how often a brand's content gets cited by AI answer engines in
response to tracked prompts, and whether the brand is actually named in
those answers and in the pages they cite. This is the real architecture
— FastAPI + Celery/Redis job scheduling + Supabase Postgres + Next.js UI —
with only the engines temporarily swapped for free-tier test ones
(Gemini, OpenRouter) instead of the eventual paid APIs (Perplexity Sonar,
OpenAI direct, xAI Grok, DataForSEO for Google AI Overview).README 전문 보기 ↗Tracks how often a brand's content gets cited by AI answer engines in response to tracked prompts, and whether the brand is actually named in those answers and in the pages they cite. This is the real architecture — FastAPI + Celery/Redis job scheduling + Supabase Postgres + Next.js UI — with only the engines temporarily swapped for free-tier test ones (Gemini, OpenRouter) instead of the eventual paid APIs (Perplexity Sonar, OpenAI direct, xAI Grok, DataForSEO for Google AI Overview).
/frontend Next.js (TypeScript) — UI only. Reads Supabase directly (anon key,
RLS-protected). Triggers fetches via the backend and polls for
live per-prompt/engine status.
/backend Python — FastAPI (API layer) + Celery (worker + beat scheduler).
Every external engine call, citation normalization, and all
Supabase writes (service-role key) happen here.
/supabase SQL migration + seed data.
The frontend never holds engine API keys, the Supabase service-role key, or the Redis connection string. The backend never serves the UI.
Every engine — test or real — implements one interface:
# backend/clients/base.py
class EngineClient(ABC):
async def fetch(self, prompt_text: str) -> RawEngineResponse: ...
backend/tasks.py and the DB-write logic only ever talk to EngineClient,
never to Gemini or OpenRouter specifics. Swapping in Perplexity/OpenAI/Grok/
DataForSEO later means writing one new class in backend/clients/ and
adding one line to ENGINE_CLIENTS in backend/clients/__init__.py —
tasks.py, main.py, and the schema never change.
POST /api/projects/{id}/fetch fans out one Celery task per
(active prompt × engine) and returns immediately with a batch_id. Celery
workers process each task independently — a rate limit or failure on one
prompt/engine never blocks the others. The frontend polls
GET /api/projects/{id}/fetch-status/{batch_id} (backed by the
fetch_batches/fetch_batch_tasks tables) to show live progress. Celery
Beat also fires this fan-out automatically on a schedule — no manual
trigger required.
supabase/migrations/0001_init.sql.
Creates the schema (including fetch_batches/fetch_batch_tasks for
async status tracking), enables basic RLS, seeds the gemini and
openrouter engine rows, and seeds one demo project with prompts.Project URL → both NEXT_PUBLIC_SUPABASE_URL and SUPABASE_URLanon public key → NEXT_PUBLIC_SUPABASE_ANON_KEYservice_role key → SUPABASE_SERVICE_ROLE_KEY (backend only — keep secret)Free tier caveat: Supabase pauses a free project after 7 days of inactivity. If the app "stops working" after a break, un-pause it from the dashboard — no data is lost.
rediss://).CELERY_BROKER_URL and CELERY_RESULT_BACKEND in backend/.env
to that URL with ?ssl_cert_reqs=required appended — e.g.
rediss://default:<password>@<host>:6379?ssl_cert_reqs=required. Without
this, both Celery's redis backend and redis-py's health check refuse to
start against a rediss:// URL (ssl_cert_reqs must be none,
optional, or required — lowercase; CERT_REQUIRED etc. do not work).Free tier: 500K commands/month, 256MB, scales to zero — plenty of headroom for a handful of prompts on a daily schedule. Upstash speaks the standard Redis protocol, so Celery connects to it exactly like any other Redis instance.
📘 Before adding or budgeting for any engine, read
docs/ENGINE-APIS.md. It documents what every engine's payload actually contains (fan-out queries, citations, which sources were read-but-not-cited, sentence-level source mapping), the exact endpoints, and current verified pricing for Gemini, OpenAI, Perplexity, Grok and DataForSEO — written to be readable without a technical background. Verified 22 Aug 2026 against the official docs and against a real captured Gemini payload.Two findings from it that change decisions:
- Gemini 3.x bills per search query, not per prompt. One question that fans out to 7 searches costs 7 units. Switching from 2.5 to 3.6 raised our effective grounding cost roughly 7× for identical prompts.
groundingSupportsis the highest-value field we don't parse. It maps each sentence of an answer to the sources backing it, and it's already sitting in our storedraw_responseJSON — backfillable, no new vendor.
429 raises inside GeminiClient.fetch, which the
Celery task catches via autoretry-style backoff (max_retries=3,
exponential countdown) — it never crashes the batch or retries into a
silent wall.
429 RESOURCE_EXHAUSTED on this project while ungrounded calls return 200.
Reproduced on two keys across two days. Google's pricing page claims 500
free grounded requests/day on the free tier, which contradicts what we
observe. Enabling billing on the Google Cloud project is the reliable
fix — at our volume (~900 searches/month) it sits inside the included
5,000/month block and should cost close to nothing.:free) models give free text, not free citations — real
web-grounded citations need OpenRouter's paid web-search plugin
(~$0.02/request via Exa). By default (OPENROUTER_ENABLE_WEB_SEARCH=false)
this calls a free model and layers on clearly-labeled simulated
citations (is_simulated = true).OPENROUTER_MODEL — two real choices, not a free/paid mistake to avoid:
openai/gpt-oss-20b:free (default in .env.example): genuinely free,
but it's OpenAI's open-weight model, not what ChatGPT actually
runs — its answers don't really represent "what would ChatGPT say."openai/gpt-4o-mini: small real per-token cost, but actually
representative of ChatGPT's behavior for a given query — use this
when the point is to approximate real ChatGPT output, not to stay
free. Combine with OPENROUTER_ENABLE_WEB_SEARCH=true to also get
real citations (the closest replication of ChatGPT's browsing mode).429s are handled the same way as Gemini's.cd backend
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
pip install -r requirements.txt
copy .env.example .env # then fill in the keys from steps 1-3
Then, in three separate terminals (all from backend/, venv activated):
# Terminal 1 — API
uvicorn main:app --reload --port 8000
# Terminal 2 — Celery worker (processes fetch tasks)
celery -A celery_app worker --loglevel=info --pool=solo # --pool=solo on Windows
# Terminal 3 — Celery beat (fires the scheduled fan-out automatically)
celery -A celery_app beat --loglevel=info
GET http://localhost:8000/api/health should return
{"status": "ok", "supabase_connected": true, "redis_connected": true}.
cd frontend
npm install
copy .env.example .env.local # then fill in Supabase URL/anon key
npm run dev
Open http://localhost:3000.
projects.default_country, set when you create it); a prompt
can override it (prompts.country), and the Prompts table has a per-row
market selector plus market filter chips. The resolved code is stamped onto
every raw_responses/citations row it produces, so changing a prompt's
market later never relabels the history it already generated. See
"Country targeting" below for what each engine actually does with it.POST /api/projects/{id}/fetch,
which returns a batch_id immediately. The button then polls
GET /api/projects/{id}/fetch-status/{batch_id} every 2s and shows live
per-prompt/engine status (pending → success / rate_limited / error) as
Celery workers process the queue.FETCH_SCHEDULE_HOUR_UTC in .env) — see backend/celery_beat_schedule.py.
Move this to weekly once the real (paid) engine APIs replace the free-tier
test ones, to stay well under their rate limits.Overview, Prompts, Brands) —
every AI answer is run through one structured-output Gemini Flash call
(backend/classifier.py::classify_answer) that detects which tracked
brands (yours + competitors) are named, in what order, and sentiment
toward yours specifically. Results land in answer_brand_mentions and
raw_responses.brand_sentiment_score/brand_position. If that call fails
(e.g. rate limited — it shares Gemini's quota with the grounding call
itself), brand_mentioned_in_answer falls back to a plain text match
rather than silently defaulting to "not mentioned."domain_types) into Corporate/Editorial/UGC/
Institutional/Reference/Other; each citation gets a free heuristic
content-type label (Listicle/How-To/Review/Product Page/etc. — regex on
the URL, no extra API call). The Top/New/Trending/Losing tabs compare
3-day citation windows — New/Trending/Losing need a few days of history
to populate./sources/gap-analysis) — real cited pages confirmed
to not mention your brand, ranked by citation count./fanouts) — the literal sub-search queries Gemini's
grounding tool issued before answering (groundingMetadata.webSearchQueries,
free, was already in the response). OpenRouter doesn't expose these, so
this page is Gemini-only./perception) — a second prompt type (prompt_type = 'perception') for open brand-description questions, run via a separate
synchronous endpoint (POST /api/projects/{id}/fetch-perception — low
volume, doesn't need Celery batch tracking). Extracts attribute
associations (classify_attributes) into brand_attributes, shown as an
association-score list plus a radar chart (plain SVG, no chart library)
comparing your brand against your top 2 competitors by attribute volume.daily_metrics is upserted per project per
UTC day at the end of every successful fetch task
(backend/metrics.py::refresh_daily_metrics); the Overview KPI row shows
deltas vs. the previous day once there's more than one day of history.None of this needs new paid APIs — it's all built on the same free-tier Gemini/OpenRouter calls, using Gemini Flash as a shared classifier regardless of which engine produced the answer being classified.
Resolution order is prompts.country → projects.default_country →
ENGINE_LOCALE_COUNTRY (the env var is now only a floor for rows predating
migration 0005, not the knob you turn to change markets). The resolved ISO
alpha-2 code is passed into EngineClient.fetch(prompt_text, country), and
each client applies it with whatever its API actually supports:
user_location.country on the openrouter:web_search
server tool (web-search mode only), plus the prompt-level framing below.
The location parameter steers the search; it does not tell the model
who it's writing for, so without the framing the answer is still written
for a generic (usually US) reader while citing local sources.google_search grounding tool
exposes no country parameter (only lat/lng, for Maps-style "near me"
queries); Gemini writes its own search queries from the prompt, so stating
the market there is the only lever that exists.Both engines share one countries.localize_prompt() so the same prompt run
against both is phrased identically — otherwise cross-engine comparison
would be measuring our own wording, not the engines.
Two honest limits: prompt-level framing is a bias, not a guarantee — an engine can still return sources from elsewhere — and neither free-tier engine offers true geo-routed execution (a request actually issued from that country), which is what the paid GEO data APIs sell. Treat the market as "answered for a user in X", not "answered in X".
daily_metrics now carries a country column: '' is the blended
all-markets row the Overview trend reads, and one row per market is written
alongside it on every rollup.
rate_limited with exponential-backoff retries, not lost — just expect a
batch to complete over several minutes rather than all at once.backend/
main.py FastAPI app: CRUD + async fetch trigger/status + health
celery_app.py Celery app config (Upstash Redis broker + backend)
celery_beat_schedule.py Periodic schedule (daily while testing free tiers)
tasks.py Celery tasks — one per (prompt, engine) pair
db.py Supabase service-role client
config.py All env-driven settings
countries.py Supported markets + shared prompt localization
classifier.py Gemini-Flash structured-output classification:
brand mentions/order, sentiment, topic/intent,
domain type, perception attributes
metrics.py Daily rollups into daily_metrics (trend deltas)
perception.py Synchronous perception-prompt run + attribute extraction
normalize.py Domain extraction + heuristic content-type labels
normalizer.py Per-citation enrichment + domain-type cache fill
brand_check.py Fetches cited pages, checks for brand mentions
clients/
base.py EngineClient ABC + Citation/RawEngineResponse models
gemini_client.py Real grounding citations + redirect resolution + fanouts
openrouter_client.py Free/paid-web-search modes
__init__.py ENGINE_CLIENTS registry — add new engines here
models.py Pydantic request/response models
requirements.txt
.env.example
frontend/
app/ Overview, Prompts (+detail), Fanouts, Sources
(+gap-analysis), Brands, Perception
components/
lib/supabase/ anon-key clients (reads + prompt/brand CRUD)
.env.example
supabase/
migrations/0001_init.sql Core schema + async fetch tracking
migrations/0002_analytics.sql Competitor mentions, sentiment/position,
domain types, daily metrics, fanouts, attributes
migrations/0003_content_briefs.sql AI-generated content briefs
migrations/0004_citation_position.sql Citation order within an answer
migrations/0005_prompt_country.sql Per-prompt market targeting
migrations/0006_considered_brands.sql Brands the engine retrieved but never named
migrations/0007_fanout_position.sql Order the engine fired its sub-searches in
docs/
ENGINE-APIS.md What each engine's payload contains, the exact
endpoints, and verified pricing for Gemini,
OpenAI, Perplexity, Grok and DataForSEO.
Non-technical readable. Read before adding an
engine or estimating cost.