a discord bot for the tootsies server. ask, recap, discuss, ship features by typing.
RESOLVED. Per-surface search controls are now set in
utils/perplexity.py(_SEARCH_CONFIG): every surface getssearch_context_size="medium"and the trend/news surfaces get a recency window (music/discourseweek, recap/chimeinday;askstays unfiltered so evergreen fact-verification pages survive).search()takessearch_context_size/recencyoverrides for the eval harness atscripts/eval_perplexity_params.py.highcontext was deliberately NOT shipped by default (cost is cross-surface) — flip it via the eval if a surface still hedges. The rest of this doc is the original investigation.
utils/perplexity.py calls Perplexity Sonar with only model + messages, so it inherits every default — including search_context_size="low" (shallowest retrieval). Result: low-signal, evergreen filler. Symptom (found while evaluating music posts): every Perplexity response opens with “I can’t verify live trends — results are mostly YouTube mixes / playlist pages.” We were encoding intent as prose in the query string (“last few hours”, “check Twitter/X”) and assuming the API acts on it; those are actually structured API parameters we never set. Fix = set the search-control params (per-surface), eval before/after, ship as its own PR.
Tootsies = Discord bot (“Toots”). utils/perplexity.py wraps Perplexity Sonar to inject real-time web context into 5 surfaces (ask / discourse / recap / chimein / music). Python 3.11, asyncpg, aiohttp. CI gates on ruff check . && mypy . && pytest (all three must pass). Never push to main — branch + PR.
Payload at utils/perplexity.py:74-79:
payload = {"model": _MODEL, "messages": [{"role": "user", "content": query}]}
No search params → all defaults inherited. Biggest culprit is search_context_size="low".
Docs: https://docs.perplexity.ai/api-reference/chat-completions-post and https://docs.perplexity.ai/docs/sonar/filters
| Parameter | Current (default) | Consider | Notes |
|---|---|---|---|
web_search_options.search_context_size |
"low" |
"medium"/"high" |
Likely dominant fix. Low = shallow retrieval → “can’t verify” filler. Cost: sonar ~$5/1k req (low) → ~$12/1k (high). |
search_recency_filter |
none | "week" (music) / "day" (news/chimein) |
Values: hour/day/week/month/year. Cannot combine with date filters. |
search_domain_filter |
none | allowlist Billboard/Pitchfork; or denylist -youtube.com |
Max 20 domains. Allowlist (no prefix) OR denylist (- prefix), not both. |
model |
sonar |
maybe sonar-pro |
Higher quality + cost. |
search_mode |
web |
per-surface | web/academic/sec. Date filters silently ignored in academic. |
week recency, medium+ contextday or hour recencyNote: the query text in build_search_query already says “last few hours” for some surfaces — too tight for music, and prose ≠ parameter regardless.
+search_recency_filter="week": 4 sources, fresh this-week drops (Chxrry, Syd, Young M.A.…)Hedging was intermittent across runs → recency alone isn’t a guaranteed fix; docs point to search_context_size="low" as the bigger lever. Test both.
utils/perplexity.py:31-32 — _API_URL, _MODEL = "sonar"utils/perplexity.py:62 — async def search(self, query, *, purpose=...); payload at lines 74-79 ← the thing to changeutils/perplexity.py:243 — build_search_query(user_input, *, surface, category, channel_name, channel_topic); surface branches: 257 (ask), 273 (discourse), 289 (recap), 298 (chimein)utils/perplexity.py:159 _SOURCES, :164 _CATEGORY_QUERIES, _DEFAULT_TRENDINGpurpose=): cogs/ask.py:198, cogs/discourse.py:258, cogs/chimein.py:358, cogs/recap.py:142, cogs/music.py:185pplx_<purpose> (pplx_ask/discourse/recap/chimein; music uses purpose="music"). See CLAUDE.md event table.search() — per-surface config (recency + context_size, maybe domains) threaded via a new arg or a purpose→config map.search_context_size bump ~doubles per-call cost. Get user sign-off before going high.scripts/eval_music_post.py.search_recency_filter can’t combine with search_after/before_date_filter.Pull PERPLEXITY_API_KEY via Railway GraphQL (pattern in CLAUDE.md “Debugging Railway deploys”):
02da7404-8f48-401e-b960-ca4da938e498, env c6260f06-4fa6-4d59-a0de-dd284f59c815 (production), service $RAILWAY_SERVICE_IDvariables(projectId, environmentId, serviceId) → PERPLEXITY_API_KEYruff check . && mypy . && pytest. No em dashes in string literals (enforced: tests/test_persona.py::test_no_em_dashes_anywhere_in_repo). Branch off main, open PR.
iTunes reference verification: utils/apple_music.py appends whatever iTunes returns for a fuzzy query with zero check that resolved artist/title matches what the model named (wrong-track false-positive risk on the links-only music channel). Separate PR on the music side.