news 2026/10/8 20:12:21

用 Next.js + LangGraph.js 构建简历 AI Agent 实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 Next.js + LangGraph.js 构建简历 AI Agent 实战

1. 为什么简历工具值得用 AI Agent 重做一遍

简历这个赛道看起来已经很拥挤了,各种在线简历生成器、模板站、排版工具一抓一大把。但真正动手做过简历产品的人都知道,传统简历工具的天花板非常明显:它们本质上只是"排版器",用户还是得自己想内容、自己组织语言、自己判断写得好不好。一个工作三年的人和一个刚毕业的学生,打开同一个简历工具,得到的帮助几乎是一样的——这显然不合理。

我这次要落地的项目,就是用Next.js + LangGraph.js搭一个真正意义上的简历 AI Agent。它和普通"套模板"工具的区别在于:Agent 会主动追问你的经历、帮你把口语化的描述改写成专业表达、根据目标岗位动态调整内容侧重、甚至在你写完之后帮你做一轮"HR 视角"的挑刺。关键词里的AI Agent、LangGraph.js、Next.js三个词,正好对应了这个项目的三个核心:智能决策、流程编排、产品落地。

为什么是 Agent 而不是简单的"调一次大模型 API"?因为简历优化天然是一个多轮、有状态、需要分支判断的过程。比如用户说"我想投后端开发岗",Agent 需要判断:用户有没有相关项目经验?如果有,追问技术栈和量化成果;如果没有,是不是要引导他挖掘可迁移的经历?这种"根据上一步结果决定下一步问什么"的逻辑,用单次 API 调用根本做不出来,必须靠 Agent 的状态机来编排。

这篇文章适合谁看?如果你已经会写 React、了解 Next.js 的基本用法,想找一个完整、能跑通、有真实业务价值的 AI Agent 项目来练手,那这篇就是为你写的。我会把架构设计、LangGraph.js 的图怎么画、Next.js 的前后端怎么衔接、流式输出怎么处理、以及我在实测中踩过的坑,全部摊开讲。不会只给你一个"Hello World"级别的 Demo,而是能真正拿去改造成产品的完整方案。

先说结论:整个项目的技术栈是Next.js 14(App Router)+ LangGraph.js + OpenAI 兼容接口 + Tailwind CSS,部署在支持 Node.js 运行时的平台上。LangGraph.js 负责 Agent 的流程编排,Next.js 的 Route Handler 负责把 Agent 包装成流式 API,前端用ReadableStream消费流式数据实现"打字机"效果。下面从架构开始拆。

2. 简历 Agent 的整体架构与 LangGraph.js 的图设计

2.1 为什么选 LangGraph.js 而不是自己写状态机

很多人第一反应是:Agent 不就是"循环调用大模型 + 判断要不要调工具"吗,我自己写个 while 循环不就行了?我一开始也是这么想的,直到我把简历 Agent 的流程画出来才发现,自己写状态机很快就会失控。

简历 Agent 的真实流程是这样的:先做意图识别(用户是想新建简历、优化某段经历、还是针对岗位做匹配),然后进入信息采集环节(多轮追问),采集够了进入内容生成,生成后进入质量评估,评估不通过要回退到采集或生成,通过之后才输出。这里面有循环、有条件分支、有并行节点(比如同时做"专业度检查"和"岗位匹配度检查"),手写状态机维护起来非常痛苦。

LangGraph.js 的核心价值就是把这种流程抽象成图(Graph):节点(Node)是处理单元,边(Edge)是流转逻辑,条件边(Conditional Edge)负责分支。它天然支持循环、支持状态在节点间传递、支持中断和恢复。对于简历这种"多轮对话 + 分支判断"的场景,几乎是量身定做。

提示:LangGraph.js 和 Python 版的 LangGraph 概念基本一致,但 JS 版在类型定义和流式处理上有些差异,网上大部分教程是 Python 的,迁移时要注意 API 命名。

2.2 简历 Agent 的状态结构设计

LangGraph 里最核心的概念是State(状态),它是在所有节点之间流转的共享数据。简历 Agent 的状态我设计成这样:

// lib/agent/state.ts import { Annotation } from "@langchain/langgraph"; export const ResumeState = Annotation.Root({ // 对话历史,用 reducer 做追加 messages: Annotation<BaseMessage[]>({ reducer: (prev, next) => prev.concat(next), default: () => [], }), // 当前阶段:collect / generate / evaluate / done stage: Annotation<string>({ reducer: (_, next) => next, default: () => "collect", }), // 结构化的简历数据 resumeData: Annotation<ResumeData>({ reducer: (prev, next) => ({ ...prev, ...next }), default: () => ({}), }), // 目标岗位 targetRole: Annotation<string>({ reducer: (_, next) => next, default: () => "", }), // 评估得分与反馈 evaluation: Annotation<Evaluation>({ reducer: (_, next) => next, default: () => ({ score: 0, feedback: [] }), }), // 重试次数,防止死循环 retryCount: Annotation<number>({ reducer: (_, next) => next, default: () => 0, }), });

这里有几个设计要点值得展开。第一,messages用了concatreducer,因为对话历史是只增不减的,每次节点返回新消息时自动追加,不用手动管理。第二,resumeData用对象合并 reducer,因为采集阶段可能分多轮填充不同字段(先填基本信息,再填项目经历),合并比覆盖更合理。第三,retryCount是我特意加的熔断机制——如果评估一直不通过,不能让 Agent 无限循环下去,超过 3 次就强制输出当前结果并提示用户手动调整。

2.3 图的节点划分与流转逻辑

整个 Agent 我拆成了 5 个节点,每个节点职责单一:

节点名职责输入输出
intentNode识别用户意图,决定进入哪个分支最新用户消息更新 stage
collectNode多轮追问,采集简历信息对话历史 + 当前 resumeData追问问题或更新 resumeData
generateNode根据采集信息生成简历内容resumeData + targetRole生成的简历文本
evaluateNode从 HR 视角评估简历质量生成的简历评分 + 改进建议
finalizeNode整理输出,结束流程所有状态最终简历

流转逻辑用条件边控制。intentNode之后根据 stage 决定去collectNode还是generateNode;generateNode之后固定去evaluateNode;evaluateNode之后是关键分支——如果评分达标或重试超限,去finalizeNode,否则回到collectNode补充信息。

// lib/agent/graph.ts import { StateGraph, END } from "@langchain/langgraph"; const workflow = new StateGraph(ResumeState) .addNode("intent", intentNode) .addNode("collect", collectNode) .addNode("generate", generateNode) .addNode("evaluate", evaluateNode) .addNode("finalize", finalizeNode) .addEdge("__start__", "intent") .addConditionalEdges("intent", routeByStage, { collect: "collect", generate: "generate", }) .addConditionalEdges("collect", routeAfterCollect, { generate: "generate", collect: "collect", // 继续追问 }) .addEdge("generate", "evaluate") .addConditionalEdges("evaluate", routeAfterEvaluate, { finalize: "finalize", collect: "collect", }) .addEdge("finalize", END); export const resumeAgent = workflow.compile();

这套图跑起来之后,整个简历优化过程就变成了一个"有记忆、会判断、能回退"的智能流程。用户不需要知道背后发生了什么,他只会感觉"这个工具好像真的懂我在写什么"。

3. Next.js 侧如何把 Agent 包装成可用的产品接口

3.1 App Router 下的流式 Route Handler

Agent 跑起来只是第一步,怎么把它接到前端才是产品化的关键。简历生成这种场景,用户最讨厌的就是"点一下按钮,转圈 20 秒,然后一次性蹦出一大段文字"。所以流式输出是刚需,让用户看到内容一个字一个字冒出来,体验完全不同。

Next.js 14 的 App Router 里,Route Handler 可以直接返回ReadableStream。LangGraph.js 编译后的图支持.streamEvents()方法,能按事件流式产出每个节点的中间结果。我把两者对接起来:

// app/api/chat/route.ts import { NextRequest } from "next/server"; import { resumeAgent } from "@/lib/agent/graph"; import { HumanMessage } from "@langchain/core/messages"; export const runtime = "nodejs"; // 必须,LangGraph 依赖 Node API export async function POST(req: NextRequest) { const { messages, threadId } = await req.json(); const encoder = new TextEncoder(); const stream = new ReadableStream({ async start(controller) { try { const eventStream = resumeAgent.streamEvents( { messages: [new HumanMessage(messages.at(-1).content)] }, { version: "v2", configurable: { thread_id: threadId } } ); for await (const event of eventStream) { if (event.event === "on_chat_model_stream") { const chunk = event.data.chunk?.content; if (chunk) { controller.enqueue( encoder.encode(`data: ${JSON.stringify({ text: chunk })}\n\n`) ); } } if (event.event === "on_chain_end" && event.name === "finalize") { controller.enqueue( encoder.encode(`data: ${JSON.stringify({ done: true })}\n\n`) ); } } } catch (err) { controller.enqueue( encoder.encode(`data: ${JSON.stringify({ error: String(err) })}\n\n`) ); } finally { controller.close(); } }, }); return new Response(stream, { headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive", }, }); }

这里用的是SSE(Server-Sent Events)格式,每条消息以data:开头、\n\n结尾。前端用EventSource或者fetch+ReadableStream都能消费。我实测下来,fetch方式更灵活,因为可以带 POST body 和自定义 header。

注意:export const runtime = "nodejs"这行千万别漏。LangGraph.js 内部用了一些 Node.js 特有的 API,如果跑在 Edge Runtime 上会直接报错。我一开始图省事没加,调试了半小时才发现是运行时的问题。

3.2 会话持久化:thread_id 与 Checkpointer

简历优化不是一次对话能搞定的,用户可能今天填一半,明天接着填。LangGraph 提供了Checkpointer机制,通过thread_id把每个会话的状态存下来,下次带着同样的thread_id请求,Agent 就能"记得"之前聊到哪了。

开发阶段我用的是MemorySaver,简单直接:

import { MemorySaver } from "@langchain/langgraph"; const checkpointer = new MemorySaver(); export const resumeAgent = workflow.compile({ checkpointer });

但MemorySaver是存在进程内存里的,服务一重启就没了,生产环境必须换成持久化方案。LangGraph.js 官方支持多种存储后端,我选的是PostgresSaver,因为简历数据本身就该存数据库,顺手把会话状态也放进去,运维成本最低。

import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres"; const checkpointer = PostgresSaver.fromConnString(process.env.DATABASE_URL); await checkpointer.setup(); // 首次运行建表

setup()会自动创建几张表来存 checkpoint 和写入记录,跑一次就行。这里有个坑:如果你用的是连接池(比如 PgBouncer),setup()可能会因为事务问题失败,建议用直连跑一次初始化。

3.3 前端如何优雅地消费流式数据

前端这块我用了一个自定义 Hook 来封装流式消费逻辑,把"发消息、收流、更新 UI"三件事解耦:

// hooks/useResumeAgent.ts export function useResumeAgent(threadId: string) { const [output, setOutput] = useState(""); const [loading, setLoading] = useState(false); const send = useCallback(async (content: string) => { setLoading(true); setOutput(""); const res = await fetch("/api/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ messages: [{ role: "user", content }], threadId }), }); const reader = res.body!.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n\n"); buffer = lines.pop() || ""; // 最后一段可能不完整,留到下次 for (const line of lines) { if (!line.startsWith("data: ")) continue; const payload = JSON.parse(line.slice(6)); if (payload.text) setOutput((prev) => prev + payload.text); if (payload.done) setLoading(false); } } }, [threadId]); return { output, loading, send }; }

这里最关键的是buffer 的处理。SSE 的数据块在网络传输中可能被任意切分,一次read()拿到的可能是一条完整消息,也可能是半条。所以必须维护一个 buffer,按\n\n分割,最后一段不完整的留到下一轮拼接。这个细节如果处理不好,会出现 JSON 解析报错或者文字乱码,非常隐蔽。

4. 让简历 Agent 真正"聪明"的几个关键实现

4.1 结构化输出:把大模型的自由文本变成可用数据

简历 Agent 和普通聊天机器人最大的区别是:它需要产出结构化数据,而不是一段散文。比如采集阶段,我需要把用户说的"我在字节干了两年后端"解析成{ company: "字节", duration: "2年", role: "后端" }这样的对象,才能存进数据库、才能做后续的岗位匹配。

LangChain.js 提供了withStructuredOutput方法,配合 Zod schema 可以强制模型输出符合结构的数据:

import { z } from "zod"; const ResumeSchema = z.object({ basic: z.object({ name: z.string().describe("姓名"), years: z.number().describe("工作年限"), targetRole: z.string().describe("目标岗位"), }), experiences: z.array(z.object({ company: z.string(), role: z.string(), duration: z.string(), highlights: z.array(z.string()).describe("量化成果,每条尽量带数字"), })), }); const structuredModel = model.withStructuredOutput(ResumeSchema); const result = await structuredModel.invoke(prompt);

实测下来,withStructuredOutput比手动写 prompt 要求"请输出 JSON"靠谱得多,因为它底层用的是 function calling 或者 JSON mode,模型会严格遵守 schema。但有个坑:字段的describe一定要写清楚,尤其是highlights这种数组字段,我会在 describe 里明确写"每条尽量带数字",模型输出的质量会明显提升。

4.2 追问策略:怎么让 Agent 问出有价值的问题

简历采集最怕的就是 Agent 像个机器人一样问"请描述你的项目经历",用户回一句"做了个电商系统"就没了。好的追问应该是有引导性的,能帮用户把模糊的经历具体化。

我的做法是在collectNode里给模型一个"追问清单",让它根据当前已采集的信息,找出信息密度最低的部分重点追问:

const COLLECT_PROMPT = `你是一位资深简历顾问,正在帮用户完善简历。 当前已采集信息: {currentData} 目标岗位:{targetRole} 请判断:哪些关键信息还缺失?哪些描述过于笼统需要量化? 追问时遵循: 1. 一次只问 1-2 个问题,不要一口气问一堆 2. 问题要具体,比如"这个项目你负责了哪部分?有没有性能提升的数据?" 3. 如果用户描述里有"优化了性能"这类模糊表达,追问具体数字 4. 语气专业但友好,像朋友聊天 如果信息已经足够完整,直接输出 [COLLECT_DONE]`;

这个 prompt 的关键在于给了模型明确的判断标准和输出信号。[COLLECT_DONE]是一个约定好的标记,routeAfterCollect函数检测到这个标记就流转到生成节点,否则继续追问。这种"用文本标记控制流程"的做法在 Agent 开发里很常见,比让模型输出 JSON 控制字段更稳定。

4.3 评估节点:用"HR 视角"做质量把关

评估节点是我觉得整个项目最有价值的部分。它模拟 HR 筛简历的视角,从几个维度给简历打分:

维度权重评估要点
岗位匹配度30%技能、经历是否贴合目标岗位
量化程度25%成果是否有具体数字支撑
表达专业度20%用词是否专业、有无口语化表达
结构清晰度15%逻辑是否清晰、重点是否突出
亮点突出度10%是否有让人眼前一亮的经历

评估节点同样用结构化输出,返回{ score, feedback: [{ dimension, issue, suggestion }] }。如果总分低于阈值(我设的是 75 分),就带着 feedback 回到采集节点,让 Agent 针对性地补充信息。

这里有个经验:评估标准要写进 prompt 里,而且要写得足够细。我一开始只写"请评估简历质量",模型给的分永远在 80 分以上,毫无区分度。后来我把上面这张表的维度、权重、评估要点全部塞进 prompt,评分才变得有参考价值。

4.4 防止 Agent 陷入死循环的三道保险

Agent 开发最怕的就是无限循环——评估不通过、补充信息、再评估、还是不通过……烧 token 不说,用户体验也极差。我加了三道保险:

第一道是retryCount,每次从评估回到采集就 +1,超过 3 次强制流转到finalize。第二道是评估分数趋势检测,如果连续两次评估分数没有提升,说明补充的信息没起作用,直接结束。第三道是超时控制,在 Route Handler 层面给整个 Agent 执行加一个 60 秒的超时,超时就返回当前已有结果。

function routeAfterEvaluate(state: typeof ResumeState.State) { const { evaluation, retryCount } = state; if (evaluation.score >= 75) return "finalize"; if (retryCount >= 3) return "finalize"; return "collect"; }

这三道保险看起来简单,但能避免 90% 的线上事故。我见过太多 Agent 项目因为没做熔断,一个请求跑了几分钟还在循环,最后把 API 额度烧光。

5. 实测中踩过的坑与性能优化

5.1 流式输出与结构化输出的冲突

这是我在这个项目里踩的最大的坑。前面说了,前端要流式输出,但结构化输出(withStructuredOutput)是一次性返回完整对象的,没法流式。这两个需求天然矛盾。

我的解决方案是分节点处理:collectNode和evaluateNode用结构化输出(因为它们的产出是内部数据,用户不需要实时看到),generateNode用普通流式输出(因为生成简历内容是用户最想实时看到的)。这样既保证了数据结构的可靠性,又保证了核心体验的流畅性。

// generateNode 用流式 const stream = await model.stream(prompt); let fullContent = ""; for await (const chunk of stream) { fullContent += chunk.content; // 通过 config.writer 把 chunk 推给外层流 config.writer?.(chunk.content); }

LangGraph.js 的节点函数可以接收config参数,通过config.writer把中间结果推出去,外层streamEvents就能捕获到。这个机制是打通"节点内部流式"和"整体流式"的关键。

5.2 Token 消耗与上下文管理

简历 Agent 是多轮对话,对话历史会越来越长,token 消耗是个大问题。我做了两件事来控制成本。

第一是对话历史裁剪。只保留最近 10 轮对话,更早的对话用一条摘要代替。摘要由模型生成,压缩成 100 字以内。这样既保留了上下文,又控制了长度。

第二是状态与对话分离。resumeData是结构化的,它本身就承载了核心信息,不需要依赖完整对话历史。所以即使裁剪了对话,Agent 依然知道用户填了哪些信息。这个设计让上下文管理变得简单很多。

function trimMessages(messages: BaseMessage[], maxRounds = 10) { if (messages.length <= maxRounds * 2) return messages; const recent = messages.slice(-maxRounds * 2); const summary = `[早期对话摘要] 用户已提供基本信息,正在完善项目经历。`; return [new SystemMessage(summary), ...recent]; }

5.3 并发场景下的状态隔离

关键词里有个"ai agent 怎么扛并发",这确实是生产环境必须考虑的问题。LangGraph 的 Checkpointer 是按thread_id隔离的,只要每个用户会话有独立的thread_id,状态就不会串。但有几个细节要注意。

第一,thread_id的生成要保证唯一性,我用的是crypto.randomUUID(),前端首次进入时生成并存到 localStorage。第二,如果用MemorySaver,高并发下内存会暴涨,必须换持久化存储。第三,模型调用本身是 IO 密集型的,Node.js 的单线程模型反而适合这种场景,但要注意给模型调用加超时和重试,避免某个慢请求拖垮整个服务。

const model = new ChatOpenAI({ modelName: "gpt-4o-mini", timeout: 30000, maxRetries: 2, temperature: 0.7, });

gpt-4o-mini是我实测下来性价比最高的选择,简历这种任务不需要顶级模型,mini 版本完全够用,成本只有十分之一。temperature设 0.7 是因为简历生成需要一点创造性,太低会显得死板。

5.4 部署时的运行时选择

Next.js 项目部署时,Route Handler 的运行时选择很关键。我前面强调过必须用nodejs运行时,但还有一个坑:部分 Serverless 平台对响应时长有限制,比如某些平台默认 10 秒超时,而 Agent 跑一轮可能要 20-30 秒。

解决方案有两个:一是选支持长时运行的平台,或者把超时调到 60 秒以上;二是把 Agent 执行改成异步任务模式——请求立即返回一个 task_id,前端轮询或者用 WebSocket 拿结果。我目前用的是第一种,因为简历场景对实时性要求没那么高,用户能接受等 30 秒,只要能看到流式输出就不觉得慢。

提示:如果你的部署平台不支持长连接,SSE 可能会被网关切断。这时候可以考虑用轮询方案,或者把流式输出改成"分段返回"。

6. 这套架构还能怎么扩展

把简历 Agent 跑通之后,我发现这套Next.js + LangGraph.js的架构其实是个通用模板,稍微改改就能用到很多场景。

比如面试模拟 Agent:把评估节点换成"面试官提问"节点,采集节点换成"回答评估"节点,就能做一个模拟面试工具。再比如岗位匹配 Agent:把简历数据和岗位 JD 都作为输入,让 Agent 做匹配度分析和差距建议。核心的图结构、流式接口、状态管理几乎不用改,只需要替换节点内部的 prompt 和逻辑。

从工程角度看,还有几个可以深化的方向。一是引入 RAG,把优质简历库、岗位 JD 库做成向量检索,让 Agent 生成内容时有参考。二是多 Agent 协作,比如一个 Agent 负责内容生成,一个负责事实核查(防止编造经历),一个负责风格统一。LangGraph 天然支持多 Agent 编排,这是它比简单 Chain 强大的地方。三是加入人工审核节点,用 LangGraph 的interrupt机制,在关键节点暂停等用户确认,确认后再继续。

我自己在实际操作中的体会是:Agent 项目的难点从来不在"调通模型",而在流程设计和边界处理。模型能力是现成的,但怎么把它的输出变成可靠的产品功能,怎么处理各种异常和边界情况,才是真正拉开差距的地方。简历 Agent 这个项目麻雀虽小,但把多轮对话、结构化输出、流式响应、状态持久化、熔断控制这些 Agent 开发的核心问题都覆盖到了,非常适合作为从"会调 API"到"能做产品"的进阶练手项目。

最后分享一个小技巧:调试 LangGraph 的时候,把streamEvents的所有事件都打印出来,你会看到每个节点的进入、退出、模型调用的开始和结束。这个日志比任何调试工具都直观,能帮你快速定位是哪个节点出了问题。我一开始嫌日志吵,后来发现没有它根本没法调试,强烈建议在开发阶段打开。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 20:11:53

Tauri+Python Sidecar:轻量桌面应用与跨语言进程通信实战

可能很多刚开始做桌面工具的人都有过这种纠结&#xff1a;Electron 打包出来动辄一百多兆&#xff0c;内存随便跑三百兆&#xff0c;用户下载你的"小工具"还要等半天。换纯 Rust 写&#xff0c;又舍不得 Python 生态里现成的算法库、爬虫库和数据处理能力。我最后落地…

作者头像 李华
网站建设 2026/10/8 20:08:57

Android Studio 复刻微信主界面:BottomNavigationView 与 RecyclerView 实战

简介&#xff1a;这是一份面向Android初学者与界面开发爱好者的实战项目源码&#xff0c;围绕「用Android Studio制作微信界面」展开&#xff0c;帮助读者在真实工程中理解移动端UI搭建流程。资源包共1041个文件&#xff0c;约24.25MB&#xff0c;涵盖426个flat资源、237个json…

作者头像 李华
网站建设 2026/10/8 20:08:14

安卓免费排班工具实测:循环排班+提醒,搞定轮班倒班记录

排班这事儿&#xff0c;以前我都是靠手写和脑子硬记。赶上夜班第二天又要调班&#xff0c;或者在医院、工厂、便利店上班的朋友都懂——排班表一变&#xff0c;生活节奏全得跟着变。今天要聊的这款《极简排班》&#xff0c;就是安卓手机端一个完全免费的排班工具&#xff0c;核…

作者头像 李华
网站建设 2026/10/8 20:07:35

OpenTelemetry GenAI 语义约定实战:LLM 应用调用链追踪与 Token 成本治理

1. 为什么 AI 应用的可观测性突然成了刚需过去两年我一直在做 LLM 应用落地&#xff0c;从最早的"套壳对话"到现在的多智能体编排、RAG 检索增强、工具调用链&#xff0c;踩过的坑比写过的代码还多。最让我头疼的不是模型效果不好&#xff0c;而是出了问题根本不知道…

作者头像 李华
网站建设 2026/10/8 20:07:19

操作系统期末复习:搭知识骨架与三遍刷题法

简介&#xff1a;这是一份面向计算机专业学生与期末备考者的操作系统复习资料&#xff0c;内容涵盖操作系统基本概念、类型、主要特征、功能模块、发展历程及UNIX系统等考点&#xff0c;并配有答案便于自测。资源包仅含1个doc文档&#xff0c;大小439KB&#xff0c;文档结构清晰…

作者头像 李华
网站建设 2026/10/8 20:07:16

Superpowers:给AI编程助手装一套可复用的技能包,让工作流真正起飞

过去三个月&#xff0c;我把绝大多数写代码的时间都交给了 AI 编程助手&#xff0c;但真正让我效率起飞的不是某个更聪明的模型&#xff0c;而是一个叫 Superpowers 的开源项目。它不是新的 IDE&#xff0c;也不是某家公司的产品&#xff0c;而是一套给 Claude Code 这类 AI 编…

作者头像 李华