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

标签:#an

找到 1517 篇相关文章

AI 资讯

Como servir os 68 milhões de CNPJs da Receita com ~10ms de latência em Go

Todo dev brasileiro que já precisou consultar CNPJ conhece o dilema: ou você usa uma API que faz proxy da Receita (3 a 10 segundos por consulta, quando não cai), ou baixa o dump de dados abertos e monta a própria base — e descobre que "baixar um CSV" era a parte fácil. Eu montei a própria base. Este post é o diário honesto do que funcionou, do que quebrou e dos números reais — 217 milhões de linhas servidas em ~10ms de p50 dentro do datacenter, num Postgres de 1 vCPU. A arquitetura em uma frase Não consulte a Receita em tempo real. Ingira o dump mensal e sirva da sua infra. O resto é decorrência. Receita (dump mensal, ~6GB zip) ──▶ ingestão Go (COPY) ──▶ Postgres ──▶ API (chi) CGU (CEIS/CNEP, zip diário) ──▶ job diário ──┘ O dump da Receita: as pegadinhas que ninguém documenta O layout oficial existe, mas o que quebra parser de verdade é o que está fora dele: Encoding latin1 (ISO-8859-1) — acento vira lixo se você ler como UTF-8. Em Go: charmap.ISO8859_1.NewDecoder() num transform.Reader streaming. Decimal com vírgula ( "1000000,00" ) e datas YYYYMMDD onde 0 e 00000000 significam nulo. CNPJ quebrado em 3 colunas (básico 8 + ordem 4 + DV 2). A chave de junção entre empresas, estabelecimentos e sócios é o básico — errar isso custa um dia. As partições 0–9 não se alinham entre arquivos. O estabelecimento da partição 3 pode ser de uma empresa da partição 7. Foreign key rígida entre as tabelas = COPY quebrando no meio da carga. A solução: sem FK; a integridade vem da fonte. Bytes NUL ( 0x00 ) no meio dos dados. O Postgres rejeita NUL em text . Um strings.ReplaceAll(s, "\x00", "") no parser economizou três recargas. Desde jan/2026 o repositório é um Nextcloud do SERPRO+ com WebDAV público — dá pra listar meses com PROPFIND e baixar com o token do share como usuário. Adeus, scraping. COPY ou morte A diferença entre INSERT em lote e o protocolo COPY não é incremental — é outra categoria. Com pgx.CopyFrom e lotes de 50k: 28,1 milhões de empresas em 1m28s (~320k linhas/s) num

2026-07-06 原文 →
AI 资讯

France to Stop Certifying Non-Quantum-Safe Encryption

France is accelerating its transition to post-quantum encryption: France’s cybersecurity agency ANSSI said on Tuesday it would stop certifying security products that lack quantum-resistant encryption, a move that will force government bodies and critical operators to shift away from older systems. Samih Souissi, ANSSI’s chief of staff, said at the France Quantum conference that the agency would halt such certifications from 2027, and that businesses should be buying only quantum-safe products by 2030. ANSSI approval is required for use in French government agencies and critical infrastructure, making the policy a de facto phase-out of older encryption...

2026-07-06 原文 →
AI 资讯

Presentation: Practical Robustness: Going Beyond Memory Safety in Rust

Andy Brinkmeyer shares how engineering leaders and architects can use Rust to build failure-proof systems. Moving beyond memory safety, he explains how ownership, enums, and the typestate pattern embed complex runtime protocols into compile-time checks. Learn to eliminate entire classes of bugs, manage real-world resources safely, and maximize codebase robustness effortlessly. By Andy Brinkmeyer

2026-07-06 原文 →
AI 资讯

How I Benchmarked an LLM Running Entirely on a Phone (No Cloud, No API)

"It works on my test input" is the most dangerous sentence in on-device AI development. I typed that sentence - or some version of it - a dozen times while building Redacto, our on-device PII redaction app running Gemma 4 E2B on a Samsung Galaxy S25 Ultra. The model would redact a patient name from a clinical note, I would nod, and I would move on. Then I would hand the phone to a teammate, they would type a police report, and the model would redact the suspect description instead of the victim name. The problem is not the model. The problem is that manual spot-checking is not validation. You are testing a single input against your own expectations, with all the confirmation bias that entails. When you have five domain modes (HIPAA, Financial, Tactical, Journalism, Field Service), three difficulty levels, and two candidate models, you need something systematic. You need a benchmark suite. This post covers how I built one - from dataset curation to scoring methodology to on-device infrastructure - for a hackathon app running entirely on a phone. No cloud. No API calls. No data leaving the device. Why Not Use an Existing Framework? The LLM evaluation space has mature tools. EleutherAI's lm-eval-harness is the community standard for evaluating language models against academic benchmarks like MMLU, HellaSwag, and ARC. Stanford's HELM (Holistic Evaluation of Language Models) provides a multi-metric evaluation framework with standardized scenarios. Google's BIG-bench offers hundreds of tasks for probing specific capabilities. These frameworks are excellent for what they do. They are also completely wrong for this problem, for three reasons. First, they assume server-side inference. lm-eval-harness expects to call a model through an API or load it in PyTorch on a GPU server. Redacto's model runs on a Qualcomm Hexagon NPU inside a phone. There is no Python runtime, no HuggingFace tokenizer at evaluation time, no way to hook into the framework's inference loop. Second, their

2026-07-06 原文 →
AI 资讯

I Ran a Technical SEO Audit for Five Days: the Gates Mattered More Than the Five Fixes

Plenty of SEO audits end with a single tool report. You run Lighthouse, screenshot Search Console coverage, save a "12 issues found" panel, and call it done. The trouble is that most audits finished that way silently revert within three months. Someone publishes a new post, refactors a component, swaps a font, and the issue quietly comes back. Nobody notices. Over the last five days I actually audited my four-language blog (ko/ja/en/zh, 298 posts per language). Five items, all fixed. But what I really want to talk about isn't what I fixed. It's that the five fixes mattered less than the build gates that keep them from ever returning. An audit should be a loop, not an event. Why a one-report audit always comes back Most technical SEO issues aren't "the code is wrong." They're "an invariant was never enforced anywhere." Take a clear rule: a published post must not link internally to a draft. Obvious enough. But if a human has to remember that every time, then the moment a recommendation generator pulls in one draft slug, a 404 is born. The report catches that 404 and shows it to you, but it does nothing to prevent the next one. So I ran the audit as a three-step loop. Measure. Fix the biggest item first. Then turn that item into a checker and nail it to the build . Skip the third step and the first two become a chore you repeat every six months. Once a gate is in place, the same class of problem makes npm run build fail. A pipeline enforces the rule, not human memory. This isn't a new invention. It's the same logic by which tests prevent bug regressions, applied to the content and markup layer. It's just oddly rare in SEO, where most teams leave "SEO checks" as a quarterly manual task. The five items I actually ran over five days Measurement first. Each item got a before/after in numbers, not a vibe that "things feel better" but reproducible figures. (The raw log of all five lives on the improvement history page too.) Date Item Before After Gate 07-02 relatedPosts int

2026-07-06 原文 →
AI 资讯

My Fine-Tuned Gemma 4 Loaded Fine, Then Broke on the First Message

I fine-tuned Gemma 4 E2B. The adapter merged cleanly. The export to .litertlm completed without errors. I pushed the model to my phone, initialized the engine, and everything looked green. Then I tried to create a conversation and got this: Failed to apply template: unknown method: map has no method named get (in template:238) No model loading failure. No quantization error. The model initialized, the tokenizer loaded, and then the runtime choked on a Jinja template feature it does not support. This failure only surfaces when you actually try to run inference, not when you load the model. If you are demoing at a hackathon, this is the worst possible time to discover a compatibility issue. I hit this exact bug while building Redacto, a zero-trust PII redaction app that runs Gemma 4 E2B entirely on-device. This post walks through the full fine-tune-to-deploy pipeline: how to QLoRA a model on Colab, export it for LiteRT-LM, and avoid the undocumented template trap that will block your deployment. The Full Pipeline Here is what the fine-tune-to-deploy pipeline looks like end to end: HuggingFace base weights -> QLoRA fine-tune (Colab) -> Merge adapter into base -> Patch chat template <-- the step nobody tells you about -> Quantize + export to .litertlm -> Push to device Each stage has its own failure modes. The template patch step is the one that was undocumented at the time, and it is the one that will cost you hours if you do not know it exists. A note on framing before we dig in: this was an under-resourced fine-tune. I trained on 3,000 of the 400,000 samples in the ai4privacy/pii-masking-400k dataset for a single epoch, and the label format did not fully match what Redacto expected downstream. The point of this post is not the fine-tune's accuracy - it is the deployment mechanics I had to work through to get any fine-tuned model onto the device at all. Step 1: QLoRA Fine-Tuning on Colab QLoRA (Quantized Low-Rank Adaptation) lets you fine-tune a quantized model by tra

2026-07-06 原文 →
AI 资讯

Predicting When a Client Will Actually Pay: Modeling Invoice Timing With an AI Agent

The single hardest thing about getting paid isn't writing the invoice. It's the follow-up — knowing when to nudge a quiet client, and doing it in a tone that doesn't torch the relationship. Most tools solve this with a dumb cron job: "send a reminder 7 days after the due date." That's wrong for almost everyone, and here's why. The problem with fixed reminder schedules Payment behavior isn't uniform. One client pays like clockwork on day 32 of a "net 30" invoice — not late, just their rhythm. Another pays on day 5 but only if you remind them on day 3. A blanket "day 7 past due" reminder annoys the first client (who was always going to pay) and misses the second (who needed the poke earlier). So the real problem is per-client timing prediction , not scheduling. You want to model each client's payment distribution and act at the point where a reminder has the highest marginal effect — the moment they're most likely to convert intent into a transfer. Modeling payment rhythm as a per-client distribution Every invoice gives you a labeled data point: (sent_date, due_date, paid_date, amount, was_reminded) . Over time, per client, that's a distribution of "days from send to pay." The naive move is to average it. Don't — averages hide the shape, and the shape is the whole signal. We model each client's pay-day as a distribution and track two things that matter more than the mean: Dispersion — a tight distribution (always day 30–32) means a reminder before day 30 is noise. A wide one means the client is reminder-sensitive. Reminder lift — comparing paid-day distributions with and without a nudge tells you whether reminders actually move this client, and by how much. for client in clients : hist = paid_events ( client ) # list of days-to-pay p50 , p90 = quantiles ( hist , [. 5 , . 9 ]) lift = mean ( days_without_reminder ) - mean ( days_with_reminder ) # act just before the client's own habitual pay point, # but only if a nudge historically helps them if lift > MIN_LIFT_DAYS :

2026-07-06 原文 →
AI 资讯

终将合上的莫比乌斯环:为什么《南方公园》迟早会拍“父母一代的童年”?

在《南方公园》(South Park)长达二十余年的播映史中,观众们见证了无数荒诞的奇迹。我们曾以为这群四年级的孩子会永远停留在那个没有手机、只有雪地的虚构小镇里。然而,随着特辑《后新冠时代》(Post Covid)的推出,观众们终于看到了主角四人组人到中年的模样——斯坦变成了自私的中年危机男,凯尔成了秃顶的心理咨询师,卡特曼甚至讽刺地皈依了犹太教,而肯尼则成为了伟大的科学家。 “长大”这一曾经被视为不可触碰的禁忌剧情,最终还是真切地呈现在了我们面前。 那么,顺着这个逻辑,下一个尚未开拓、但 注定会到来 的剧情处女地是什么? 答案只有一个: 现任父母一代(兰迪、杰拉德、史蒂芬、谢拉等)在南方公园度过的童年往事。 这不仅仅是一个粉丝的狂想,而是《南方公园》在叙事结构、商业逻辑以及核心主题演变下, 必定会发生且正在酝酿的终极剧情。 以下我们将从四个维度,深度解析为什么“父母辈童年篇”的出现是历史的必然。 一、 角色重心的位移:兰迪·马什已经成为事实上的“男主角” 要理解为什么父母的童年很重要,首先要看《南方公园》现在的核心是谁。 在早期的节目中,家长的功能非常单一——他们是孩子闯祸后的惩罚者,或者是荒谬社会现象的背景板。但随着创作者特雷·帕克(Trey Parker)和马特·斯通(Matt Stone)步入中年,他们的视角不可避免地发生了偏移。 斯坦的爸爸——兰迪·马什(Randy Marsh),已经从一个功能性配角,逐渐篡位成为了本剧事实上的第一男主角。 从种植大麻的“特种大麻(Tegridy Farms)”主线,到他各种中年危机的狂欢,兰迪的戏份和角色深度甚至超越了孩子们。观众不仅想看斯坦和凯尔,更想看兰迪又作了什么新死。 既然兰迪已经成为了灵魂人物,那么探索他的“前传”就具有了极高的叙事价值。兰迪是如何从一个地质学家变成如今的疯癫模样的?他和杰拉德(凯尔的爸爸)在童年时期有着怎样相爱相杀的关系?史蒂芬(巴特斯的爸爸)那近乎病态的严厉性格,是不是源于他自己童年时遭受的更可怕的“禁足”? 给头牌角色写前传,是所有长寿美剧在后期挖掘角色深度、延长生命周期的必经之路。 二、 历史的镜像:南方公园是一个“代际宿命”的闭环 《南方公园》最核心的喜剧和讽刺张力,往往来源于 “历史的重复” 。 在《后新冠时代》中,我们看到长大的孩子们不可避免地活成了他们父母的样子:斯坦和兰迪一样酗酒、焦虑、与世界妥协。这种“长大后我就成了你”的幻灭感,是本剧最深刻的黑色幽默。 如果这个闭环要完整,我们就必须看到父母辈的童年。 我们可以预见到这样一幅充满讽刺艺术的画面: 在1980年代的南方公园,小兰迪、小杰拉德、小史蒂芬和小斯图尔特(肯尼的爸爸)也曾组成过一个“四人组”。 他们当时可能也面临着和今天的斯坦、凯尔一模一样的困境——愚蠢的父母、荒诞的镇长、莫名其妙的末日危机。 小兰迪可能曾是一个像斯坦一样理智、对世界充满正义感的孩子,他发誓“我以后绝对不要成为我爸那样无聊的中年人”;而小杰拉德可能比凯尔更具道德洁癖。 这种“屠龙少年终成恶龙”的跨时空对比,将产生无与伦比的戏剧冲击力。 它能将《南方公园》的荒诞主义升华为一种关于“宿命”和“时间”的哲学思考:每一个愚蠢的中年人,都曾是那个试图拯救世界的孩子。 三、 终极的情怀武器:80年代的怀旧经济学 从商业和流行文化的角度来看,主打“80年代怀旧”是当今影视圈的财富密码(想想《怪奇物语》的爆火)。 《南方公园》的创作者特雷和马特出生于60年代末、70年代初,他们的童年恰好度过在70年代末到80年代。对于这两个天才创作者来说, 解构并重塑自己的童年,是他们创作生涯中迟早要交出的一张答卷。 在“父母辈童年篇”中,他们可以肆无忌惮地致敬和讽刺他们自己成长年代的产物: 雅达利游戏机、卡式录音带、初代的MTV。 冷战时期的恐慌、里根时代的保守主义。 经典的80年代怪兽电影和校园青春片范式。 这不仅能吸引那些看着《南方公园》长大的老观众(他们现在也为人父母,有着强烈的怀旧需求),还能为剧集提供源源不断的全新文化素材,避免现代科技(AI、短视频)题材带来的创作疲劳。 四、 尚未填补的巨大剧情坑(Canon) 在现有的剧情碎片中,创作者其实已经有意无意地暗示了父母辈丰富的童年/青年往事,这些“坑”都在等待着被填满: 兰迪与杰拉德的大学基情 :他们曾提到在大学时期探索过性取向,这段荒唐的青春期是如何过渡的? 兰迪的男孩天团梦 :兰迪年轻时曾是男子组合“Ghetto Avenue Boys”的成员,大红大紫后迅速过气,这段经历如何塑造了他渴望关注的性格? 镇上大人们的恩怨 :为什么卡特曼的妈妈莱安娜年轻时是全镇的交际花?莫普斯托博士的小白鼠实验在几十年前给小镇带来了什么灾难? 这些零散的设定就像一颗颗散落的珍珠,急需一根名为“童年

2026-07-06 原文 →
AI 资讯

Retro-Downfall Arcanum

🎲 A Tale of Inference Woes 🎲 Thy context window overflows with dread, Thy API keys scattered 'cross thy thread. Thou switchest providers mid-conversation, And pray thy tokens find the right foundation. No ward stands guard when tools go rogue, No grimoire saves a session from the fog. Thy agents wander, masterless and blind, Thy prompts untested—leaving truth behind. Thy wallet weeps. Thy latency doth creep. Thy model's fine. Thy infrastructure? Not so deep. Sound familiar? I'm excited to share the public README for Arcanum — a .NET 10, single-binary, Native AOT, local-first AI inference hub that treats your infrastructure with the seriousness of a dungeon master and the organization of a well-kept grimoire. Arcanum is one self-contained native executable. No runtime prerequisite. No "install the framework first." Just arcanum serve and you're running a full inference platform on loopback. What's in the bag of holding: 🏰 Local-first & encrypted — SQLCipher-encrypted Grimoire persists every session, entry, and memory. Your data never leaves your machine unless you tell it to. ⚔️ Multi-provider native engine — Any OpenAI-compatible API (DeepSeek, Groq, Ollama via /v1, LM Studio, etc.) plus local GGUF models via a managed llama-server lifecycle. One hub, zero vendor lock-in. 🔮 OpenAI API compatible — POST /v1/chat/completions and GET /v1/models work with existing OpenAI clients out of the box. Drop-in replacement for your local stack. 🛡️ Wards & Sanctum — High-risk tools require operator approval before execution. Per-campaign sandboxes enforce path containment, network policy, and OS-level CPU/memory/FD limits via cgroups v2 and setrlimit. 📜 Spells, not prompts — Versioned markdown workflows with dependency resolution, tool allowlisting, and semantic routing. Dry-run cast previews before spending a single token. 🧙 Autonomous Apprentices — Goal-driven agents with plan generation, retry/backoff, autonomous plan revision, DM escalation, and parallel step execution. 🏰 The

2026-07-06 原文 →
AI 资讯

From Angular.js to Fine-Grained Reactivity: Part 2 — The JS Proxy Runtime

In the first article of this series, we saw how a custom build-time compiler can transform a legacy Angular.js template into raw, optimized JavaScript. To recap, starting from this template: <!-- simple.html --> <p> Hello {{ name }}! </p> Our Go compiler generates the following JavaScript module: // simple.js export function template () { const p_0 = document . createElement ( " p " ); const text_1 = document . createTextNode ( "" ); p_0 . append ( text_1 ); return { mount ( container ) { container . append ( p_0 ); }, update ( change ) { if ( " name " in change ) { text_1 . data = " Hello " + change . name + " ! " ; } } } } This is incredibly clean. By running template() , we get an object with mount and update methods. Using mount is fully intuitive: we pass a reference to a DOM element, and it injects our empty paragraph ( p_0 ) into it: import { template } from ' ./simple.js ' ; const { mount , update } = template (); const container = document . getElementById ( ' view-container ' ); mount ( container ); // The DOM now contains: <p></p> (waiting for data) However, the paragraph remains empty until we call update with a change object like this: let changes = { name : " Mario " , }; update ( changes ); // The DOM surgically updates to: <p>Hello Mario!</p> But who is responsible for tracking changes in our application state, building this changes object, and calling update ? The answer lies in marrying the legacy Angular.js $scope with the modern JavaScript Proxy API . The Legacy State Pattern In a traditional Angular.js application, developers mutate the state directly inside a controller by assigning properties to the $scope object: // simple-controller.js export function SimpleController ( $scope ) { $scope . name = " Mario " ; } To bridge the gap between this legacy controller and our new build-time template, we need a way to automatically capture the assignment $scope.name = "Mario" and translate it into a structured update: let changes = { name : " Mario " }

2026-07-06 原文 →
AI 资讯

PostgreSQL query planner parameters and prepared statements

PostgreSQL provides several planner configuration parameters, such as enable_seqscan and enable_indexscan , that influence how execution plans are generated. These settings affect planning, not the execution of an already-generated plan. With prepared statements, this raises an interesting question. Should planner settings be applied before PREPARE, before EXECUTE, or both? Let's look at a simple example: a "tasks" table with a due date and a "done" status: \ c drop table if exists tasks ; -- a table of tasks with status (done or not) and due date create table tasks ( id bigint generated always as identity primary key , due timestamptz , done boolean ); -- insert 500 tasks, with 1% not done insert into tasks ( due , done ) select now () + interval '1 day' * n , 42 != n % 100 from generate_series ( 1 , 500 ) n ; -- index the todo (partial index) create index on tasks ( due , id ) where done = false ; vacuum analyze tasks ; With a partial index, I indexed only the tasks that are not yet done ( done = false ) because that's my most frequent query pattern: postgres =# explain select id , due , done from tasks where done = false and id > 0 order by due limit 1 ; QUERY PLAN --------------------------------------------------------------------------------------- Limit ( cost = 0 . 13 .. 3 . 60 rows = 1 width = 17 ) -> Index Scan using tasks_due_id_idx1 on tasks ( cost = 0 . 13 .. 17 . 47 rows = 5 width = 17 ) Index Cond : ( id > 0 ) ( 3 rows ) With partial indexes, the condition covered by the index is not even visible in the execution plan because the index itself enforces the condition. Prepared statement I decided to use a prepared statement with all values as parameters. It is probably not a good idea in this case. When a parameter can have only a few different values and you expect different cardinalities for each, you should probably define one query per value, using literals. I'm doing this to illustrate what can happen, with a simple, extreme example: postgres =# pr

2026-07-06 原文 →
AI 资讯

Prompt Caching and Cost Control in Java

Introduction We already covered picking the right model tier for the task and caching a large shared prefix in https://pg-blogs.netlify.app/posts/11-building-reliable-llm-apps-in-java/ . Those two lines were the tip of a bigger discipline: LLM cost is not a fixed line item, it's an engineering variable — one you can measure and shrink with the same rigor you'd apply to database query time or container memory. This post goes deeper: how input/output pricing actually works, the exact cache_control shape and how to prove a cache hit rather than assume one, the Batches API for work that isn't latency-sensitive, and model routing — using a cheap model to triage, escalating only the hard cases to a stronger one. The honest framing throughout: measure before you optimize. Every technique here has a cost of its own; applied to the wrong workload, "optimization" makes things slower or more expensive. Token Economics: Why the Prefix Is the Bill Anthropic (like every hosted LLM provider) prices input and output tokens separately, and output is always pricier — the model has to generate output autoregressively, one token informed by all the ones before it, while input can be processed in parallel. Representative pricing from the current model catalog: Model Input Output Claude Opus 4.8 $5.00 / MTok $25.00 / MTok Claude Sonnet 5 $3.00 / MTok $15.00 / MTok Claude Haiku 4.5 $1.00 / MTok $5.00 / MTok Two consequences follow directly: Long system prompts, tool definitions, and RAG context are read on every request , not written once. A 20K-token system prompt sent on every one of 10,000 requests is 200M input tokens — at Opus 4.8 rates, $1,000 before a single output token is generated. The shared prefix , not the user's question, is usually where the money goes. A verbose model wastes money twice — once on the extra output tokens themselves, and again because the next turn's messages history now carries that verbosity forward as input on every subsequent call. Trimming max_tokens an

2026-07-06 原文 →
AI 资讯

Prompt Caching and Cost Control in Python

Introduction https://pg-blogs.netlify.app/posts/10-building-reliable-llm-apps-in-python/ closed with a section on picking the right model per task and caching a shared prefix. That was the entry point into a bigger discipline: LLM spend is an engineering variable, not a fixed bill — one you can measure and reduce with the same rigor you'd apply to query latency or memory footprint. This post goes deeper on four levers: how input/output pricing actually works and why the prefix is usually where the money goes, the exact cache_control shape and how to prove a cache hit instead of assuming one, the Batches API for work that isn't latency-sensitive, and model routing — a cheap model triaging requests and escalating only the hard ones. The throughline is honest: measure before you optimize. Every lever here has its own cost; misapplied, it makes things slower or pricier, not cheaper. Token Economics: Why the Prefix Is the Bill LLM providers price input and output tokens separately, and output always costs more — generation is autoregressive (each token depends on every one before it), while input can be processed in parallel. Representative pricing from the current model catalog: Model Input Output Claude Opus 4.8 $5.00 / MTok $25.00 / MTok Claude Sonnet 5 $3.00 / MTok $15.00 / MTok Claude Haiku 4.5 $1.00 / MTok $5.00 / MTok Two things follow: A long system prompt, tool list, or RAG context is billed as input on every request , not written once. Send a 20K-token system prompt on 10,000 requests and that's 200M input tokens — at Opus 4.8 rates, $1,000 before the model has generated a single output token. The shared prefix , not the user's actual question, is usually the dominant cost. Verbose output costs twice — once directly (more output tokens billed at the higher rate), and again because the next turn's history carries that verbosity forward as input. Asking for concise output and setting a sane max_tokens is a cost control, not just a style choice. This is why the tw

2026-07-06 原文 →
AI 资讯

Gson silent bug that Never Said a Word(Interview Prep)

Here's a bug that looks impossible until you understand Gson. You have this data class in your Pokedex app: data class PokemonStat ( @SerializedName ( "base_stat" ) val baseStat : Int , val stat : StatInfo ) A teammate cleans up the code and deletes what looks like a redundant line: data class PokemonStat ( val baseStat : Int , // @SerializedName removed val stat : StatInfo ) It compiles . No red errors. He runs the app — and every Pokemon's baseStat is 0 . Not the real 45 or 49. Just 0 . Everywhere. And Gson never threw an error, never logged a warning, never said a single word. If you can explain why this happens, you understand Gson better than most juniors. This is also a favorite interview question. Let's break it fully. What Gson actually does When the JSON comes back from the server, Gson goes key by key: Read a key from the JSON — say base_stat . Look for a Kotlin property with the exact same name . Found it? Pour the value in. Not found? Leave that property at its default value and move on. That's the entire matching game — exact name match, or nothing. Now look at the "cleaned up" class. The JSON key is base_stat . The Kotlin property is baseStat . Those are not the same string . Gson looks for a property called base_stat , doesn't find one, shrugs, and leaves baseStat at its default. The default for an Int is 0 . That's your bug. @SerializedName("base_stat") was never redundant. It was the sticky note telling Gson: "this property is called baseStat in Kotlin, but look for base_stat in the JSON." Delete the note, and Gson stops matching. Two ways to fix it: Rename the property to base_stat — works, but breaks Kotlin's camelCase convention. Put @SerializedName("base_stat") back — keeps the clean name and matches. This is the right one. But why 0 ? Why not a crash? This is the part that surprised me. A missing field feels like it should be an error. It isn't. Gson treats a missing key as allowed . It builds your object, fills the fields it found, and leaves

2026-07-05 原文 →