AI 资讯
Govee’s smart nugget ice maker makes every iced drink feel like a luxury
For some people, the ice in a beverage is almost as important as the drink itself. That’s the audience Govee had in mind when designing its latest ice maker, the GoveeLife Smart Nugget Ice Maker Pro. This $500 premium smart home gadget is aimed at those who crave what’s called “the good ice,” the soft, chewable […]
AI 资讯
No Agent Grades Its Own Homework
You ask Claude to review your code. It says "looks good, clean, well factored". Of course it does. It wrote that code five minutes ago. You just asked the author to grade his own paper, and he gave himself an A. Having an AI review code works. But not by asking the one who just wrote it. Quality doesn't come from a smarter model, it comes from an architecture where no role checks itself. The self-preference bias This isn't a hunch, it's measured. A model evaluating its own output rates it higher than others' at equal quality: the self-preference bias , documented by Panickssery and co-authors in 2024, and it's causal, not correlational. The model recognizes its own style and prefers it. In practice that means the naive loop "write, then review what you just wrote" is broken by construction. You don't get a review, you get a justification. The agent already decided its code was good the moment it produced it; asking again only confirms. The blind reviewer So the first rule: the reviewer is never the author. In my config, the review agents run in a clean context . They don't see the implementation prompt, they don't know what constraints the author set, they meet the diff like a colleague on Monday morning. And when the author is a known model, the reviewer is from a different family , to break style recognition. One detail matters as much as the rest: the developer's name never enters the reviewer's prompt. No "this was written by a senior", no "review this model's work". The author's identity is exactly the information that triggers the bias. We take it off the table. No finding without a receipt The second trap is the opposite of the first. An AI reviewer, especially in a clean context, tends to over-flag: it invents problems to look useful, it flags "vulnerabilities" that aren't. A review that cries wolf on every line is no better than a complacent one: either way, you stop listening. Hence the receipt rule. Every finding must cite a file:line and pass a check bef
AI 资讯
I Built a Free Apache Kafka Course from Scratch — Here's the Full Curriculum (and What I Got Wrong)
I Built a Free Apache Kafka Course from Scratch — Here's the Full Curriculum (and What I Got Wrong) I spent months building a free Apache Kafka course covering everything from first principles to a real-time analytics platform final project. No paywall. No "premium tier." 9 modules, 470 minutes of content, completely free. Here's the full syllabus, the Python code that actually works, and the honest mistakes I made building the curriculum — so you don't repeat them. Why I Built This Every time someone asked me "how do I learn Kafka?", I sent them to the same 3 places: The official Confluent docs (dense, assumes you already know what you're doing) A $15 Udemy course that spends Module 1 explaining what a computer is A YouTube playlist where half the videos are deleted None of them answered the real question beginners have: why does Kafka exist, and what problem does it actually solve before I write a single line of code? That's the gap I built for. The Problem With Most Kafka Tutorials Most tutorials start with: "Kafka is a distributed event streaming platform..." And then they immediately show you a Docker Compose file with 6 services. Beginners copy-paste it, something breaks, they don't know why, they quit. The real problem is that Kafka is an answer to a specific architectural problem — and if you don't understand the problem first, the solution makes no sense. So Module 1 and 2 of this course don't touch Kafka at all. They build the problem statement from scratch. The Full Syllabus (9 Modules, 470 Minutes) Module 1: Introduction to Kafka — 35 min Not "what is Kafka" — but why event streaming exists at all. What breaks in traditional request-response architectures at scale. Module 2: The Problem Statement — 30 min A real-world scenario: you're building an e-commerce platform. Orders, inventory, notifications, analytics — all tightly coupled. What happens when one service goes down? This module makes the pain visceral before Kafka enters the picture. Module 3: How
AI 资讯
Your console.log Is Lying to You
Open your browser DevTools and run this: const user = { name : " Bob " } console . log ( user ) user . name = " Alice " You would expect the log to show { name: "Bob" } , the value at the time of the console.log call. The collapsed line is what you expect: ▶ Object { name: "Bob" } But expand it, and you will see: name: "Alice" Oops. So what's going on? console.log() is the most-used debugging tool in JavaScript, but it can be subtly unreliable. Not because it is broken, but because it optimizes for speed and interactivity rather than for accuracy . It was built for fast exploration in a live, interactive environment, and those priorities come with tradeoffs that can genuinely mislead you during debugging. Over the next sections, we'll look at a few ways the console can mislead you - and, more importantly, why each one exists. Objects Aren't Snapshots When you pass an object to console.log() in browser DevTools, the browser does not immediately serialize it into a string. Instead, it stores a live reference to that object and defers the actual rendering until you expand the entry. This is called lazy evaluation, and it is what caused the surprise. The collapsed ▶ Object you see is essentially a placeholder: the properties shown inside it are evaluated at the moment you click the arrow, not at the moment you called console.log() . By then, your code has already continued running. That means what you're seeing is not a frozen record of the object at the time of logging, but a live view into whatever the object happens to look like when DevTools renders it. In the example: You log { name: "Bob" } DevTools stores a reference to the user object The code continues executing user.name is mutated to "Alice" You expand the logged object later and see the current state This behavior can feel unintuitive at first, because most developers mentally model console.log() as "print this value right now", but in browser DevTools, it is closer to "show me this object as it exists when
AI 资讯
The ‘Almost Homeless’ Subreddit Is a Stark Glimpse at Soaring Wealth Inequality
As the billionaire class gets richer, the growing online community is offering tips on how to survive with very little.
AI 资讯
From Regex Hell to AI: How I Finally Tamed Messy PDF Invoices
Last month, I spent three days wrestling with 500 PDF invoices. Each one had the same data—vendor name, invoice number, total amount—but the layouts were all over the place. Different fonts, missing headers, tables that somehow broke across pages. I tried regex. I tried OCR with layout analysis. I even tried building a rule-based parser that looked for keywords like "Total:" . Nothing worked reliably. Every time I fixed one pattern, another invoice broke. I was one commit away from throwing my laptop out the window. Then I took a step back. I realized I didn't need to understand every layout variation. I just needed to understand the data . And that's where AI came in. What didn’t work Let me be clear: I tried the usual suspects first. Regex. Classic. I wrote patterns like r"Total\s*:\s*\$?(\d+\.\d{2})" . Worked on 60% of invoices. The rest had "Total Due" or "Amount Total" or the dollar sign in a different place. Regex is great when you control the input. I didn't. OCR with layout parsing. I used Tesseract with --psm 6 and tried to extract lines by bounding boxes. It helped a bit, but tables with merged cells or rotated text threw it off. Plus, I had to write code to guess which box was a field name and which was a value. Rule-based parser. I built a dictionary of known vendors and their layouts. That worked … until I got an invoice from a new vendor. Maintenance became a nightmare. I was solving the wrong problem. Instead of fighting formatting, I needed to focus on meaning . The AI approach that saved me I remembered that large language models are surprisingly good at understanding context. If I could give the model the raw text from a PDF and a description of what I wanted, maybe it could extract the fields directly. Here’s the core idea: treat extraction as a structured generation task. Provide a prompt with a few examples (few-shot) or just describe the schema, and let the model output JSON. I found an API that did exactly this with a simple HTTP call. (Full d
AI 资讯
Indian payments chief thinks AI will be heavily involved in next era of digital payment growth
Dilip Asbe said that newer UPI apps could be more competitive with a viable commercial model
AI 资讯
When SSH commands hit a csh login shell — wrapping every command in /bin/sh -c across the codebase
One day a user reported an oddly asymmetric bug. In the "add new site" modal, picking an SSH profile and clicking "auto-detect WordPress install path" always failed with "no path found." But clicking the WP-CLI path test button on the same SSH connection worked fine . Same credentials, same host — one succeeded, the other failed. Tracing it down, the culprit was an old foe: csh / bash incompatibility on the server side . This post walks through the fix, sweeping the same bug across the rest of the codebase, and the static-analysis test we added to keep it from coming back. The smoking gun — find: 2: unknown primary or operator The server-side error log gave it away: find: 2: unknown primary or operator find itself is POSIX-standard, but it was dying with a mysterious 2 argument. That 2 is the leading number of 2>/dev/null — a redirect that was being passed as a literal argument to find because the shell never interpreted it as a redirect in the first place . Note: 2>/dev/null is the standard way to silently discard stderr in Bourne shell (sh) and bash. csh (C shell) uses different syntax and doesn't recognize it. Sakura Internet defaults users to csh We've documented this before in the four-host investigation of why WP-CLI doesn't run : on Sakura Internet (Japanese host), the default user login shell is csh / tcsh , not bash. This collides with how paramiko (Python's SSH library) works: exec_command runs the command through the user's login shell. Sending find ... 2>/dev/null to a Sakura host means csh tries to interpret it and chokes . That's the real error. The bash/sh idioms that fall over on csh include: 2>/dev/null (redirect) [ -f path ] (test syntax) for X in ...; do ... done (loop) cmd1 && cmd2 (short-circuit) \( ... \) (subshell) These all blow up with "unknown primary or operator" or "Missing }" on csh. "I fixed one site, so they're all fixed" — but they weren't This wasn't our first encounter with this issue. A few release rounds earlier, we'd noticed test
AI 资讯
SMS Pumping Is Draining Your 2FA Budget — and Mobile-Originated iMessage 2FA Fixes It
If you send SMS one-time codes, there's a decent chance you're paying scammers to phone-spam themselves on your dime. It even has a name: SMS pumping . And it's not a rounding error — Elon Musk claimed Twitter was losing ~$60M/year to fake 2FA traffic before they killed SMS 2FA for free accounts. Here's how the scam works, why SMS 2FA is structurally expensive, and why flipping the direction — mobile-originated (MO) 2FA , taken to its logical end over iMessage — fixes both the cost and the fraud at once. What is SMS pumping? SMS pumping (also called AIT — Artificially Inflated Traffic , or SMS toll fraud ) is a scheme where bad actors abuse a form that sends SMS one-time codes. They pump thousands of phone numbers — usually premium ranges they secretly control with a telecom — into your "send me a code" endpoint. You pay for every one of those messages. A cut of that termination fee flows back to the fraudsters via the carrier. The "users" never log in. They were never users. The entire point was to make your verification endpoint dial a meter that pays them. The structure that makes this possible is simple: you, the company, send (and pay for) the message. Every code is revenue for someone in the delivery chain — so there's a direct financial incentive to trigger as many as possible. Why SMS 2FA is expensive even without fraud Even with zero abuse, application-to-person ( A2P SMS ) is a bad cost curve: You pay per message. Volume spikes — a launch, a bot attack, an international audience — turn into surprise bills. International is brutal. Cross-border A2P carries steep carrier surcharges that vary wildly by destination. Carrier fees and registration overhead. In the US you're funneled through A2P 10DLC registration, brand vetting, and per-segment fees before you send a single legit code. So your 2FA line item is pay-per-event , unpredictable , and exploitable . Three bad properties for something that's supposed to be boring infrastructure. The Twitter/X case This
AI 资讯
TeamLab 那片會跟著你走的花海,原理拆解 DIY
TeamLab 那片會跟著你走的花海,原理拆解+DIY 先看這張圖 這是 TeamLab 在東京台場的《呼應燈之森林》。當你走過去,附近的燈會慢慢亮起;你離開後,燈又慢慢暗下去,像是真的森林一樣。 還有另一個作品《花與人的共存》,花叢會跟著你移動——你站的地方,花就開在你腳邊;你離開,花就凋謝。 這兩件作品的核心邏輯是一樣的。這篇文章就來拆解它。 原理一:偵測位置 TeamLab 的互動裝置需要知道「你在哪裡」。 最常見的方法有兩種: 紅外線感應 :在地面下方埋紅外線接收器,你走過時阻擋光線,系統就知道有人在這個位置。缺點是只能測「有沒有人」,不能測「人在哪一個方向」。 深度相機(RealSense / Kinect) :像 Xbox 的體感相機,透過紅外線測量每一個點到你相機的距離,生成一張「深度地圖」。軟體在深度地圖裡找出人體的位置,然後算出座標。 DIY 版本 :一塊 Arduino + 超音波感測器(HC-SR04,大約 60 元)就能做到基本的「有人靠近」偵測。 原理二:控制回應 知道你在哪裡之後,系統要決定「要做什麼回應」。 TeamLab 的做法是 :不是「觸發」,而是「強度變化」 。 傳統的感應燈:感應到人 → 燈全亮 → 人離開 → 燈全滅。 TeamLab 的邏輯:感應到人 → 燈慢慢變亮(0.5 秒)→ 人持續在 → 維持亮度 → 人離開 → 慢慢變暗(2 秒)。 「慢慢」是關鍵。瞬間變化讓人注意到「科技」;緩慢變化讓人以為「這個空間有生命」。 這就是「驚奇設計」的核心: 時機對了,物理反應看起來像生物反應。 原理三:集體行為 最後一個秘密:TeamLab 的裝置很少只有一個「回應」。 通常會有 100-500 個元素(燈、花、光點)。每個元素各自計算自己與你的距離,決定自己的亮度或顏色。 當 500 個燈各自以稍微不同的速度亮起和暗下,你看到的不是「一個燈亮了」,而是「一片森林在你腳下呼吸」。 心理錯覺 :你把「一群各自輕微不同步的簡單反應」,詮釋成「一個整體有意志的生物」。 用 Arduino 自己做一個迷你版 材料: Arduino Uno(大約 200 元) 超音波感測器 HC-SR04(大約 60 元) LED 燈 x 3(大約 15 元) 麵包板和杜邦線 原理很簡單: 超音波感測器偵測距離 距離越近,LED 越亮(用 PWM 訊號控制) 距離越遠,LED 越暗 int trig = 7 ; int echo = 6 ; int led = 9 ; void setup () { Serial . begin ( 9600 ); pinMode ( trig , OUTPUT ); pinMode ( echo , INPUT ); pinMode ( led , OUTPUT ); } void loop () { digitalWrite ( trig , LOW ); delayMicroseconds ( 2 ); digitalWrite ( trig , HIGH ); delayMicroseconds ( 10 ); digitalWrite ( trig , LOW ); long duration = pulseIn ( echo , HIGH ); long distance = duration * 0.034 / 2 ; // 距離越近,LED 越亮 int brightness = map ( distance , 0 , 100 , 255 , 0 ); brightness = constrain ( brightness , 0 , 255 ); analogWrite ( led , brightness ); delay ( 50 ); } 這不是 TeamLab,但這是你自己做的「會呼吸的燈」。每個 maker 都是從這裡開始的。 庭庭:這個看起來很難 真的沒有你想的那麼難。 需要的東西全部可以在蝦皮買到,全部加起來大約 300 元。網路上有超多 Arduino 教學,關鍵字搜「Arduino 超音波 LED」就有幾十篇中文教學。 你不需要懂電子,只需要跟著步驟做,做完會有「哇,我自己做出了一個會亮的東西」的感動。 如果你想更進一步 TeamLab 的進入門檻其實不是技術,是「你要把技術藏在美學後面」。 推薦兩個方向可以繼續研究: p5.js + webcam :用 p5.js 讀取你的 webcam 影像,偵測顏色或移動。相當於用軟體做到 Kinect 的效果,零硬體成本。 Processing + 投影機 :把電腦畫面投射到牆上或地面上,加上感測器,就是一個簡單版互動投影。投影機在蝦皮一兩千元就有。 今日概念 :TeamLab 的魔法不是魔法,是三個原
开发者
【互動藝術 DIY】用 p5.js 做一塊會呼吸的粒子背景(無程式背景可)
【互動藝術 DIY】用 p5.js 做一塊會呼吸的粒子背景 先問自己:阿哲會想動手嗎? 看完這個效果,阿哲可能會想: 「那如果我把粒子排成自己的名字,滑鼠靠近時會散開嗎?」 這就是正確的方向—— 讓讀者想自己動手改參數 ,而不是背程式碼。 這個方法厲害在哪? p5.js 官網有很多炫技的粒子效果,但大部分只是給你看「很厲害」。 這次不一樣——我要教你 用最少程式碼,做出最有呼吸感的互動 。 秘密是:用「距離」控制行為,用「lerp」讓移動變溫柔。 教學順序 先建立粒子:讓一群點組成畫面 教動畫:用 sin() 做出呼吸節奏 教距離感:用 dist() 偵測滑鼠 教溫柔散開:用 lerp() 柔和移動,不是瞬移 最後加美感:透明度、殘影、暖色 第一步:讓粒子回家 class Particle { constructor ( x , y ) { this . homeX = x ; // 記住家的位置 this . homeY = y ; this . x = x ; this . y = y ; } // 讓粒子回家的力量 returnHome () { this . x = lerp ( this . x , this . homeX , 0.05 ); // 每次移動5%的距離 this . y = lerp ( this . y , this . homeY , 0.05 ); } show () { noStroke (); fill ( 255 , 180 , 120 , 200 ); // 暖橙色 ellipse ( this . x , this . y , 4 ); } } 第二步:偵測滑鼠距離 function draw () { for ( let p of particles ) { let d = dist ( mouseX , mouseY , p . x , p . y ); if ( d < 100 ) { // 滑鼠靠近時,輕輕推開 let force = 0.05 * ( 100 - d ) / 100 ; p . x += ( p . x - mouseX ) / d * force ; p . y += ( p . y - mouseY ) / d * force ; } p . returnHome (); p . show (); } } 第三步:加呼吸節奏 let breathPhase = 0 ; function draw () { breathPhase += 0.02 ; let breath = sin ( breathPhase ); // -1 ~ +1 來回循環 background ( 10 , 8 , 5 ); // 暖暗色背景 for ( let p of particles ) { let d = dist ( mouseX , mouseY , p . x , p . y ); if ( d < 100 ) { let force = 0.05 * ( 100 - d ) / 100 ; p . x += ( p . x - mouseX ) / d * force ; p . y += ( p . y - mouseY ) / d * force ; } p . returnHome (); p . show ( breath ); // 把呼吸相位傳進去 } } function show ( breath ) { noStroke (); // 呼吸時變亮,吐氣時變暗 let alpha = map ( breath , - 1 , 1 , 150 , 255 ); fill ( 255 , 180 , 120 , alpha ); ellipse ( this . x , this . y , 4 ); } 第四步:殘影效果 function draw () { // 不要每幀清掉背景,而是蓋一層半透明黑色 fill ( 10 , 8 , 5 , 30 ); rect ( 0 , 0 , width , height ); // ... 其餘粒子邏輯 } 這樣粒子移動時會留下淡淡的光跡——很有沉浸式裝置的 feel。 阿哲可以怎麼玩? 參數 預設值 改成... 效果 感知半徑 100px 50px 只有非常靠近才有反應 回家速度 0.05 0.02 超級慢,像在水裡 回家速度 0.05 0.2 快一點回覆 粒子數量 200 50 稀疏的星塵感 粒子颜色 暖橙 淡粉 更柔和的感覺 延伸練習 把粒子排成自己的名字 :讓粒子組成「阿哲」或英文字母輪廓,滑鼠靠近時文字散開,離開後慢慢聚回來。 滑鼠不是破壞者,是一陣風 :不只是排斥,而是讓粒子沿著滑鼠移動方向飄
AI 资讯
CDP Browser Control: Driving Real Chromium from Python
Playwright and Selenium are great until you hit bot detection. Google OAuth, Cloudflare, and Vercel checkpoints all flag headless browsers. Here's how to control a real Chromium instance via CDP using Python and websockets. Why Not Playwright? Playwright launches a headless browser with automation flags. Even in headed mode with Xvfb, Google detects it. The CDP Approach Launch Chromium with remote debugging: chromium-browser --user-data-dir = /path/to/profile --remote-debugging-port = 9222 --no-first-run Connect via WebSocket in Python: import asyncio , json , websockets , urllib . request async def get_page_ws (): resp = urllib . request . urlopen ( ' http://localhost:9222/json ' ) targets = json . loads ( resp . read ()) for t in targets : if t [ ' type ' ] == ' page ' : return t [ ' webSocketDebuggerUrl ' ] async def cdp_call ( ws , method , params = None ): msg_id = cdp_call . id = getattr ( cdp_call , ' id ' , 0 ) + 1 msg = { ' id ' : msg_id , ' method ' : method } if params : msg [ ' params ' ] = params await ws . send ( json . dumps ( msg )) while True : resp = json . loads ( await ws . recv ()) if resp . get ( ' id ' ) == msg_id : return resp Key Advantages Real browser fingerprint, no automation flags Persistent sessions, cookies survive across runs Google OAuth works, existing sessions carry over No bot detection, it IS a real browser Follow for more tutorials on browser automation and AI agent architecture.
AI 资讯
5 Ferramentas de IA Gratuitas que Todo Desenvolvedor Deveria Usar em 2026
5 Ferramentas de IA Gratuitas que Todo Desenvolvedor Deveria Usar em 2026 A inteligência artificial não é mais o futuro — é o presente. E o melhor: muitas ferramentas poderosas são gratuitas . Neste artigo, vou compartilhar 5 ferramentas de IA que transformaram minha produtividade como desenvolvedor. 1. 🤖 GitHub Copilot (Gratuito para opensource) O Copilot se tornou indispensável para qualquer desenvolvedor. A versão gratuita oferece: Autocomplete de código em tempo real Sugestões contextuais inteligentes Suporte a +30 linguagens Como usar: Instale a extensão no VS Code e comece a digitar. O Copilot sugere código automaticamente. # Exemplo: Digite um comentário e o Copilot gera a função # Função para ler JSON de um arquivo def read_json_file ( filepath ): import json with open ( filepath , ' r ' ) as f : return json . load ( f ) 2. 🔍 Perplexity AI (100% Gratuito) Pesquisa com IA que cite fontes. Perfeito para: Pesquisar documentação Entender conceitos complexos Encontrar soluções para bugs Dica: Use o modo "Pro Search" para respostas mais detalhadas. 3. 🎨 v0.dev (Vercel) — Frontend com IA Gere componentes React/Next.js com descrições em linguagem natural. # Exemplo de prompt: "Um card de produto responsivo com imagem, preço e botão de compra" O v0 gera o código completo, estilizado com Tailwind CSS. 4. 📝 Notion AI (IA gratuita integrada) O Notion permite usar IA para: Resumir documentos longos Gerar templates de código Traduzir conteúdo automaticamente Criar documentação técnica Atalho: Pressione Ctrl/Cmd + J para ativar a IA em qualquer bloco. 5. 🔧 Cursor (Editor com IA) O Cursor é um fork do VS Code com IA integrada nativamente: Chat com IA sobre seu código Edição por comando ("adicione tratamento de erros") Compreensão automática do contexto do projeto Diferencial: Ele lê todo seu projeto e entende o contexto, não apenas o arquivo atual. 💡 Dica Extra: Combinando as Ferramentas O segredo não é usar uma ferramenta isolada, mas combiná-las : Perplexity para pesquisa
开发者
Instagram is testing more ways to customize ‘Your Algorithm’
Instagram users could soon see more ways to tune their content.
AI 资讯
Asian AI startups launch Mythos-like models as Anthropic’s export ban drags on
New models are launching in Asia that promise Mythos-like capabilities without fear of an export ban. U.S. AI labs may never recover this enormous market.
AI 资讯
Framework-Specific Env Patterns
Your schema is portable. But each runtime loads environment variables differently. CtroEnv adapters bridge the gap — same validation logic, different data sources. Node.js: process.env + .env Files The @ctroenv/node adapter loads .env files and wraps process.env : import { defineEnv , string , number } from " @ctroenv/core " import { loadEnv } from " @ctroenv/node " const env = defineEnv ( schema , { source : loadEnv () }) loadEnv() resolves files in order: .env — shared defaults .env.{NODE_ENV} — environment-specific ( .env.development , .env.production ) .env.local — local overrides (gitignored) Later files override earlier ones. process.env takes precedence unless override: true . Monorepo Root loadEnv ({ path : " ../.. " }) // look up two directories for root .env Native Node 22+ Node 22 has built-in process.loadEnvFile() . Use native: true to delegate: loadEnv ({ native : true }) // uses process.loadEnvFile() if available Falls back to the custom parser on older Node versions. System Fallback By default, only file values are returned. With system: true , missing keys fall through to process.env : loadEnv ({ system : true }) Standalone Parser Use parseEnvFile() directly for custom file loading: import { parseEnvFile } from " @ctroenv/node " const content = readFileSync ( " .env.custom " , " utf-8 " ) const vars = parseEnvFile ( content ) Handles quotes, multiline values (backslash continuation), interpolation ( ${VAR} ), comments, and export prefix. Vite: Build-Time Validation The @ctroenv/vite plugin validates during the build: // vite.config.ts import { ctroenvPlugin } from " @ctroenv/vite " export default defineConfig ({ plugins : [ ctroenvPlugin ({ schema : " ./src/env.ts " }), ], }) If DATABASE_URL is missing, the build fails — no broken artifacts shipped. Schema Options Pass a file path or inline definition: // File path — imports the module, looks for `schema` export ctroenvPlugin ({ schema : " ./src/env.ts " }) // Inline definition ctroenvPlugin ({ schem
AI 资讯
VERCEL_EXPERIMENTAL_DEV_SKIP_LINK: Stop Dev Link Hangs
TL;DR If the Vercel CLI keeps trying to open a dev link against your Vercel project during local next dev runs, set VERCEL_EXPERIMENTAL_DEV_SKIP_LINK=1 in the shell that launches the dev server, or add it to .env.local at the project root, and restart the process. The flag is opt-in, all-uppercase, and only affects local CLI behaviour. It never reaches your deployed build, and the production runtime on Vercel does not read it. If the CLI still tries to link after a restart, scroll to Debugging when the skip link isn't working for the version-compatibility and process-tree checks that catch the cases the basic setup misses. I have shipped this flag in three production monorepos and the same four mistakes account for almost every "I set it and it did nothing" report I see. What VERCEL_EXPERIMENTAL_DEV_SKIP_LINK actually does VERCEL_EXPERIMENTAL_DEV_SKIP_LINK is an opt-in environment variable the Vercel CLI honours when it runs alongside a local Next.js dev server. Its job is narrow: tell the CLI to skip the step where it would normally reach out to Vercel and create or refresh a dev link against your Vercel project. A "dev link", in the Vercel sense, is a local connection record that lets vercel dev and some Vercel-only local emulators (KV, Postgres, Edge Config) pull real values from a Vercel project. It is useful when you want production-shaped data during development, and a real annoyance when you do not — for example in CI sandboxes, offline laptops, monorepo workspaces that share a single project, or any time you want next dev to behave like a plain Node process without the CLI wrapping it. The variable is shipped under the VERCEL_EXPERIMENTAL_ namespace, which Vercel uses to mark features that can change between CLI versions. That has two practical consequences: the name must be uppercase with underscores, and you should not build production logic on top of it. I treat it like a local-dev knob, set per shell session, and never check it into CI as a hard dependen
AI 资讯
Cutting OpenAI Costs From Scratch: What Nobody Tells You
Cutting OpenAI Costs From Scratch: What Nobody Tells You Three months ago I sat down with my finance lead and watched her scroll through our OpenAI invoice. The number was $14,200 for the month. That was the moment I knew we had a problem. Not a "maybe we should optimize" problem — a real, existential, "this kills our margins before we hit Series B" problem. I run a B2B SaaS platform that does a lot of LLM-powered document processing. Summarization, extraction, classification, the boring stuff that makes real money but burns tokens like crazy. We were routing everything through GPT-4o because, honestly, it was the path of least resistance when we started. Then the bills started arriving. This is the story of how I cut our LLM spend by 97%, the architecture decisions that made it possible, and the things I wish someone had told me before I started. The Math That Made Me Sweat Let me put actual numbers on the table. Here's what I was paying versus what I pay now: Model Provider Input $/M Output $/M vs GPT-4o GPT-4o OpenAI $2.50 $10.00 — GPT-4o-mini OpenAI $0.15 $0.60 16.7× cheaper DeepSeek V4 Flash Global API $0.18 $0.25 40× cheaper Qwen3-32B Global API $0.18 $0.28 35.7× cheaper DeepSeek V4 Pro Global API $0.57 $0.78 12.8× cheaper GLM-5 Global API $0.73 $1.92 5.2× cheaper Kimi K2.5 Global API $0.59 $3.00 3.3× cheaper Look at that DeepSeek V4 Flash row. 40× cheaper than GPT-4o. For comparable quality on the workloads I was running. I had been leaving 97.5% of my budget on the table. Doing the mental math: a $500/month OpenAI bill becomes $12.50. My $14,200 bill? Theoretically $355. That's not optimization, that's a different business. Why I Almost Didn't Do It Here's the thing nobody tells you about cost optimization at a startup: it's not a technical problem, it's a willpower problem. The reason I was paying OpenAI 40× too much wasn't because their API is hard to use. It was because switching felt risky. I had deadlines. I had a roadmap. I had investors asking about g
AI 资讯
Parsing and Rebuilding EPUB Files in Python: Lessons Learned
How we handle complex EPUB structures for AI translation without breaking navigation and metadata At LectuLibre , we built an AI‑powered book translation service. Users upload an EPUB, and our pipeline translates the text using LLMs like Claude and DeepSeek. That sounds straightforward until you have to parse and rebuild a valid EPUB without mangling the table of contents, internal links, or styles. I’m sharing the real‑world challenge we faced, how we chose our tooling, and the ugly corners we discovered when dealing with real‑world EPUB files. The Problem: EPUB is a Messy Zip File An EPUB is essentially a ZIP archive containing XHTML, CSS, images, and an OPF manifest. It’s a well‑defined standard (EPUB 3.2), but in practice publishers produce files that bend the rules: missing container.xml , inline styles that break after translation, and structural quirks that make parsing fragile. Our translation process needed to: Accept any EPUB the user throws at us. Extract all text content while preserving the exact structure. Send each paragraph to an LLM for translation. Re‑insert the translated text into the original XHTML files. Repackage everything into a new, valid EPUB. Step 4 is the tricky part: the translated text can be longer or shorter, it may contain characters that need escaping, and the surrounding markup must remain intact. Our Approach: Use ebooklib with a Dose of Defensive Coding We evaluated several Python libraries: epub (pypub) – too simple, no editing support. lxml + manual zip – too much boilerplate. ebooklib – full read/write with a clean API. We went with ebooklib . It provides an object‑oriented model of the EPUB structure, allows us to iterate over documents, and can write a new EPUB from the modified objects. The downside: its documentation is sparse and it can choke on malformed files. We had to layer on a lot of validation. Step 1: Loading and Validating the EPUB import ebooklib from ebooklib import epub def load_epub ( epub_path : str ) -> ep
AI 资讯
Mastering the "Quantified Self": Building a Blazing-Fast Heart Rate Dashboard with DuckDB and Streamlit
As programmers, we love data. We track our commits, our uptime, and our deployment frequencies. But what about our most important "server"—our heart? 💓 The "Quantified Self" movement has led to an explosion of wearable data. However, if you've ever tried to analyze raw heart rate CSVs (often sampled every few seconds), you'll quickly realize that standard relational databases or even pure Pandas can get sluggish once you hit that 100k+ row mark. In this tutorial, we are going to build a high-performance Quantified Self Dashboard . We will leverage DuckDB —the "SQLite for Analytics"—to perform vectorized execution on heart rate data, paired with Streamlit and Plotly for a slick, interactive frontend. We’ll focus on Python data engineering , time-series analysis , and fast SQL processing . Why DuckDB? 🦆 Traditional databases are row-based, which is great for transactions but terrible for analytical queries. DuckDB is a columnar-vectorized query engine . This means it processes data in chunks (vectors) and utilizes modern CPU instructions (SIMD) to crunch numbers at speeds that make standard Python loops look like they're standing still. The Architecture Here is how our data pipeline flows from raw pixels (well, raw CSV rows) to actionable insights: graph TD A[Raw Heart Rate CSVs] -->|Direct Ingestion| B(DuckDB Engine) B -->|Vectorized SQL Execution| C{Data Aggregation} C -->|Moving Averages/Outliers| D[Streamlit App State] D -->|Plotly| E[Interactive Visualization] E -->|User Input| D Prerequisites 🛠️ Ensure you have the following stack installed: Python 3.9+ DuckDB : For the heavy lifting. Streamlit : For the UI. Plotly : For the beautiful charts. pip install duckdb streamlit plotly pandas Step 1: Ingesting 100,000+ Data Points in Milliseconds One of the coolest features of DuckDB is its ability to query CSV files directly without a formal "import" step. This is a game-changer for developer productivity. import duckdb import pandas as pd # Let's assume 'heart_rate.cs