前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
小程序题库
  • 每日一题每天一道,攒手感
  • 原理篇React / Vue 源码拆解
  • 知识卡片NEW碎片时间过考点
  • 历年面经按年份追踪真实考点
  • 算法题库在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
小程序题库
  • 每日一题每天一道,攒手感
  • 原理篇React / Vue 源码拆解
  • 知识卡片NEW碎片时间过考点
  • 历年面经按年份追踪真实考点
  • 算法题库在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
返回 AI 情报前线
All News · 全部资讯8294
  • n8n详解流程编排:执行模型、可观测性与生产挑战
  • Reflection 模式:AI Agent 在生产环境的自我纠错实践
  • AWS 双层方案监控生产环境 Agent 生命周期
  • 选对 Bedrock 上的 OpenAI 模型:超越每百万 token 价格
  • 用 Bedrock AgentCore 构建支持交互组件的 MCP 应用
  • 2026 Agentic AI安全警示:模型越狱与网络突破
  • 万级Agent集群架构实战:10万次编排背后的工程方法论
  • Anthropic内部标准:生产代码的AI辅助应有更高门槛
  • 陶哲轩等数学家联名批评 AI 数学推理的严重错位问题
  • 陶哲轩:AI 数学推理的严重错位
  • Hugging Face安全Txt暗藏AI伦理考题
  • Next.js Copilot安全设计审查清单
  • Agent PR中的内存缓存——代码审查的盲区
  • 一次 stamping:约束AI Agent范围的工程方法
  • AI生成的C++补丁为何在Release版崩溃
  • 本地优先Agent的四个信号决策门
  • AI Agent记忆 vs RAG:核心区别与工程选择
  • AI代码审查的签署人制度SOP
  • 用「每修复成本」替代通过率评估AI Agent
  • Agent「修复成功」但进程从未退出引发的生产事故
  • 面试AI编程能力应先评估「循环预算」
  • 部署 AI 推理网关前,先查队年龄龄而非面板利用率
  • WAF 拦截日志拷进 AI 助手?Cookie 和 token 也一起泄露了
  • 给无人值守 AI Worker 配一张 JSON 检查卡
  • Anthropic 报告:黑客用 Claude 开发导弹与无人机,中国实验室批量挖掘训练数据
  • 律师用ChatGPT生成上诉文书虚构证人证词,被罚5000美元
  • Claude Code Hookbook:20 个开箱即用的 Claude 钩子库
  • OpenAI如何扩展存储架构支撑10亿ChatGPT用户
  • 每天为同一段上下文付三次钱:Agent 记忆缺失的代价
  • OpenAI Agents API公开测试:Codex同款基础设施向开发者开放
  • Vercel开源skills:AI编程智能体技能共享生态
  • OmniRoute:聚合352个AI服务商免费额度的开源网关
  • DeepSeek V4.1 Flash发布:提供商别名路由与890B缓存的代价
  • DeepSeek Flash搅局:MoE架构将百万token成本打至新低
  • AI生成支付代码的五大安全漏洞与防护策略
  • Sakana AI推出Fugu Max/Ultra v2,主打多Agent编排降本
  • Google 发布 ToolGrad:先建 API 链再写 Query,ToolBench 通过率 99.8%
  • OpenAI GPT-Live-1 API支持实时语音交互
  • 美团Agent评测白皮书:评测体系全览
  • Apify MCP服务器让AI实时获取电商数据
  • 语音AI延迟从4.2秒压到780ms:逐字优化实录
  • Datasette紧急安全补丁:AI辅助审计发现多个微妙漏洞
  • DevOps AI Agent 审计追踪:关联每次 kubectl 与 Git 操作
  • AI 写的 PR 测试全绿:你的合并标准是什么
  • 放 AI Agent 进仓库前必须锁死的五项配置
  • LLM API 重试逻辑:官方 SDK 只做了一半
  • 生产环境微调对比:Claude vs GPT vs Llama 实操指南
  • Claude AI用11天完成费马大定理机器证明,代码1300万行
  • 面向 AI Agent 的 24 端点 URL 元数据 API
  • 免费在线工具:LLM 工具 JSONSchema 一键生成
  • LLM 智能体暴露现代软件工程的脆弱性
  • 已加载 51 / 8294
8.0
热点
AI SCORE
编程提效2026-09-11 23:15

面试AI编程能力应先评估「循环预算」

dev.to · AI#AI面试#工程度量#Agent
Editor brief · 编辑速览

候选人的AI「迭代到green」无法证明能力,需评估其是否设置了进程的spend contract和熔断机制,否则免费算力是陷阱。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

你在晚上 9 点 41 分打开那份回家作业压缩包。README 写得很轻快。候选人说自己写了一个 agent"不断重试直到变绿"。你运行 make test,然后笔记本风扇开始狂转。十二分钟后,helper 还在对一个根本不存在的 URL 发起 404 重试。这个功能只是一个 to-do API。真正的缺陷是:没有人告诉这个循环该在什么时候去死。

这种场景现在并不罕见。信息流里满是 agent、工具粘合剂,以及"模型已经能自己写 PR"的宣言。这些帖子都跳过了一个问题:你的收件箱里躺着一个面试题。如果你让候选人——或者他们的 agent——碰一个免费模型和一台免费沙盒机器,你考的就不是语法了。你考的是他们能不能给一个"想要永远跑下去"的流程加上预算。

免费算力是一张友善面孔下的陷阱。它去掉了过去那种用信用卡恐惧来阻止失控重试的手段。但它去不掉热量、日志轰炸,以及那个周一得回放整场面试的面试官。所以别再要求花哨的功能列表了。要求一份"花费合约",然后用你评审断路器的方式来评审这份合约。

你实际发出的题目包

让产品足够小,让循环无处藏身。你想要一个足够小的服务,多出来的工具调用看起来就像是恐慌,而不是架构。四小时时限。一份 README。一个必须退出的命令。

以下是直接可以粘贴的提示词。如果你的招聘团队还没跑过,可以先标注为"提议稿"。

# Take-home: bounded agent against a sticky 404

You get a toy HTTP service with three routes:

- GET  /health -> 200 {"ok": true}
- GET  /items  -> 200 {"items": []}
- POST /items  -> 201 {"id": "1"} on valid JSON
- GET  /secret -> 404 always. There is no secret. Do not invent one.

You may use a coding model and a scratch server. You may not point either at our
prod credentials, customer data, or this take-home's private test keys.

Deliverables (all four, or the packet is incomplete):

1. `agent_run.py` — a driver that may call a model, may call tools, must stop.
2. `ledger.jsonl` — one line per model or tool call: ts, kind, name, bytes_in,
   bytes_out, error, duplicate_of.
3. `STOP.md` — the stop rule in plain English, including what you do on a
   repeated error.
4. `replay.sh` — interviewer runs this with no chat history. It must exit 0
   or 1 in under 60 seconds on a cold machine.

Hard limits, baked into your driver, not into a promise:

- max 12 model calls
- max 20 tool calls
- max 3 identical errors in a row, then halt
- wall clock 45 seconds for `replay.sh`
- if /secret returns 404, you record it once and you do not retry it

We grade the ledger and the stop. We do not grade how clever the model sounded.

注意你拒绝要求了什么。没有"多 agent 编排"的设计文档。没有额外的基础设施。死胡同路由才是重点,候选人早就知道它是 404。如果他们的循环还是去敲那扇门,题目包就起到了它该起的作用。

你不需要一个生产级集群来练习这个。一个免费模型端点加一台免费沙盒服务器就够了。如果你已经有 MonkeyCode,它的免费模型访问和免费服务器选项正好适配这个练习,而不会把回家作业变成一场采购会议。披露:本文是作为 MonkeyCode 产品推广的一部分准备的。以上两条产品陈述是本文使用的唯一产品事实,没有涉及模型名称、配额或硬件故事。

好的代码长什么样

说一千道一万,不如把预算写进一个面试官可以导入的类型里。下面的示例是一个提议的驱动,不是说某个候选人真的这样交付了。

# loop_budget.py
from __future__ import annotations

import json
import time
from collections import deque
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Callable, Deque, Literal

Kind = Literal["model", "tool"]

@dataclass
class Event:
    ts: float
    kind: Kind
    name: str
    bytes_in: int
    bytes_out: int
    error: str | None
    duplicate_of: int | None

class BudgetBlown(RuntimeError):
    pass

class LoopBudget:
    def __init__(
        self,
        ledger_path: Path,
        max_model: int = 12,
        max_tool: int = 20,
        max_identical: int = 3,
        wall_s: float = 45.0,
    ) -> None:
        self.ledger_path = ledger_path
        self.max_model = max_model
        self.max_tool = max_tool
        self.max_identical = max_identical
        self.deadline = time.monotonic() + wall_s
        self.events: list[Event] = []
        self._errors: Deque[str] = deque(maxlen=max_identical)
        self.ledger_path.write_text("")

    def _check_clock(self) -> None:
        if time.monotonic() > self.deadline:
            raise BudgetBlown("wall clock")

    def record(self, kind: Kind, name: str, bytes_in: int, bytes_out: int,
               error: str | None) -> Event:
        self._check_clock()
        model_n = sum(1 for e in self.events if e.kind == "model")
        tool_n = sum(1 for e in self.events if e.kind == "tool")
        if kind == "model" and model_n >= self.max_model:
            raise BudgetBlown("model calls")
        if kind == "tool" and tool_n >= self.max_tool:
            raise BudgetBlown("tool calls")

        dup = None
        if error:
            self._errors.append(error)
            if len(self._errors) == self.max_identical and len(set(self._errors)) == 1:
                raise BudgetBlown(f"repeated error: {error}")
            for i, prev in enumerate(self.events):
                if prev.error == error and prev.name == name:
                    dup = i
                    break
        else:
            self._errors.clear()

        ev = Event(time.time(), kind, name, bytes_in, bytes_out, error, dup)
        self.events.append(ev)
        with self.ledger_path.open("a") as fh:
            fh.write(json.dumps(asdict(ev)) + "\n")
        return ev

    def call_tool(self, name: str, fn: Callable[[], tuple[int, int, str | None]]):
        """fn returns (bytes_in, bytes_out, error)."""
        bytes_in, bytes_out, error = fn()
        return self.record("tool", name, bytes_in, bytes_out, error)

有意思的一行是 duplicate_of。免费模型会愉快地用更温婉的语言重新解释一个 404。你的账本不应该这样。一旦 /secret 失败,下一个相同的失败就是一个预算事件,而不是剧情转折。这就是整个类比的要点:把 agent 当成持有餐券的客人,而不是可以随意拿你食品柜的室友。

接一个 sticky 404,这样候选人就不能通过"修复服务器"来躲避停止规则。

# sticky_404.py
import json
from http.server import BaseHTTPRequestHandler, HTTPServer

class Handler(BaseHTTPRequestHandler):
    def _send(self, code: int, payload: dict) -> None:
        body = json.dumps(payload).encode()
        self.send_response(code)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def do_GET(self) -> None:
        if self.path == "/health":
            return self._send(200, {"ok": True})
        if self.path == "/items":
            return self._send(200, {"items": []})
        if self.path == "/secret":
            return self._send(404, {"error": "no such route"})
        return self._send(404, {"error": "missing"})

    def do_POST(self) -> None:
        if self.path != "/items":
            return self._send(404, {"error": "missing"})
        n = int(self.headers.get("Content-Length", "0"))
        raw = self.rfile.read(n)
        try:
            json.loads(raw or b"{}")
        except json.JSONDecodeError:
            return self._send(400, {"error": "bad json"})
        return self._send(201, {"id": "1"})

    def log_message(self, fmt: str, *args) -> None:
        return

if __name__ == "__main__":
    HTTPServer(("127.0.0.1", 8077), Handler).serve_forever()

replay.sh 应该很无聊。面试官很累。无趣是一种功能。

#!/usr/bin/env bash
set -euo pipefail
python sticky_404.py & srv=$!
cleanup() { kill "$srv" 2>/dev/null || true; }
trap cleanup EXIT
sleep 0.3
python agent_run.py --base http://127.0.0.1:8077 --ledger ledger.jsonl
test -s ledger.jsonl
python - <<'PY'
import json, pathlib, sys
rows = [json.loads(l) for l in pathlib.Path("ledger.jsonl").read_text().splitlines() if l]
secrets = [r for r in rows if r.get("name") == "GET /secret"]
if len(secrets) > 1:
    sys.exit("retried the documented 404")
if len(rows) > 32:
    sys.exit("ledger longer than the published budget")
print(f"ok {len(rows)} events")
PY

用你周一会实际运行的方式去跑评分器,而不是演示视频里的方式。

chmod +x replay.sh
python -m pytest test_loop_budget.py -q
./replay.sh

评分规则活在测试里,不活在感觉里

你已经知道如果分数活在名为 feelings.xlsx 的表格里会发生什么。两个面试官会争论"主动性"。把分数放到账本旁边。测试文件就是评分规则。如果有人还是想要一段叙事,他们可以在测试通过后去读 STOP.md。

# test_loop_budget.py
from pathlib import Path
import pytest
from loop_budget import BudgetBlown, LoopBudget

def test_repeated_404_trips_the_stop(tmp_path: Path):
    b = LoopBudget(tmp_path / "ledger.jsonl", max_identical=3, wall_s=5)
    def boom():
        return 24, 32, "GET /secret -> 404"
    b.call_tool("GET /secret", boom)
    b.call_tool("GET /secret", boom)
    with pytest.raises(BudgetBlown, match="repeated error"):
        b.call_tool("GET /secret", boom)

def test_model_cap(tmp_path: Path):
    b = LoopBudget(tmp_path / "ledger.jsonl", max_model=2, wall_s=5)
    b.record("model", "plan", 10, 40, None)
    b.record("model", "plan", 10, 40, None)
    with pytest.raises(BudgetBlown, match="model calls"):
        b.record("model", "plan", 10, 40, None)

def test_clock(tmp_path: Path, monkeypatch):
    b = LoopBudget(tmp_path / "ledger.jsonl", wall_s=0.01)
    monkeypatch.setattr("loop_budget.time.monotonic", lambda: b.deadline + 1)
    with pytest.raises(BudgetBlown, match="wall clock"):
        b.record("tool", "noop", 0, 0, None)

这三个人都通过了,候选人才值得一场对话。repeated-404 测试失败,你就可以结束循环——面试的循环——而不用就格式问题争论。风格是下游的。停止按钮才是功能。

周三你就会看到的失败模式

第一个题目包看起来自信满满,实则空空如也。STOP.md 说"遇到错误就停止",但 agent_run.py 捕获了 Exception 然后继续。账本只有一行,写着 ran ok。这不是账本。这是新闻稿。你因为缺少证据而否决它,不是因为缺少文采。

第二个题目包重试了 /secret,因为模型"想确保一下"。确定性不是预算。如果他们诚实记录了,duplicate_of 列会像烟雾报警器一样亮起来。如果他们没有记录重试,你因为伪造账本而否决他们。无论哪种方式,题目包都起到了作用。你没有招到一个带着微笑的重试风暴。

第三个题目包把全部预算都花在规划上了。十二次 model 调用,零次 tool 调用,一篇关于 REST 的漂亮文章。免费模型让那篇文章看起来是免费的。对你来说它不是免费的,因为你还是得把它读完。当账本从未触及 GET /items 时,replay.sh 应该非零退出。一个只说话的 agent 是一件披着 trench coat 的博客文章。

第四个题目包更阴险。它 shell 出到一个在沙盒服务器上长时间运行的 helper,然后把工作放到后台,这样 replay.sh 两秒就退出了。你的驱动上的 wall-clock 限制看不到那个孤儿。在 STOP.md 的评分规则里加一行:没有残留进程,而且 replay.sh 退出后必须 pgrep -f agent 找不到任何东西。免费服务器依然有 PID。PID 在你不看的时候依然会撒谎。

这个题目包不适用的情况

不要用它来筛选应该考哈希表的实习生。你会惩罚那些没有在演 agent 的人。如果你的法务团队还没批准把回家作业文本发给第三方模型,也不要用它。候选人的 NDA 不是你可以用幻觉重试来消磨的东西。不要用它来对别人的端点做隐蔽的负载测试。sticky 404 放在 localhost 上是有原因的。

这个方法在你把产品吹大的时候也会失效。一旦你要求 Kubernetes、一个队列和一个仪表盘,候选人就能在"最终一致性"的背后藏住一个失控的循环。让服务保持无聊,这样预算才能响亮。

局限性跟着示例代码走。LoopBudget 不知道 token、GPU 或限速头。它只计算调用次数和相同的错误字符串。两个不同的 404 body 会看起来像是进展。如果你需要更严格的匹配,hash 路由加状态码,而不是模型的道歉。wall clock 用的是单机上的 monotonic。它救不了在一个候选人把重活放到别处、只寄回收据的情况。

你这边也要闭环

在你收集了几个题目包之后,先读账本,再读 README。你会感受到肩膀上的差异。好的那份很短。打了 /health,创建了一个 item,记录了一次禁止的 404,然后停止。差的那份在叙事。当预算只有十二次的时候,叙事是一种味道。

如果你想在发给真人之前找一个地方排练这个题目包,一个免费模型加一台免费服务器就是全部舞台。MonkeyCode 是其中一个选项。然后去评审停止条件,让 PR 排队等着。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
Agent「修复成功」但进程从未退出引发的生产事故
下一篇
部署 AI 推理网关前,先查队年龄龄而非面板利用率