尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Cloudflare Workers 上跑 LLM 长任务:用 Queue 与 Durable Object 终结 524 超时
第一次被 524 支配的那个下午我以为代码写坏了。页面提交一篇作文后端 Worker 调用大语言模型做评分逻辑也很简单拿请求、拼 prompt、调远程模型接口、解析返回、把分数写回响应。结果浏览器转圈转了一分多钟最后蹦出一行超时错误。反复加日志、拆 prompt、换模型参数问题还是隔三差五出现。后来我意识到不是代码的错而是我让 HTTP 请求去等待一次 LLM 评分这件事本身就设计错了。LLM 长任务和 Web 请求的生命周期在 Cloudflare Workers 上尤其矛盾。普通 HTTP 请求从进入到响应天然以毫秒、秒为基本单位而一次评分要阅读理解整篇文章再逐 token 生成评语轻松跑上几十秒。Workers 运行环境对单次请求又有明确限制——CPU 时间、墙钟时间都卡得死死的。把这两件事放在一句话里就是标题说的HTTP 请求等不到一次评分。这篇文章会从请求超时现场开始拆解 Workers 的资源边界然后给出一个在生产环境里跑通的异步方案请求负责登记、队列负责流转、Durable Object 负责状态和续命。如果你也要在 Workers 上跑 LLM 长任务这篇文章可以直接拿来当设计参考。1. 一次等不到评分的现场从 524 看 LLM 任务在 Worker 里的死法1.1 这个业务场景长什么样我在做模拟项目X的时候需要给用户提交的作文做自动评分。用户写一篇 800 字左右的文章系统调用大语言模型按内容、结构、语言三个维度分别打分再生成一段可读的评语。这个功能最开始的实现非常直白一个 Worker 就是唯一入口收到POST /grade请求后解析作文拼好评分 prompt然后await远程模型接口拿到结果后直接返回给前端。调用链大概是这样的POST /grade - 解析请求体 - 拼接评分 prompt - await fetch(remoteLlmApi) - 解析模型返回 - Response.json({ contentScore, structureScore, languageScore, comment })单看这个链路没有任何明显问题。但实际一跑100 次请求里总有 5 到 10 次超时。作文越长、要求模型写得越详细超时概率就越高。更难受的是超时不固定同一个请求重试一次可能就成功了完全没有稳定规律排查起来非常恼火。1.2 超时到底发生在哪把 Worker 日志打开超时时请求的完整时间线其实很清晰请求进来了模型接口调用发出去然后日志就停在等待模型返回这一行再往后就没有输出了。平台侧返回的是 524 或者 522意思是网关在规定时间内没等到源站响应连接被强制断开。关键点在于调用外部模型接口时等待时间虽然不消耗 CPU但会消耗墙钟时间。Workers 对每个请求不光有 CPU 时间限制还有墙钟时间限制。哪怕你的代码本身只运行了 1 秒 CPU墙钟一到请求照样被杀。远程 LLM 推理恰恰是典型的长时间等待网络返回场景和平台限制正面撞车。1.3 LLM 推理的耗时构成很多人对 LLM 推理耗时的感知是大概几秒但放到评分场景里这个数字会膨胀很多。生成式模型是逐 token 输出的评分要读完整篇作文还要生成一段有信息量的评语输入和输出都是大开销。我用一个粗略公式估算一次评分的耗时总耗时 ≈ 输入预填充耗时 输出 token 数 × 单 token 生成耗时 排队耗时 网络耗时举个例子一篇 800 字作文输入约 1200 token模型输出 250 token 评语。如果生成速度是每秒 20 token光生成就要 12.5 秒。加上网络延迟、模型排队、输出解析一次评分 20 到 60 秒非常常见。这个时长放在一个同步 HTTP 请求里几乎必然撞上墙钟限制。所以等不到评分不是偶发事故而是同步架构下的必然结果。2. Workers 的时间账本CPU 时间、墙钟时间和它们能救你的地方2.1 先看懂两张写进文档的表格要把长任务搬上 Workers第一步不是写代码而是搞清楚平台的硬性边界。我这里列几个关键指标以官方文档为准数据是我在模拟项目X里实测时校对过的常见值。指标免费计划付费计划常见值单请求 CPU 时间10 ms30 s单请求墙钟时间约 30 s5 分钟内存上限128 MB128 MB单请求子请求数量501000很多人看到这张表会误以为付费计划能把请求挂 5 分钟那同步等一次评分应该够了。理论上是够了但实际操作中你会遇到更麻烦的问题浏览器、网关、负载均衡器不会真的让你挂 5 分钟用户也没有耐心盯着页面转圈。所以这张表真正的价值不是告诉你可以等多久而是告诉你不要设计成同步等待。2.2 CPU 时间和墙钟时间的区别决定你能不能这么写这是理解整个方案的基础。CPU 时间指的是代码实际占用处理器干活的时间比如循环、JSON 解析、字符串拼接。墙钟时间是请求从进入 Worker 到响应离开的总时间包括所有等待。打个比方你去买菜自己走路一公里花 10 分钟排队付款等 40 分钟。CPU 时间是走路的 10 分钟墙钟时间是出门到回家的 50 分钟。Workers 限制的是走路时间最多 30 秒但出门到回家最多 5 分钟。如果你的主要时间花在排队等网络上那 CPU 限制不会拦住你墙钟限制会。放在评分任务上就是调用模型接口期间 CPU 基本是空闲的但墙钟在走。这也是为什么在 Worker 里同步 await 一个 30 秒的模型接口会经常挂在 5 分钟墙钟上——因为一个请求里你可能还要处理多次重试、解析大响应、写存储墙钟很容易就超了。2.3 这些限制对评分任务意味着什么如果直接在请求里 await 模型接口免费计划的 30 秒墙钟基本顶不住付费计划的 5 分钟勉强够但是把用户请求挂 5 分钟体验上等于报废。更别说如果模型服务偶发变慢5 分钟一样会超。所以正确思路只有一个把等待评分结果从请求生命周期里拆出来。请求只负责受理后台慢慢跑跑完用户再主动来取。这个转变看着简单但涉及一套异步任务架构接下来就讲它。3. 把同步等待改成异步流转Queue、Durable Object 与状态机3.1 核心原则请求只做受理不做推理改造后的流程是用户提交作文Worker 立刻生成一个taskId把作文和评分参数存起来然后返回已受理。后台消费者从队列里拿到消息真正调用模型接口做评分把结果写回状态中心。用户拿到taskId后轮询结果接口直到任务变成done。这个改动给评分任务带来了几个质变请求耗时可压缩到 100 毫秒以内HTTP 请求和 LLM 推理彻底解耦任务失败可以重试可以通过消费者并发控制避免把外部模型服务压垮。代价是前端要多写一个轮询逻辑但这个代价非常值得。异步化并不是 Workers 特有的技巧传统后端早就在用。但 Workers 上做异步化有一个特别之处没有常驻进程你必须有明确的存储来记录任务状态有明确的触发机制来保证后台任务真的会跑完。这就要用到 Cloudflare 家族的另外几个组件。3.2 四个组件怎么分工整个方案里我用了四个主要组件分工非常清晰组件职责生产者 WorkerHTTP 入口校验参数、生成 taskId、登记状态、发送队列消息Queue消息缓冲和重试是任务流转的管道消费者 Worker订阅队列调用 LLM 接口执行评分回写状态Durable Object任务状态中心提供强一致存储和 Alarm 续命能力KV 在这里是可选项我用来做最终结果缓存。但注意KV 不能作为唯一的任务状态源原因后面踩坑部分细说。为什么需要 Queue而不是直接往 Durable Object 里塞消息因为 Queue 天然提供削峰、失败重试、并发控制而且让生产者和消费者完全解耦。如果你不用 Queue每次评分任务都要自己写重试逻辑、处理并发很容易在崩溃场景下丢任务。Queue 的至少一次投递结合状态机能构建出可靠的幂等处理。3.3 为什么状态必须建立在 Durable Object 上评分任务是一个典型的状态机pending到running再到done或failed。这个状态必须强一致因为消费者可能在崩溃后重试同一条消息轮询接口也在随时读取状态。如果两个入口对任务状态的理解不一致就会出现同一篇作文被评分两次或者结果被旧值覆盖。KV 是最终一致性存储写入后立刻读取可能拿到旧值这在任务状态判断时是致命的。Durable Object 则是单实例强一致存储同一个taskId永远落到同一个 DO 实例上读和写都走同一份存储不存在多个副本之间的同步延迟。再加上 Durable Object 支持 Alarm可以安排未来某个时间点再次触发代码这是长时间任务的续命关键。Alarm 的用法后面会展示。一句话先说明白如果远程模型接口支持异步任务模式提交后返回一个 taskId你稍后查结果消费者根本不需要一直等。它可以把远程 taskId 存进 DO然后设置 60 秒后的闹钟。60 秒后 DO 被系统重新唤醒去查一次结果没完成就再设 60 秒。这样每一次单独的请求执行时间都很短但任务总时长可以远超单次请求墙钟限制。4. 评分任务的可运行实现从入队、执行再到前端拿结果4.1 任务状态机设计先定义任务的数据结构。我习惯把所有业务字段放在一个GradeTask里状态字段单独维护。这里为了简洁合并成一个对象interface GradeTask { id: string; // taskId全局唯一 essay: string; // 待评分作文 status: pending | running | done | failed; result?: GradeResult; error?: string; createdAt: number; updatedAt: number; } interface GradeResult { contentScore: number; structureScore: number; languageScore: number; comment: string; }状态流转很简单pending表示已受理但还没开始running表示消费者开始调模型了成功后进入done失败进入failed。注意running这个状态非常重要它是幂等判断的依据也是前端展示正在评分的依据。4.2 生产者 Worker 代码生产者只做三件事生成任务、登记状态、发队列。先从 DO 里根据taskId拿到同一个实例的 stub再写入初始任务最后发送消息。interface Env { TASK_QUEUE: QueueGradeTask; TASK_DO: DurableObjectNamespace; RESULTS_KV: KVNamespace; } export default { async fetch(req: Request, env: Env): PromiseResponse { if (req.method ! POST) { return new Response(not found, { status: 404 }); } const payload await req.json(); const task: GradeTask { id: crypto.randomUUID(), essay: String(payload.essay), status: pending, createdAt: Date.now(), updatedAt: Date.now(), }; const stub env.TASK_DO.get(env.TASK_DO.idFromName(task.id)); await stub.createTask(task); await env.TASK_QUEUE.send(task); return Response.json({ taskId: task.id, status: task.status }); }, };注意这里的crypto.randomUUID()生成一个随机 ID既作为队列消息主键也作为轮询接口的路径参数。idFromName能保证同一个taskId永远映射到同一个 Durable Object 实例这是强一致的前提。4.3 Durable Object 的状态存储写法DO 类里定义任务状态相关的读写方法。核心是markRunning要返回布尔值告诉消费者这条消息是否已经被处理过实现幂等。export class TaskDO extends DurableObjectEnv { async createTask(task: GradeTask) { await this.ctx.storage.put(task, task); } async markRunning(): Promiseboolean { const task await this.ctx.storage.getGradeTask(task); if (!task || task.status running || task.status done) { return false; } task.status running; task.updatedAt Date.now(); await this.ctx.storage.put(task, task); return true; } async markDone(result: GradeResult) { const task await this.ctx.storage.getGradeTask(task); if (!task) return; task.status done; task.result result; task.updatedAt Date.now(); await this.ctx.storage.put(task, task); } async markFailed(error: string) { const task await this.ctx.storage.getGradeTask(task); if (!task) return; task.status failed; task.error error; task.updatedAt Date.now(); await this.ctx.storage.put(task, task); } async getTask(): PromiseGradeTask | null { return this.ctx.storage.getGradeTask(task); } }注意这里所有方法都是 Durable Object 实例上的方法通过 stub 调用。外部消费者调用markRunning时如果返回false说明任务已经被处理过或者正在处理中应该直接跳过避免重复评分。4.4 队列消费者与评分执行消费者的核心逻辑是从队列拿消息先把任务标记为running再调用外部模型接口评分。这里我用一个gradeByLlm函数代替具体模型调用实际项目里替换成 Workers AI 或者任意兼容接口都行。export default { async queue(batch: MessageBatchGradeTask, env: Env) { for (const msg of batch.messages) { const task msg.body; const stub env.TASK_DO.get(env.TASK_DO.idFromName(task.id)); // 幂等检查如果已经在跑或者已完成直接跳过 if (!(await stub.markRunning())) { continue; } try { const result await gradeByLlm(task.essay, env); await stub.markDone(result); // 结果写一份到 KV 做缓存轮询时优先读 await env.RESULTS_KV.put( result:${task.id}, JSON.stringify(result), { expirationTtl: 86400 }, ); } catch (err) { await stub.markFailed((err as Error).message); // 需要重试就 throw让队列重新投递 // 如果是不需要重试的请求错误可以不 throw直接丢弃消息 throw err; } } }, }; async function gradeByLlm(essay: string, env: Env): PromiseGradeResult { // 这里替换成实际模型调用建议用 AbortSignal.timeout 控制超时 const controller new AbortController(); const timer setTimeout(() controller.abort(), 60_000); try { const resp await fetch(env.LLM_ENDPOINT, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ essay }), signal: controller.signal, }); const data await resp.json(); return { contentScore: data.contentScore, structureScore: data.structureScore, languageScore: data.languageScore, comment: data.comment, }; } finally { clearTimeout(timer); } }这里有一个关键点队列消费者同样受 CPU 时间和墙钟时间限制不是躲在队列后面就可以无限跑。如果一条消息里的评分要 60 秒那消费者还好如果评分要 5 分钟以上就必须配合 Alarm 做续命见下一节。4.5 用 Alarm 续命单次请求跑不完怎么办某些极端场景下一次评分的总时长可能超过 5 分钟比如模型排队严重、作文特别长、评语要求特别详细。这时候不能在一个消费者请求里傻等而应该利用远程接口的异步模式提交评分任务后立刻拿到一个远程任务 ID然后让 Durable Object 每隔一段时间去查一次结果。远程模型接口如果是 OpenAI 兼容接口通常不会提供原生异步模式。但一些推理网关、自建服务会提供202 Accepted 轮询地址的形式。我封装过一个通用写法export class TaskDO extends DurableObjectEnv { // 当消费者发现远程任务尚未完成时调用此方法注册轮询信息 async registerRemotePoll(remoteTaskId: string, checkUrl: string) { await this.ctx.storage.put(remoteTask, { remoteTaskId, checkUrl, status: running, }); await this.ctx.storage.setAlarm(Date.now() 60_000); } async alarm() { const remote await this.ctx.storage.getRemoteTask(remoteTask); if (!remote || remote.status done) return; const resp await fetch(remote.checkUrl, { signal: AbortSignal.timeout(10_000), }); const data await resp.json(); if (data.status completed) { await this.ctx.storage.put(remoteTask, { ...remote, status: done, result: data.result, }); } else { // 没跑完60 秒后再来 await this.ctx.storage.setAlarm(Date.now() 60_000); } } }这个模式非常灵活每一次 alarm 触发都是一个独立请求墙钟很短但任务总时长可以通过不断setAlarm无限延伸。这就是把长任务搬进 Cloudflare Workers的终极形态——不是让一个请求跑很久而是让很多个短请求接力跑完一件事。4.6 客户端获取结果的两种方式轮询与 SSE任务提交后前端需要一个接口查状态。轮询是最稳的写法查询代码如下async fetch(req: Request, env: Env) { const url new URL(req.url); const match url.pathname.match(/^\/tasks\/(.)$/); if (!match) return new Response(not found, { status: 404 }); const taskId match[1]; const stub env.TASK_DO.get(env.TASK_DO.idFromName(taskId)); const task await stub.getTask(); if (!task) return new Response(task not found, { status: 404 }); return Response.json({ status: task.status, result: task.result, error: task.error, }); }前端每 2 秒调一次这个接口拿到done就展示分数。轮询的缺点是要频繁发起 HTTP 请求但优点是没有长连接风险稳定可靠。如果追求更实时的体验可以用 SSE。Worker 返回一个text/event-stream流每 2 秒往流里写一次状态const encoder new TextEncoder(); const stream new ReadableStream({ async start(controller) { for (let i 0; i 60; i) { const task await stub.getTask(); if (task.status done) { controller.enqueue(encoder.encode(data: ${JSON.stringify(task.result)}\n\n)); controller.close(); return; } controller.enqueue(encoder.encode(data: ${JSON.stringify({ status: task.status })}\n\n)); await new Promise((r) setTimeout(r, 2000)); } controller.enqueue(encoder.encode(data: {status:timeout}\n\n)); controller.close(); }, }); return new Response(stream, { headers: { Content-Type: text/event-stream }, });注意 SSE 本质是长连接挂太久同样有被平台断开的可能。我的经验是 SSE 控制在 2 分钟以内比较稳超过这个时间就让前端自动切换成轮询或者直接刷新页面重新查状态。5. 实测数据与配置清单40 篇作文跑一遍之后5.1 一次真实的队列压测观察我把这套方案放回模拟项目X里用 40 篇长短不一的作文做了一轮完整测试。外部模型接口是同一个平均单次评分耗时约 18 秒最慢的一篇 47 秒。消费者并发设为 1 的时候40 篇作文排队跑完接近 13 分钟并发设为 3总时长降到约 5 分钟并发设为 5总时长约 4 分钟。超时率从原来同步方案的 5% 到 10% 降到 0。这个结果说明两件事第一异步化解决了请求等不到的问题所有任务都能在后台被消费掉第二总耗时的瓶颈几乎完全在外部模型接口本身Worker 这边的队列和状态读写开销非常小。所以优化方向很明确要么换更快的模型服务要么提高消费者并发要么在评分 prompt 上做减法减少输出 token 数。5.2 并发、批次和解散带理解清楚队列消费者有两个参数最容易踩坑max_batch_size和max_concurrency。max_batch_size表示一次投递给消费者的消息数量。默认值可能大于 1如果一批消息里每条都要跑几十秒的 LLM 调用那这个消费者请求的墙钟时间非常容易超限。我的建议是长任务场景下直接把max_batch_size设为 1让每条消息独立消费互相不拖累。吞吐量不够就提高并发不要靠单次多跑几条来解决。max_concurrency决定同一时刻有多少消息正在被并行处理。这个值受外部模型接口 QPS 限制。把外部模型打爆会返回 429任务会失败重试反而更慢。我的经验是从 3 到 5 起步观察外部服务响应时间稳定后再逐步上调。5.3 控制推理成本的三件事长任务部署到 Workers 之后还要盯住推理成本。第一件事是限制输出 token 数。评语长度对分数稳定性的边际收益很低但 token 成本涨幅很大。我的评分 prompt 里固定要求评语不超过 150 字配合模型接口的max_tokens参数控制在 300 左右费用直接降了一大半。第二件事是轮询接口不要频繁打 DO。DO 是按读写次数计费的前端每 2 秒轮询一次如果每次轮询都读 DO写任务多时成本会很可观。我的优化是结果写完后放进 KV 并设置 TTL轮询接口先尝试读 KV读不到再回退到 DO。因为结果一旦写入就不会再变KV 的最终一致性在这个场景下完全可接受。第三件事是给每次模型调用加超时。用AbortSignal.timeout(60_000)或者手动AbortController防止个别请求挂在网络上既浪费时间也占队列并发额度。5.4 关键配置清单最后给一份可以直接抄的wrangler.toml核心配置name grader-worker main src/index.ts compatibility_date 2025-01-01 [[queues.producers]] binding TASK_QUEUE queue grader-tasks [[queues.consumers]] queue grader-tasks max_batch_size 1 max_concurrency 5 [[durable_objects.bindings]] name TASK_DO class_name TaskDO [[kv_namespaces]] binding RESULTS_KV id your-kv-namespace-idmax_batch_size 1是长任务场景下的关键配置max_concurrency 5则要根据外部模型服务的承受力调整。把队列、DO、KV 三个绑定配齐消费者 Worker 和生产者 Worker 可以是同一个入口文件的不同 exportCloudflare 会根据事件类型自动分流。6. 踩坑记录这些问题我花了一晚上才搞明白6.1 waitUntil 不是免死金牌最早我想过用ctx.waitUntil()在响应返回后继续跑评分逻辑以为这样可以绕过超时。实测发现waitUntil只是告诉平台响应返回后还有异步任务要跑平台确实会继续执行一会但具体能跑多久完全没有保证而且任务崩溃后没有重试机制状态也无处查。结果就是看起来任务启动了实际可能跑到一半就被平台回收用户轮询永远等不到结果。正确做法是把它完全交给 Queue 和 DO让平台管理生命周期而不是依赖请求返回后那一小段不确定的窗口。waitUntil只适合做日志上报、缓存清理这类轻量动作。6.2 重复消费导致评分翻倍队列的投递语义是至少一次不是恰好一次。消费者处理一条消息时如果遇到 Worker 重启、请求超时、进程崩溃平台会把这条消息重新投递。如果没有幂等处理同一篇作文就会被评分两次产生两份结果用户也会看到分数跳变。我的解决方法就是前面代码里的markRunning返回布尔值消费者开始处理前先尝试把状态从pending改成running如果改不了说明这条消息已经有人处理过直接跳过。这样即使消息被重复投递评分也只执行一次。6.3 KV 读不到刚刚写入的结果一开始我在轮询接口里直接读 KV结果发现任务明明已经完成KV 里却查不到。原因是 KV 是最终一致性的存储写入后立刻读取可能拿到旧值。评分结果写 KV 和用户轮询读 KV 之间只有几百毫秒非常容易踩中这个窗口。后来我把 DO 作为任务状态的唯一权威来源KV 只是结果缓存。轮询接口先尝试 KV读不到再读 DO。注意不要让 KV 读失败影响状态判断KV 命中失败时必须回退到 DO否则用户会看到任务状态一直在running。6.4 本地 wrangler dev 和线上行为不一致本地开发时Queue 是模拟实现不会真的触发消费者也不会模拟重试语义Durable Object 本地存储也是独立的一份。所以经常出现本地测得好好的一部署线上就出问题的情况。这不是代码逻辑不对而是本地环境和线上机制不同。我的建议是本地只验证生产者和 DO 状态流转队列消费行为一定要部署到线上测试或者用 Cloudflare 提供的本地队列模拟器仔细对一遍配置。线上测试时多用真实请求跑几次重点观察队列消息有没有堆积、消费者有没有报错。6.5 模型输出太长把存储撑爆有次我把评语的max_tokens调到 1500模型真的输出了一大段废话结果 Durable Object 的put直接失败任务卡在running状态出不来。DO 存储对单条记录的大小有限制完整模型返回里的历史消息、思考过程、冗长 JSON 都不该写进去。最终我规定只允许把评分结果的结构化字段写入 DO原始模型响应最多存一个摘要。评语限制在 200 字以内低 Token 输出既能省流也能避免存储写入失败。长文本任务一定要记得状态中心存的是状态不是数据堆。最后分享一个我自己的习惯现在无论做什么功能只要里面出现可能超过 10 秒的环节我都会先问自己一个问题——用户真的需要同步拿到这个结果吗绝大多数时候答案是不需要。于是代码结构就会变成先返回 taskId后台慢慢跑跑完通知或者轮询。这套以 Queue 和 Durable Object 为核心的异步模式不只在作文评分项目里帮了大忙之后做文档总结、批量标签生成也都直接复用了同一套骨架。它没有让 LLM 变快但让 Workers 里的长任务变得可控这比任何奇技淫巧都重要。
RELATED

相关推荐

AI协同开发STM32实战:从需求拆解到调试验证的完整流程

AI协同开发STM32实战:从需求拆解到调试验证的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/19 1:50:26
AI-native芯片设计:稀缺能力不是算力,而是数据、验证与三栖型判断力

AI-native芯片设计:稀缺能力不是算力,而是数据、验证与三栖型判断力

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/19 1:50:26
硬件开发入门十讲:从原理图到量产的全流程工程思维

硬件开发入门十讲:从原理图到量产的全流程工程思维

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/19 1:50:26
MORE NEWS

更多资讯

📰

从零手写朴素贝叶斯:糖尿病预测实战与避坑指南

简介:这份PDF文档面向模式识别、机器学习入门学习者与课程设计者,围绕朴素贝叶斯分类器在医疗场景中的落地展开,解决如何用统计学方法从生理指标中预测糖尿病发病风险的问题。资源包共1个PDF文件,大小约771KB,内容为完…

📰

人工智能读书报告:从搜索与知识表示看AI发展史

简介:这是一份面向人工智能初学者与课程学习者的读书报告文档,围绕人工智能发展史、基本方法、发展方向与应用场景展开梳理,适合用于课程作业参考、知识框架搭建与复习备考。资源包内含1个docx文件,整体约19KB,以文字笔…

📰

LangChain核心组件与实战:从RAG到Agent的大模型编排指南

我第一次用大模型 API 写业务功能时,天真地以为只要把接口调通、提示词写得足够妙,项目就稳了。结果第一个稍微像样的 Demo 就把我教育了一顿:同一段提示词要在三个地方复用,用户多轮对话得自己维护上下文,模型偶尔规规…

📰

Spring Boot配置从入门到排错:application.yml、绑定与优先级

1. 聊清楚一件事:Spring Boot 为什么把配置默认放在 application.yml一提到 Spring Boot 的“配置”,很多人第一时间想到的是那些让人眼花缭乱的自动装配,而不是一份 application.yml。但在实际项目里,真正让本地运行好好的服务一…

📰

任务调度系统实践:构建自动化数据采集与解析管家

咱们做数据采集的老哥们应该都碰到过这种情况:手里的重复抓取和解析作业越来越多,今天手动跑一次,明天忘了跑,后天数据库里空了半截数据,或者同一批数据被重复解析了好几遍,越管越乱。我去年也掉进这个坑里…

📰

大数据面试真题拆解:从原理到排障的工程化应答

简介:本资源是2023年面向大数据开发、运维、云计算、数据治理及架构师岗位的全栈面试题集,系统覆盖Linux/Shell基础、Hadoop生态(HDFS/MapReduce/YARN)、ZooKeeper协调服务、Flume/Kafka实时采集与消息系统、Hive数仓与SQL优化、H…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬