今日已更新 293 条资讯 | 累计 23876 条内容
关于我们

标签:#ICE

找到 159 篇相关文章

AI 资讯

I Went Looking for the Basis of 'N Characters Per Minute Is Fast' — There Wasn't One. Setting Read-Aloud Thresholds Honestly

📝 Originally published in Japanese on Zenn. This is the English version. Canonical: https://zenn.dev/uya0526_design/articles/satellite3_metrics-rationale 📚 This is satellite article #3 in my "Read-Aloud Speed Meter dev log" series. For the whole picture, see the main article . Where This Sits The read-aloud speed meter converts speaking speed into an evaluation label like "slightly fast," and stagnation rate into one like "few." Those labels ultimately become the foundation for Claude Haiku's feedback. So — on what basis did I draw the thresholds (the dividing lines)? This article digs into that "basis." The short answer from my research: I couldn't find a paper that defines an academic threshold for "N characters/min = fast/slow." This is a record of how I drew the lines honestly once I'd learned there was no firm basis. More than the metric numbers themselves, I believe being transparent about why I chose those numbers is what makes an evaluation app trustworthy. 💡 I'm an ex-Java engineer learning TypeScript in public. This one is mostly about design decisions. Why Obsess Over the "Basis"? An evaluation app passes judgment on the user: "your reading is slightly fast." Once you're passing judgment, if you can't explain "why we can say that," it's just guesswork. This app in particular passes the labels straight to Claude Haiku to generate coaching. If the foundational label has an unclear basis, the feedback built on top of it is a castle on sand. So I decided to nail down the basis for the thresholds first. Two things to research: The judgment basis for speaking speed (characters/min) The judgment basis for stagnation rate (the proportion of silence) As it turned out, these two had completely different kinds of basis. Speed Thresholds: No Academic Threshold → Draw From General Rules of Thumb What I found For speaking speed, I first looked for academic backing. Here's what I found: Speaking speed has traditionally been measured against mora count, but prior researc

2026-06-18 原文 →
AI 资讯

HLD Fundamentals #3: Microservices Design Patterns: Strangler, Saga, and CQRS

When organizations scale, a simple monolithic architecture often becomes difficult to maintain, deploy, and scale. This is where microservices come into the picture. However, moving to microservices introduces new challenges: How do we migrate from a monolith safely? How do we handle transactions across multiple services? How do we scale read-heavy applications efficiently? Three popular patterns solve these problems: Strangler Pattern – Monolith to Microservices Migration Saga Pattern – Distributed Transaction Management CQRS (Command Query Responsibility Segregation) – Read/Write Scalability 1. Strangler Pattern Why Do We Need It? Most companies cannot shut down a production monolith and rewrite everything from scratch. A complete rewrite is risky because: Development takes a long time. Existing customers are affected. Bugs can impact business operations. Rollback becomes difficult. The Strangler Pattern allows teams to migrate gradually with minimal risk. What Is It? The Strangler Pattern is a migration strategy where new microservices slowly replace parts of a monolithic application until the monolith is no longer needed. The name comes from the strangler fig tree, which gradually grows around another tree and eventually replaces it. How Does It Work? [Insert diagram here showing Client → API Gateway → Monolith + Microservices] Step 1 All requests go to the monolith. Client | v Monolith Step 2 Introduce an API Gateway (or Controller). Client | v API Gateway | v Monolith Step 3 Extract one module into a microservice. Client | v API Gateway |------> Order Service | v Monolith Step 4 Gradually move more modules. Client | v API Gateway |------> Order Service |------> Payment Service |------> Inventory Service | v Monolith Step 5 Eventually remove the monolith completely. Example Consider an e-commerce application. Initially, everything exists inside one application: Monolith ├── Orders ├── Payments ├── Inventory └── Users Over time: Orders become Order Service Payme

2026-06-18 原文 →
AI 资讯

Saga Orchestration in Go: Distributed Workflows That Actually Roll Back

Every non-trivial business operation touches more than one system. An e-commerce order reserves inventory, charges a payment method, and schedules a shipment — three services, three databases. A bank transfer debits one account and credits another across two ledgers that may not even be in the same data center. A cloud VM provisioning workflow reserves a network port, allocates storage, starts the hypervisor, registers billing, and sends a notification — five services, five independent state stores. The question is: what happens when step four fails after steps one through three have already succeeded? In a monolith backed by a single database, the answer is simple: roll back the transaction. The database engine guarantees atomicity; either everything commits or nothing does. But when your workflow spans multiple services, each owning its own storage, there is no transaction boundary that wraps them all. There is no rollback button. Step one through three have already made durable changes to systems that do not know about each other, and step four's failure has left the system in an inconsistent state. This is not a pathological edge case. It is the default condition in any distributed architecture. And it gets worse: the failure might not be a hard error. The network might time out. The billing service might return a 503. You do not know whether step four applied its effect or not — you only know you did not receive a success response. Now what? This is the problem sagas were designed for. Client Inventory Svc Payment Svc Shipping Svc │ │ │ │ 1 │──reserve(item)──►│ │ │ │◄──── 200 OK ─────│ │ │ │ [reserved ✓] │ │ │ │ │ │ 2 │──────────── charge(card, $99) ────►│ │ │◄───────────────── 200 OK ──────────│ │ │ │ [charged ✓] │ │ │ │ │ 3 │─────────────────────── schedule(order) ─────────────►│ │◄─────────────────────────── 503 ──────────────────── │ │ │ │ [no record ✗] │ │ │ │ ╔══════════════════════════════════════════════════════╗ ║ ⚠ Inconsistent state ║ ║ Inventory: it

2026-06-18 原文 →
AI 资讯

The Dependency Injection Quest: How I Turned Spaghetti Code Into a Lightsaber 🚀

The Quest Begins (The “Why”) Picture this: I’m knee‑deep in a legacy codebase that feels like the Death Star’s trash compactor—every time I try to add a feature, the walls close in and I’m squashed by tight coupling. I’d just spent three hours tracking down a bug that only showed up when the payment gateway was mocked in a test. The culprit? A new PaymentGateway() buried deep inside an OrderService class. It was like trying to defeat Darth Vader with a butter knife—no matter how hard I swung, the Dark Force (aka hidden dependencies) kept pulling me back. I realized I was instantiating collaborators inside the very classes that should be oblivious to their implementation details . The result? Tests that needed a real database, a real Stripe account, and a sacrificial goat to run. Any change to a third‑party API meant hunting down every new scattered across the project. Onboarding a new teammate felt like handing them a map written in ancient Sumerian. Honestly, I was ready to quit coding and become a professional napper. Then, during a late‑night coffee‑fueled refactor session, I stumbled upon a tiny line of documentation that whispered: “Depend on abstractions, not concretions.” It sounded like Yoda giving me a pep talk. The Revelation (The Insight) The magic spell I uncovered is Dependency Injection (DI) —specifically, constructor injection . Instead of a class creating its own collaborators, we hand them in from the outside. Think of it as giving a Jedi their lightsaber rather than making them forge one in the middle of a battle. Why does this feel like discovering the Force? Testability explodes – you can swap in fakes, mocks, or stubs without touching production code. Flexibility skyrockets – swapping a payment provider becomes a one‑line config change, not a scavenger hunt. Clarity reigns – the constructor becomes an honest inventory of what a class needs to do its job. The moment I applied it, the codebase felt lighter, like Luke finally trusting the Force ins

2026-06-18 原文 →
AI 资讯

🔮 Beat the Oracle: A FIFA World Cup 2026 AI Prediction Duel

This is a submission for the June Solstice Game Jam What I Built Beat the Oracle is a daily FIFA World Cup 2026 prediction game where you go head-to-head against an AI — Google's Gemini 1.5 Flash — to call match scores before kickoff. Out-predict the machine and you win the day's Turing Test. Lose, and the Oracle has outsmarted you... until tomorrow. Every day you're served the same 5 matches as everyone else: some already played (scored instantly), some upcoming (lock in your call and come back). The Oracle reads each team's recent World Cup form and makes its own prediction with written reasoning — which you only see after you've locked in yours. No peeking, no cheating. Just you versus the machine. Scoring: Result Points Exact scoreline 3 🎯 "Enigma Cracked!" Correct result (W/D/L) 1 ✅ Miss 0 ❌ Why this fits the June Solstice Game Jam This jam asked for a game inspired by the solstice or any June celebration — and Beat the Oracle is stitched to June on two threads the challenge itself calls out: The World Cup is June's global celebration. The prompt names it directly: "the electric teamwork and high stakes of the World Cup, bringing the entire planet together in the spirit of play." That's the playground this game lives in — and as a bonus, I built it from 🇨🇦 Canada, a 2026 host nation . June is Alan Turing's month. Born June 23rd, Turing is the reason this jam has a "father of computing" prize at all. So I didn't bolt a Turing reference onto a football game — I built a playable Turing Test and gave it a World Cup costume. Turing's 1950 question, "Can machines think?" , becomes a question you answer with your gut every single day: can a machine predict football better than you? And the "daily" loop — new matches each day, your score reset, the machines winning "for today" — leans into the solstice's own theme of cycles and the passage of time. Every day is a fresh test. Every match is a new cipher. 🔗 Live demo: hema-nambi.github.io/BeatTheOracle Code Hema-Nambi /

2026-06-17 原文 →
AI 资讯

Claude Fable 5 Pulled by US Export Order — 72 Hours After Launch

Three days. Claude Fable 5 — Anthropic's most capable model ever shipped to the public, posting 95% on SWE-bench Verified — was live for exactly 72 hours before the US government issued an export control directive on June 12 that forced Anthropic to pull it globally. For everyone. Including US users. Including Anthropic employees who hold foreign passports. Here is what Fable 5 actually is, what the government directive says, what Anthropic says about it, and what developers building on Claude should do while this gets resolved. What Claude Fable 5 Is Anthropic launched Claude Fable 5 on June 9, 2026, alongside Claude Mythos 5, its restricted sibling for government-adjacent cybersecurity work. Fable 5 is the first publicly available model in Anthropic's new "Mythos-class" tier — a category above the previous frontier that Claude Opus 4.8 (released May 28) occupied. The benchmark gap is not close. Fable 5 posted 95.0% on SWE-bench Verified and 80.3% on SWE-bench Pro. The next best competitor on SWE-bench Pro is GPT-5.5, sitting at 58.6%. That is a 21.7-point gap — roughly twice the margin by which Claude Opus 4.8 led its generation. Across all eight coding benchmarks Anthropic published at launch, Fable 5 led with an average margin of 11.8 points: Benchmark Claude Fable 5 Next Best Gap | SWE-bench Verified | 95.0% | ~74% | +21 | | SWE-bench Pro | 80.3% | 58.6% (GPT-5.5) | +21.7 | | FrontierCode Diamond | leads | baseline | +23.6 | | HLE (no tools) | leads | baseline | +13.7 | | Terminal-Bench | leads | baseline | +4.6 | Beyond static benchmarks, Anthropic ran a long-horizon game-playing evaluation using Slay the Spire with persistent file-based memory. Fable 5 improved three times faster than Opus 4.8 as memory accumulated, and reached the final act three times as often. The large-context reasoning advantage — the same capability that powered the 8x engineering productivity multiplier at Anthropic — is structurally more pronounced in Fable 5 than in any previous publ

2026-06-14 原文 →
AI 资讯

Struct Embedding in Go: Composition That Bites When You Reach for Inheritance

Book: The Complete Guide to Go Programming Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub You come to Go from a language with classes. You see struct embedding for the first time, and it reads like inheritance. A field with no name, methods that "carry over" to the outer type, a base struct that your type extends. So you write code the way you always have, and most of it works. Then a method does something you did not ask for, a type satisfies an interface you never meant to implement, or two embedded types fight over a name and the compiler shrugs until the exact line that calls it. Embedding is not inheritance. It is composition with a syntax that promotes methods and fields up one level. Once you hold that distinction, the surprises stop being surprises. Here is where they come from. Embedding promotes, it does not subclass Write an embedded field by giving a type with no field name: type Engine struct { Horsepower int } func ( e Engine ) Start () string { return "vroom" } type Car struct { Engine // embedded Brand string } Car now has a Start method and a Horsepower field, both promoted from Engine . You can write car.Start() and car.Horsepower as if they were declared on Car . car := Car { Engine : Engine { Horsepower : 300 }, Brand : "Fiat" } fmt . Println ( car . Start ()) // vroom fmt . Println ( car . Horsepower ) // 300 This is where the inheritance illusion starts. car.Start() is sugar. The compiler rewrites it to car.Engine.Start() . The receiver of Start is still an Engine , never a Car . There is no base class, no super , no virtual dispatch. Engine does not know Car exists. That last point is the one that bites. A promoted method runs against the embedded value, not the outer struct. The method that ignores the outer struct Say you want a stringer on the embe

2026-06-14 原文 →
AI 资讯

defer in Loops: The Resource Leak Go Still Lets You Write

Book: The Complete Guide to Go Programming Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub You wrote a function that walks a directory and reads every file. It opened cleanly in review. It passed tests on a fixture folder with three files. Then a customer pointed it at a folder with 20,000 files, and the logs filled with: open /data/batch/img-08431.png: too many open files The code never closed anything early. It deferred every close. And that is exactly the problem. defer runs at function return, not end of iteration defer schedules a call to run when the surrounding function returns. Not when the current block ends. Not when the loop iteration ends. When the function returns. Most of the time that distinction does not matter, because most deferred calls live in short functions that return quickly. Put a defer inside a for loop, though, and every iteration adds one more deferred call to a stack that does not unwind until the whole loop is done and the function exits. Here is the version that ships: func processFiles ( paths [] string ) error { for _ , p := range paths { f , err := os . Open ( p ) if err != nil { return err } defer f . Close () // runs at RETURN, not here if err := handle ( f ); err != nil { return err } } return nil } Read it the way the language reads it. On the first iteration, os.Open returns a file handle and you defer its close. On the second iteration, another handle, another deferred close. By the time the loop has touched 20,000 files, you are holding 20,000 open descriptors, and not one of them closes until processFiles returns. Your process has a file-descriptor limit. On Linux the soft default is often 1024. You blow through it somewhere around the 1024th file, and the error you get back says nothing about defer . It says too many open files , wh

2026-06-14 原文 →
AI 资讯

Your Voice Agent Is Slow. Here Are 5 Tricks to Hide It.

My voice agent took 1.2 seconds. Users hated it. So I made it lie. A while back I shipped a voice agent that took roughly 1,200ms to respond. Not catastrophic on paper. Pretty bad in practice. Users would ask a question, get a beat of silence, and start over. Some thought the mic had cut out. One tester told me, with a straight face, that my agent was "thinking too hard." I tried everything legitimate first. Smaller LLM. Streaming TTS. Region-pinned endpoints. I shaved off about 200ms and felt clever for a week. Then I measured again and realized I was still on the wrong side of every latency threshold that matters. So I gave up on being faster and started working on being a better liar. This is the playbook I wish I had when I started: five perception tricks that reduce felt latency without touching the actual numbers. They're the voice-AI equivalent of a magician's misdirection. Your right hand waves at the audience. Your left hand swaps the card. The cliff you can't engineer your way out of In a previous article I broke down the three latency cliffs for voice AI. The short version: Around 200ms : the brain starts to register the pause as "slow." This is the conversational baseline humans use with each other. Around 500ms : the conversation breaks. The user starts to wonder if they need to repeat themselves. Around 800ms : they've quietly given up. Even if your answer arrives, the trust is gone. If your stack is doing STT plus LLM plus TTS plus network, hitting 200ms end-to-end is, frankly, a fantasy for most teams. You can chase it. You can throw money at it. You can cache and prefetch and stream. At some point you bottom out. That's where perception work begins. The user can't measure your p99 latency. They can only measure how the agent feels . Those are two different problems and they have two different solutions. 5 tricks I now use to mask latency 1. Acknowledgment tokens ("Got it", "On it", "Let me check") What it is: A short, instant utterance played the mo

2026-06-13 原文 →
AI 资讯

Voice Agents That Follow Up by Email

Last sprint, a team I talked to demoed a voice agent that handled support calls impressively — right up until a caller asked "can you email me those instructions?" and the room went quiet. The agent could talk about the docs. It had no address to send them from. The workaround on the whiteboard afterwards was grim: relay through a shared noreply@ , lose the replies, reconcile threads manually in the ticketing system. Voice agents hit this wall constantly, because phone calls generate follow-up artifacts — reset instructions, documents, meeting recaps — and email is how callers expect to receive them. The clean fix is the same one that works for text agents: the voice agent gets its own mailbox. The identity half A Nylas Agent Account is a hosted mailbox you create through the API — Agent Accounts are in beta — and the voice use case from the product docs is exactly the scenario above: a voice agent taking support calls sends documents, reset instructions, or meeting recaps from its own voice-agent@yourcompany.com address the moment the caller asks. The part that makes it more than a send pipe: when the caller replies, the reply returns through the same account, so the full conversation is one thread in one mailbox. The phone call and its written follow-ups stop living in separate systems. Each account is a real grant with a grant_id that works against the existing Messages, Threads, and Webhooks endpoints, ships with six system folders, and sends up to 200 messages per account per day on the free plan. The plumbing half The voice agents recipe covers how the runtime actually calls email tools. The flow is the same regardless of vendor: speech → STT → LLM (function-calling) → subprocess(nylas …) → JSON → LLM → TTS → speech The LLM decides on a tool, the runtime spawns a Nylas CLI subprocess with --json , the result comes back, and the model composes a spoken response. On LiveKit, a tool is just a decorated function: from livekit.agents import function_tool import sub

2026-06-12 原文 →