ai
Technical notes on web development, DevOps, and AI integration.
67 articles
- 04:50ai
My Scraper Kept Catching My Own Prompt Echo
An accessibility snapshot caught my own prompt instead of the AI answer. The fix: echo rejection, clipboard-first extraction, and a recover subcommand.
TL;DR: Chat scrapers fail when the answer anchor matches the user's own echoed prompt, so the fix filters template markers and length. Virtualized rendering hides offscreen text anyway, making clipboard reads via the Copy button the reliable data path over DOM snapshots. A .url sidecar written before polling lets the script recover finished answers without resending.
#automation#playwright#qwen - 02:49frontend
The Chat DOM Only Holds Half the Answer
Scraping an AI chat answer from the DOM gets you half of it. The full text lives behind the Copy button, plus a strict output contract.
TL;DR: Chat UIs use virtualization, so most of the AI's answer never exists in the DOM and scrolling won't load it. The fix layers a Copy-button click to read the clipboard, an accessibility tree snapshot, and innerText as fallbacks. The real win: define an output contract upfront — code block plus sentinel marker — so scraping becomes deterministic.
#automation#playwright#llm - 02:34ai
AI Agent Auto-Publishing: Brakes Beat Gas
A blog pipeline that researches, writes, verifies, and publishes on its own, plus the four gates that make it trustworthy.
TL;DR: The author's blog publishes articles fully automatically via a 2-hour cron pipeline that researches, drafts, verifies, and posts without human touch. Safety comes from strong brakes: verification gates that reject bad content, automatic rollback after publishing, and escalation to humans for taste calls. Full-auto is trusted only for mechanical tasks; editorial judgment stays human.
#ai-agents#automation#ci-cd - 02:34backend
Semantic Search on a 1GB VPS Without a Vector DB
Pure-Python cosine, vectors in MariaDB postmeta, embeddings computed locally. Semantic features with no new service on a small server.
TL;DR: Running a blog on a 1GB VPS rules out a vector database, so the author computes bge-m3 embeddings locally via Ollama and stores them as JSON in MariaDB postmeta. Related-article matching and dup-checks use pure-Python cosine similarity, fast enough for around 100 articles. Lesson: for small blogs, skip Qdrant or pgvector until scale demands it.
#python#fastapi#embedding - 02:31ai
My Cron Pipeline Drafts Through a Browser, With Local Backup
Free Qwen chat via Playwright is now the primary draft engine for my article cron, with a local router9 fallback wired like a circuit breaker.
TL;DR: The author scrapes Qwen's free web chat via Playwright, copying answers from the clipboard since virtualized DOM rendering hides long replies. Knowing free tiers die without notice, a circuit breaker routes to local router9 after two failures, giving genuinely separate failure domains. The bet isn't that scraping lasts, just that the pipeline keeps running when it doesn't.
#automation#llm#playwright - 23:24ai
The Night I Copy-Pasted My Style Guide for the Tenth Time
Paste the same style rules ten times and you have a bug, not a habit. One agent skill file now carries the entire editorial voice.
TL;DR: Long prompts packed with style rules kept failing because the agent broke them anyway. Editorial voice is procedural knowledge, so it belongs in an Agent Skills file that loads on demand, not in every prompt. Moving everything to one SKILL.md shrank the prompt from seventy lines to twenty and created a single source of truth.
#agent-skills#writing-style#editorial - 23:00ai
The Search Snippet Said 96%, the Board Said 79.2%
Search snippets claimed 95-96% on SWE-bench Verified. The official board says 79.2%. Four rules to keep benchmark numbers honest.
TL;DR: The author checked the actual SWE-bench Verified leaderboard and found the top score is 79.20%, not the 95%+ figures circulating in search snippets. The gap exposed how easily benchmark numbers get cited without opening primary sources. The fix: log access dates, trust only opened primaries, snippets lose conflicts, report tied scores as-is.
#ai-agents#swe-bench#benchmark - 15:39ai
That Time a Control Flag Showed Up in the Chat Bubble
A raw CTA_FLAG: YES marker leaked into a live chat bubble. The strip regex only matched end-of-string, and the SSE stream bypassed it entirely.
TL;DR: A CTA_FLAG marker leaked into the UI because the model ignored placement instructions and SSE streaming sent chunks before the strip regex ran. The fix moved CTA data into a structured field on the knowledge source, rendered directly by the frontend. Lesson: never parse UI-critical data out of model prose; use structured fields.
#llm#streaming#sse - 00:54frontend
Chat result rows, timeline style: metadata first
The time chip and tags in the chat popup were never a CSS problem. Metadata had to travel from SQL up to the DTO before the UI could dress up.
TL;DR: The popup rows looked flat because the API never sent published_at, tags, or categories—the fix started at the database, lifting metadata through repositories, DTOs, and SSE until the frontend had data to render. The existing TimelineRow component was reused across all three popup contexts instead of copying markup. Total cost: seven files, 214 lines added.
#react#pydantic#sqlmodel