[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fLneuPIb0qpuQ_oKbc_CGaVuio7vLeU1N9Ria3NcjOQA":3,"$fJU-4tot_gC5fDkujNeoE-cGsdMy5V_KcdUXLuAnTFgw":15,"$fauY3OmnitA236jd4b6KsS-lYOsXyFw16cZNYsVPjeUA":423},{"slug":4,"title":5,"description":6,"content":7,"content_html":8,"pub_date":9,"tags":10,"draft":14},"ai-agent-what-is","什么是 AI Agent？从 LLM 到自主执行","LLM 本身是无状态问答机，Agent 是什么让它’动’起来的？本文深入解析 Agent 的四个核心能力、ReAct 框架、工具调用原理，以及主流框架横向对比。","import Mermaid from '..\u002F..\u002Fcomponents\u002FMermaid.astro'\nimport Chart from '..\u002F..\u002Fcomponents\u002FChart.vue'\n\nexport const paradigmRadarData = {\n  labels: ['适应性', '可靠性', '工具能力', '控制灵活性'],\n  datasets: [\n    {\n      label: 'Chatbot',\n      data: [1, 5, 2, 1],\n      backgroundColor: 'rgba(0,212,255,0.2)',\n      borderColor: 'rgba(0,212,255,0.9)',\n      borderWidth: 2,\n      pointBackgroundColor: 'rgba(0,212,255,0.9)',\n    },\n    {\n      label: 'Workflow',\n      data: [2, 5, 3, 2],\n      backgroundColor: 'rgba(57,255,20,0.2)',\n      borderColor: 'rgba(57,255,20,0.9)',\n      borderWidth: 2,\n      pointBackgroundColor: 'rgba(57,255,20,0.9)',\n    },\n    {\n      label: 'Agent',\n      data: [5, 2, 5, 5],\n      backgroundColor: 'rgba(255,0,170,0.2)',\n      borderColor: 'rgba(255,0,170,0.9)',\n      borderWidth: 2,\n      pointBackgroundColor: 'rgba(255,0,170,0.9)',\n    },\n  ],\n}\n\nexport const paradigmRadarOptions = {\n  scales: {\n    r: {\n      min: 0,\n      max: 5,\n      ticks: { display: false, stepSize: 1 },\n      grid: { color: 'rgba(136,136,170,0.25)' },\n      angleLines: { color: 'rgba(136,136,170,0.25)' },\n      pointLabels: { color: '#c8c8d8', font: { family: 'JetBrains Mono', size: 11 } },\n    },\n  },\n}\n\nexport const frameworkBarData = {\n  labels: ['LangChain', 'LlamaIndex', 'AutoGen', 'OpenClaw', 'Dify'],\n  datasets: [\n    {\n      label: '上手难度',\n      data: [3, 3, 2, 4, 5],\n      backgroundColor: 'rgba(0,212,255,0.2)',\n      borderColor: 'rgba(0,212,255,0.9)',\n      borderWidth: 2,\n    },\n    {\n      label: '工具生态',\n      data: [5, 4, 3, 3, 4],\n      backgroundColor: 'rgba(57,255,20,0.2)',\n      borderColor: 'rgba(57,255,20,0.9)',\n      borderWidth: 2,\n    },\n    {\n      label: '社区活跃度',\n      data: [5, 4, 4, 3, 3],\n      backgroundColor: 'rgba(255,0,170,0.2)',\n      borderColor: 'rgba(255,0,170,0.9)',\n      borderWidth: 2,\n    },\n  ],\n}\n\nexport const frameworkBarOptions = {\n  indexAxis: 'y',\n  scales: {\n    x: {\n      ticks: { color: '#8888aa', font: { family: 'JetBrains Mono', size: 10 } },\n      grid: { color: 'rgba(30,30,48,0.8)' },\n      border: { display: false },\n    },\n    y: {\n      ticks: { color: '#c8c8d8', font: { family: 'JetBrains Mono', size: 10 } },\n      grid: { display: false },\n      border: { display: false },\n    },\n  },\n}\n\n第一次接触 AI 的人，大概都会感叹：这玩意儿真聪明。但用久了你会发现一个根本限制——它只会**说**，不会**做**。\n\n你问它\"帮我发封邮件\"，它会给你写好草稿，然后说\"你可以把这段文字复制到邮件客户端发送\"。\n\n这就是 LLM 和 Agent 的核心区别。\n\n---\n\n## LLM 是什么：一台无状态的预测机器\n\n大语言模型的本质是一个条件概率函数：给定一段文本，预测下一个 token 最可能是什么。它没有记忆（每次对话都是从零开始），没有持久状态，更没有办法主动触发任何副作用。\n\n```\n输入 tokens → Transformer 前向传播 → 输出 tokens\n```\n\n这个过程是纯函数式的——相同输入（温度为 0 时）得到相同输出，不会对外部世界产生任何影响。\n\n那么，Agent 是什么让 LLM \"动\"起来的？\n\n---\n\n## Agent 的四个核心能力\n\n一个完整的 AI Agent 围绕 LLM 构建了四层能力：\n\n### 1. 感知（Perception）\n\nAgent 能接收多种形式的输入：文字、图片、文件内容、网页、API 返回值、代码执行结果……\n\n这不是 LLM 原生支持的——需要一层**输入处理管道**，把外部世界的信号转换成 token 序列送给模型。\n\n### 2. 记忆（Memory）\n\nLLM 的上下文窗口是它唯一的\"工作记忆\"。一旦超出窗口大小，早期信息就被截断了。\n\nAgent 通过外部存储（向量数据库、文件、KV store）实现长期记忆，并在需要时检索相关内容注入上下文。\n\n### 3. 规划（Planning）\n\n面对一个复杂任务，LLM 需要把它分解成可执行的步骤。这包括：\n\n- **任务分解**：把\"帮我整理这份报告\"拆成若干子任务\n- **自我反思**：执行结果不符合预期时，重新规划\n- **依赖管理**：哪些步骤可以并行，哪些必须串行\n\n### 4. 行动（Action \u002F Tool Use）\n\n这是最关键的一环。Agent 通过**工具调用**与外部世界交互：\n\n- 读写文件\n- 执行代码\n- 调用 API\n- 浏览网页\n- 发送消息\n\n工具调用把 LLM 从\"只会说\"变成了\"能做\"。\n\n---\n\n## ReAct：驱动 Agent 运转的核心框架\n\nReAct（Reasoning + Acting）是目前最主流的 Agent 执行框架，2022 年由 Google 提出。\n\n其核心思路是让 LLM 在**推理**和**行动**之间交替循环：\n\n```\nThought: 我需要知道今天的天气，让我调用天气 API\nAction: get_weather(city=\"上海\")\nObservation: {\"temp\": 22, \"condition\": \"晴\"}\nThought: 天气不错，现在我可以回答用户了\nAnswer: 上海今天晴天，22°C，适合出行\n```\n\n每一轮：\n1. **Thought**：模型输出推理过程（Chain-of-Thought）\n2. **Action**：模型决定调用哪个工具，参数是什么\n3. **Observation**：工具执行结果反馈给模型\n4. 循环直到任务完成或达到最大步数\n\n这个循环的关键洞察是：**让模型先想清楚再行动，行动结果再反哺思考**。\n\n\u003CMermaid code={`\nflowchart TD\n    U([用户输入]) --> T[Thought\\n推理意图]\n    T --> D{需要工具?}\n    D -- 是 --> A[Action\\n调用工具]\n    A --> O[Observation\\n获得结果]\n    O --> T\n    D -- 否 --> R([输出答案])\n    style U fill:#1e1e30,stroke:#00ff88,color:#e8e8f0\n    style R fill:#1e1e30,stroke:#00ff88,color:#e8e8f0\n    style T fill:#13131f,stroke:#00d4ff,color:#e8e8f0\n    style A fill:#13131f,stroke:#b44cff,color:#e8e8f0\n    style O fill:#13131f,stroke:#b44cff,color:#e8e8f0\n    style D fill:#0f0f1a,stroke:#00d4ff,color:#e8e8f0\n`} \u002F>\n\n---\n\n## Tool Use 原理：Function Calling\n\n工具调用在技术上是怎么实现的？以 OpenAI 的 Function Calling 为例：\n\n```json\n\u002F\u002F 工具描述（JSON Schema）\n{\n  \"name\": \"read_file\",\n  \"description\": \"读取本地文件内容\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"path\": {\n        \"type\": \"string\",\n        \"description\": \"文件路径，绝对路径或相对路径\"\n      }\n    },\n    \"required\": [\"path\"]\n  }\n}\n```\n\n你把工具描述（一组 JSON Schema）和用户消息一起发给模型，模型如果判断需要用工具，会返回一个结构化的调用指令：\n\n```json\n{\n  \"tool_calls\": [{\n    \"function\": {\n      \"name\": \"read_file\",\n      \"arguments\": \"{\\\"path\\\": \\\"\u002Ftmp\u002Freport.txt\\\"}\"\n    }\n  }]\n}\n```\n\n你的代码负责实际执行这个调用，把结果作为 `tool` 角色消息返回给模型，模型继续推理。\n\n**模型本身并不执行任何代码**——它只是输出结构化的\"意图\"，宿主程序负责执行。\n\n---\n\n## Agent vs Chatbot vs Workflow\n\n这三个词经常被混用，但有本质区别：\n\n| 维度 | Chatbot | Workflow | Agent |\n|------|---------|----------|-------|\n| 控制流 | 单轮问答 | 预定义流程 | 动态规划 |\n| 工具调用 | 无或有限 | 固定步骤 | 自主决策 |\n| 适应性 | 低 | 低 | 高 |\n| 可靠性 | 高 | 高 | 较低 |\n| 适用场景 | 问答\u002F创作 | ETL\u002F自动化 | 复杂开放任务 |\n\nWorkflow 适合**已知流程**的自动化——你知道第一步做什么、第二步做什么。  \nAgent 适合**未知路径**的任务——你只知道目标，具体怎么达到由模型决定。\n\n\u003CChart client:only=\"vue\" type=\"radar\" data={paradigmRadarData} options={paradigmRadarOptions} height={260} \u002F>\n\n---\n\n## 一个完整执行例子：文件操作 Agent\n\n任务：「找出 `\u002Ftmp\u002Flogs\u002F` 下所有包含 ERROR 的日志文件，统计每个文件的错误数量，写成报告」\n\n```\n用户: 找出 \u002Ftmp\u002Flogs\u002F 下所有包含 ERROR 的日志文件，统计每个文件的错误数量，写成报告\n\n[Thought] 我需要先列出 \u002Ftmp\u002Flogs\u002F 目录下的所有文件\n[Action] list_directory(path=\"\u002Ftmp\u002Flogs\u002F\")\n[Observation] [\"app.log\", \"access.log\", \"error.log\", \"worker.log\"]\n\n[Thought] 现在逐个检查哪些文件包含 ERROR\n[Action] search_in_file(path=\"\u002Ftmp\u002Flogs\u002Fapp.log\", pattern=\"ERROR\")\n[Observation] 找到 23 处匹配\n\n[Action] search_in_file(path=\"\u002Ftmp\u002Flogs\u002Faccess.log\", pattern=\"ERROR\")\n[Observation] 找到 0 处匹配\n\n[Action] search_in_file(path=\"\u002Ftmp\u002Flogs\u002Ferror.log\", pattern=\"ERROR\")\n[Observation] 找到 157 处匹配\n\n[Action] search_in_file(path=\"\u002Ftmp\u002Flogs\u002Fworker.log\", pattern=\"ERROR\")\n[Observation] 找到 8 处匹配\n\n[Thought] access.log 没有 ERROR，其他三个有。现在生成报告。\n[Action] write_file(path=\"\u002Ftmp\u002Ferror_report.md\", content=\"# 错误统计报告\\n...\")\n[Observation] 文件写入成功\n\n[Answer] 报告已生成至 \u002Ftmp\u002Ferror_report.md，共 3 个文件包含错误：\n- error.log: 157 处\n- app.log: 23 处  \n- worker.log: 8 处\n```\n\n整个过程中，**模型决定了执行路径**，而不是程序员预先写好的固定流程。\n\n---\n\n## 主流框架横向对比\n\n| 框架 | 语言 | 定位 | 工具生态 | 上手难度 |\n|------|------|------|----------|----------|\n| **LangChain** | Python\u002FJS | 全栈 Agent 框架 | 极丰富（600+ 集成） | 中，文档庞杂 |\n| **LlamaIndex** | Python | 以 RAG\u002F数据为核心 | 丰富（侧重数据连接） | 中 |\n| **AutoGen** | Python | 多 Agent 对话框架 | 中等 | 较高，概念多 |\n| **OpenClaw** | Node.js | 本地 Agent 运行时 | 中（插件\u002F技能体系） | 低，配置驱动 |\n| **Dify** | Python | 可视化低代码平台 | 丰富（含工作流） | 低，GUI 操作 |\n\n**选型建议**：\n- 快速原型 \u002F 非技术团队 → **Dify**\n- Python 重度用户，RAG 场景 → **LlamaIndex**\n- 复杂多 Agent 协作 → **AutoGen**\n- 本地私有化、系统集成 → **OpenClaw**\n- 最广泛生态 → **LangChain**（但注意 API 频繁变动）\n\n\u003CChart client:only=\"vue\" type=\"bar\" data={frameworkBarData} options={frameworkBarOptions} height={280} \u002F>\n\n> **注**：上图为作者主观评分（1=最低，5=最高），仅供参考。上手难度、工具生态、社区活跃度随版本迭代持续变化，以各框架官方文档为准。\n\n---\n\n## 总结\n\nLLM 是 Agent 的大脑，但光有大脑还不够。Agent 是在 LLM 外面包了一层**执行环境**：\n\n```\n外部世界 ←→ [工具层] ←→ [记忆层] ←→ [规划层] ←→ LLM\n```\n\nReAct 循环驱动这个系统持续运转，直到任务完成。\n\n理解 Agent 的关键认知转变是：**从「问答」到「委托」**。你不再是在和一个聊天机器人对话，而是在给一个能动的执行者下达目标。","\u003Cp>import Mermaid from ‘…\u002F…\u002Fcomponents\u002FMermaid.astro’\nimport Chart from ‘…\u002F…\u002Fcomponents\u002FChart.vue’\u003C\u002Fp>\n\u003Cp>export const paradigmRadarData = {\nlabels: [‘适应性’, ‘可靠性’, ‘工具能力’, ‘控制灵活性’],\ndatasets: [\n{\nlabel: ‘Chatbot’,\ndata: [1, 5, 2, 1],\nbackgroundColor: ‘rgba(0,212,255,0.2)’,\nborderColor: ‘rgba(0,212,255,0.9)’,\nborderWidth: 2,\npointBackgroundColor: ‘rgba(0,212,255,0.9)’,\n},\n{\nlabel: ‘Workflow’,\ndata: [2, 5, 3, 2],\nbackgroundColor: ‘rgba(57,255,20,0.2)’,\nborderColor: ‘rgba(57,255,20,0.9)’,\nborderWidth: 2,\npointBackgroundColor: ‘rgba(57,255,20,0.9)’,\n},\n{\nlabel: ‘Agent’,\ndata: [5, 2, 5, 5],\nbackgroundColor: ‘rgba(255,0,170,0.2)’,\nborderColor: ‘rgba(255,0,170,0.9)’,\nborderWidth: 2,\npointBackgroundColor: ‘rgba(255,0,170,0.9)’,\n},\n],\n}\u003C\u002Fp>\n\u003Cp>export const paradigmRadarOptions = {\nscales: {\nr: {\nmin: 0,\nmax: 5,\nticks: { display: false, stepSize: 1 },\ngrid: { color: ‘rgba(136,136,170,0.25)’ },\nangleLines: { color: ‘rgba(136,136,170,0.25)’ },\npointLabels: { color: ‘#c8c8d8’, font: { family: ‘JetBrains Mono’, size: 11 } },\n},\n},\n}\u003C\u002Fp>\n\u003Cp>export const frameworkBarData = {\nlabels: [‘LangChain’, ‘LlamaIndex’, ‘AutoGen’, ‘OpenClaw’, ‘Dify’],\ndatasets: [\n{\nlabel: ‘上手难度’,\ndata: [3, 3, 2, 4, 5],\nbackgroundColor: ‘rgba(0,212,255,0.2)’,\nborderColor: ‘rgba(0,212,255,0.9)’,\nborderWidth: 2,\n},\n{\nlabel: ‘工具生态’,\ndata: [5, 4, 3, 3, 4],\nbackgroundColor: ‘rgba(57,255,20,0.2)’,\nborderColor: ‘rgba(57,255,20,0.9)’,\nborderWidth: 2,\n},\n{\nlabel: ‘社区活跃度’,\ndata: [5, 4, 4, 3, 3],\nbackgroundColor: ‘rgba(255,0,170,0.2)’,\nborderColor: ‘rgba(255,0,170,0.9)’,\nborderWidth: 2,\n},\n],\n}\u003C\u002Fp>\n\u003Cp>export const frameworkBarOptions = {\nindexAxis: ‘y’,\nscales: {\nx: {\nticks: { color: ‘#8888aa’, font: { family: ‘JetBrains Mono’, size: 10 } },\ngrid: { color: ‘rgba(30,30,48,0.8)’ },\nborder: { display: false },\n},\ny: {\nticks: { color: ‘#c8c8d8’, font: { family: ‘JetBrains Mono’, size: 10 } },\ngrid: { display: false },\nborder: { display: false },\n},\n},\n}\u003C\u002Fp>\n\u003Cp>第一次接触 AI 的人，大概都会感叹：这玩意儿真聪明。但用久了你会发现一个根本限制——它只会\u003Cstrong>说\u003C\u002Fstrong>，不会\u003Cstrong>做\u003C\u002Fstrong>。\u003C\u002Fp>\n\u003Cp>你问它&quot;帮我发封邮件&quot;，它会给你写好草稿，然后说&quot;你可以把这段文字复制到邮件客户端发送&quot;。\u003C\u002Fp>\n\u003Cp>这就是 LLM 和 Agent 的核心区别。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"llm-是什么-一台无状态的预测机器\">LLM 是什么：一台无状态的预测机器\u003C\u002Fh2>\n\u003Cp>大语言模型的本质是一个条件概率函数：给定一段文本，预测下一个 token 最可能是什么。它没有记忆（每次对话都是从零开始），没有持久状态，更没有办法主动触发任何副作用。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>输入 tokens → Transformer 前向传播 → 输出 tokens\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这个过程是纯函数式的——相同输入（温度为 0 时）得到相同输出，不会对外部世界产生任何影响。\u003C\u002Fp>\n\u003Cp>那么，Agent 是什么让 LLM &quot;动&quot;起来的？\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"agent-的四个核心能力\">Agent 的四个核心能力\u003C\u002Fh2>\n\u003Cp>一个完整的 AI Agent 围绕 LLM 构建了四层能力：\u003C\u002Fp>\n\u003Ch3 id=\"1-感知-perception\">1. 感知（Perception）\u003C\u002Fh3>\n\u003Cp>Agent 能接收多种形式的输入：文字、图片、文件内容、网页、API 返回值、代码执行结果……\u003C\u002Fp>\n\u003Cp>这不是 LLM 原生支持的——需要一层\u003Cstrong>输入处理管道\u003C\u002Fstrong>，把外部世界的信号转换成 token 序列送给模型。\u003C\u002Fp>\n\u003Ch3 id=\"2-记忆-memory\">2. 记忆（Memory）\u003C\u002Fh3>\n\u003Cp>LLM 的上下文窗口是它唯一的&quot;工作记忆&quot;。一旦超出窗口大小，早期信息就被截断了。\u003C\u002Fp>\n\u003Cp>Agent 通过外部存储（向量数据库、文件、KV store）实现长期记忆，并在需要时检索相关内容注入上下文。\u003C\u002Fp>\n\u003Ch3 id=\"3-规划-planning\">3. 规划（Planning）\u003C\u002Fh3>\n\u003Cp>面对一个复杂任务，LLM 需要把它分解成可执行的步骤。这包括：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>任务分解\u003C\u002Fstrong>：把&quot;帮我整理这份报告&quot;拆成若干子任务\u003C\u002Fli>\n\u003Cli>\u003Cstrong>自我反思\u003C\u002Fstrong>：执行结果不符合预期时，重新规划\u003C\u002Fli>\n\u003Cli>\u003Cstrong>依赖管理\u003C\u002Fstrong>：哪些步骤可以并行，哪些必须串行\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"4-行动-action-tool-use\">4. 行动（Action \u002F Tool Use）\u003C\u002Fh3>\n\u003Cp>这是最关键的一环。Agent 通过\u003Cstrong>工具调用\u003C\u002Fstrong>与外部世界交互：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>读写文件\u003C\u002Fli>\n\u003Cli>执行代码\u003C\u002Fli>\n\u003Cli>调用 API\u003C\u002Fli>\n\u003Cli>浏览网页\u003C\u002Fli>\n\u003Cli>发送消息\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>工具调用把 LLM 从&quot;只会说&quot;变成了&quot;能做&quot;。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"react-驱动-agent-运转的核心框架\">ReAct：驱动 Agent 运转的核心框架\u003C\u002Fh2>\n\u003Cp>ReAct（Reasoning + Acting）是目前最主流的 Agent 执行框架，2022 年由 Google 提出。\u003C\u002Fp>\n\u003Cp>其核心思路是让 LLM 在\u003Cstrong>推理\u003C\u002Fstrong>和\u003Cstrong>行动\u003C\u002Fstrong>之间交替循环：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Thought: 我需要知道今天的天气，让我调用天气 API\nAction: get_weather(city=&quot;上海&quot;)\nObservation: {&quot;temp&quot;: 22, &quot;condition&quot;: &quot;晴&quot;}\nThought: 天气不错，现在我可以回答用户了\nAnswer: 上海今天晴天，22°C，适合出行\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>每一轮：\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Thought\u003C\u002Fstrong>：模型输出推理过程（Chain-of-Thought）\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Action\u003C\u002Fstrong>：模型决定调用哪个工具，参数是什么\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Observation\u003C\u002Fstrong>：工具执行结果反馈给模型\u003C\u002Fli>\n\u003Cli>循环直到任务完成或达到最大步数\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>这个循环的关键洞察是：\u003Cstrong>让模型先想清楚再行动，行动结果再反哺思考\u003C\u002Fstrong>。\u003C\u002Fp>\n\u003Cp>&lt;Mermaid code={\u003Ccode>flowchart TD     U([用户输入]) --&gt; T[Thought\\n推理意图]     T --&gt; D{需要工具?}     D -- 是 --&gt; A[Action\\n调用工具]     A --&gt; O[Observation\\n获得结果]     O --&gt; T     D -- 否 --&gt; R([输出答案])     style U fill:#1e1e30,stroke:#00ff88,color:#e8e8f0     style R fill:#1e1e30,stroke:#00ff88,color:#e8e8f0     style T fill:#13131f,stroke:#00d4ff,color:#e8e8f0     style A fill:#13131f,stroke:#b44cff,color:#e8e8f0     style O fill:#13131f,stroke:#b44cff,color:#e8e8f0     style D fill:#0f0f1a,stroke:#00d4ff,color:#e8e8f0\u003C\u002Fcode>} \u002F&gt;\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"tool-use-原理-function-calling\">Tool Use 原理：Function Calling\u003C\u002Fh2>\n\u003Cp>工具调用在技术上是怎么实现的？以 OpenAI 的 Function Calling 为例：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">\u002F\u002F 工具描述（JSON Schema）\n{\n  &quot;name&quot;: &quot;read_file&quot;,\n  &quot;description&quot;: &quot;读取本地文件内容&quot;,\n  &quot;parameters&quot;: {\n    &quot;type&quot;: &quot;object&quot;,\n    &quot;properties&quot;: {\n      &quot;path&quot;: {\n        &quot;type&quot;: &quot;string&quot;,\n        &quot;description&quot;: &quot;文件路径，绝对路径或相对路径&quot;\n      }\n    },\n    &quot;required&quot;: [&quot;path&quot;]\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>你把工具描述（一组 JSON Schema）和用户消息一起发给模型，模型如果判断需要用工具，会返回一个结构化的调用指令：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;tool_calls&quot;: [{\n    &quot;function&quot;: {\n      &quot;name&quot;: &quot;read_file&quot;,\n      &quot;arguments&quot;: &quot;{\\&quot;path\\&quot;: \\&quot;\u002Ftmp\u002Freport.txt\\&quot;}&quot;\n    }\n  }]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>你的代码负责实际执行这个调用，把结果作为 \u003Ccode>tool\u003C\u002Fcode> 角色消息返回给模型，模型继续推理。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>模型本身并不执行任何代码\u003C\u002Fstrong>——它只是输出结构化的&quot;意图&quot;，宿主程序负责执行。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"agent-vs-chatbot-vs-workflow\">Agent vs Chatbot vs Workflow\u003C\u002Fh2>\n\u003Cp>这三个词经常被混用，但有本质区别：\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>维度\u003C\u002Fth>\n\u003Cth>Chatbot\u003C\u002Fth>\n\u003Cth>Workflow\u003C\u002Fth>\n\u003Cth>Agent\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>控制流\u003C\u002Ftd>\n\u003Ctd>单轮问答\u003C\u002Ftd>\n\u003Ctd>预定义流程\u003C\u002Ftd>\n\u003Ctd>动态规划\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>工具调用\u003C\u002Ftd>\n\u003Ctd>无或有限\u003C\u002Ftd>\n\u003Ctd>固定步骤\u003C\u002Ftd>\n\u003Ctd>自主决策\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>适应性\u003C\u002Ftd>\n\u003Ctd>低\u003C\u002Ftd>\n\u003Ctd>低\u003C\u002Ftd>\n\u003Ctd>高\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>可靠性\u003C\u002Ftd>\n\u003Ctd>高\u003C\u002Ftd>\n\u003Ctd>高\u003C\u002Ftd>\n\u003Ctd>较低\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>适用场景\u003C\u002Ftd>\n\u003Ctd>问答\u002F创作\u003C\u002Ftd>\n\u003Ctd>ETL\u002F自动化\u003C\u002Ftd>\n\u003Ctd>复杂开放任务\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>Workflow 适合\u003Cstrong>已知流程\u003C\u002Fstrong>的自动化——你知道第一步做什么、第二步做什么。\u003Cbr>\nAgent 适合\u003Cstrong>未知路径\u003C\u002Fstrong>的任务——你只知道目标，具体怎么达到由模型决定。\u003C\u002Fp>\n\u003CChart client:only=\"vue\" type=\"radar\" data={paradigmRadarData} options={paradigmRadarOptions} height={260} \u002F>\n\u003Chr>\n\u003Ch2 id=\"一个完整执行例子-文件操作-agent\">一个完整执行例子：文件操作 Agent\u003C\u002Fh2>\n\u003Cp>任务：「找出 \u003Ccode>\u002Ftmp\u002Flogs\u002F\u003C\u002Fcode> 下所有包含 ERROR 的日志文件，统计每个文件的错误数量，写成报告」\u003C\u002Fp>\n\u003Cpre>\u003Ccode>用户: 找出 \u002Ftmp\u002Flogs\u002F 下所有包含 ERROR 的日志文件，统计每个文件的错误数量，写成报告\n\n[Thought] 我需要先列出 \u002Ftmp\u002Flogs\u002F 目录下的所有文件\n[Action] list_directory(path=&quot;\u002Ftmp\u002Flogs\u002F&quot;)\n[Observation] [&quot;app.log&quot;, &quot;access.log&quot;, &quot;error.log&quot;, &quot;worker.log&quot;]\n\n[Thought] 现在逐个检查哪些文件包含 ERROR\n[Action] search_in_file(path=&quot;\u002Ftmp\u002Flogs\u002Fapp.log&quot;, pattern=&quot;ERROR&quot;)\n[Observation] 找到 23 处匹配\n\n[Action] search_in_file(path=&quot;\u002Ftmp\u002Flogs\u002Faccess.log&quot;, pattern=&quot;ERROR&quot;)\n[Observation] 找到 0 处匹配\n\n[Action] search_in_file(path=&quot;\u002Ftmp\u002Flogs\u002Ferror.log&quot;, pattern=&quot;ERROR&quot;)\n[Observation] 找到 157 处匹配\n\n[Action] search_in_file(path=&quot;\u002Ftmp\u002Flogs\u002Fworker.log&quot;, pattern=&quot;ERROR&quot;)\n[Observation] 找到 8 处匹配\n\n[Thought] access.log 没有 ERROR，其他三个有。现在生成报告。\n[Action] write_file(path=&quot;\u002Ftmp\u002Ferror_report.md&quot;, content=&quot;# 错误统计报告\\n...&quot;)\n[Observation] 文件写入成功\n\n[Answer] 报告已生成至 \u002Ftmp\u002Ferror_report.md，共 3 个文件包含错误：\n- error.log: 157 处\n- app.log: 23 处  \n- worker.log: 8 处\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>整个过程中，\u003Cstrong>模型决定了执行路径\u003C\u002Fstrong>，而不是程序员预先写好的固定流程。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"主流框架横向对比\">主流框架横向对比\u003C\u002Fh2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>框架\u003C\u002Fth>\n\u003Cth>语言\u003C\u002Fth>\n\u003Cth>定位\u003C\u002Fth>\n\u003Cth>工具生态\u003C\u002Fth>\n\u003Cth>上手难度\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>LangChain\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>Python\u002FJS\u003C\u002Ftd>\n\u003Ctd>全栈 Agent 框架\u003C\u002Ftd>\n\u003Ctd>极丰富（600+ 集成）\u003C\u002Ftd>\n\u003Ctd>中，文档庞杂\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>LlamaIndex\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>Python\u003C\u002Ftd>\n\u003Ctd>以 RAG\u002F数据为核心\u003C\u002Ftd>\n\u003Ctd>丰富（侧重数据连接）\u003C\u002Ftd>\n\u003Ctd>中\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>AutoGen\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>Python\u003C\u002Ftd>\n\u003Ctd>多 Agent 对话框架\u003C\u002Ftd>\n\u003Ctd>中等\u003C\u002Ftd>\n\u003Ctd>较高，概念多\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>OpenClaw\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>Node.js\u003C\u002Ftd>\n\u003Ctd>本地 Agent 运行时\u003C\u002Ftd>\n\u003Ctd>中（插件\u002F技能体系）\u003C\u002Ftd>\n\u003Ctd>低，配置驱动\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>Dify\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>Python\u003C\u002Ftd>\n\u003Ctd>可视化低代码平台\u003C\u002Ftd>\n\u003Ctd>丰富（含工作流）\u003C\u002Ftd>\n\u003Ctd>低，GUI 操作\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>\u003Cstrong>选型建议\u003C\u002Fstrong>：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>快速原型 \u002F 非技术团队 → \u003Cstrong>Dify\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>Python 重度用户，RAG 场景 → \u003Cstrong>LlamaIndex\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>复杂多 Agent 协作 → \u003Cstrong>AutoGen\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>本地私有化、系统集成 → \u003Cstrong>OpenClaw\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>最广泛生态 → \u003Cstrong>LangChain\u003C\u002Fstrong>（但注意 API 频繁变动）\u003C\u002Fli>\n\u003C\u002Ful>\n\u003CChart client:only=\"vue\" type=\"bar\" data={frameworkBarData} options={frameworkBarOptions} height={280} \u002F>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>注\u003C\u002Fstrong>：上图为作者主观评分（1=最低，5=最高），仅供参考。上手难度、工具生态、社区活跃度随版本迭代持续变化，以各框架官方文档为准。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Chr>\n\u003Ch2 id=\"总结\">总结\u003C\u002Fh2>\n\u003Cp>LLM 是 Agent 的大脑，但光有大脑还不够。Agent 是在 LLM 外面包了一层\u003Cstrong>执行环境\u003C\u002Fstrong>：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>外部世界 ←→ [工具层] ←→ [记忆层] ←→ [规划层] ←→ LLM\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>ReAct 循环驱动这个系统持续运转，直到任务完成。\u003C\u002Fp>\n\u003Cp>理解 Agent 的关键认知转变是：\u003Cstrong>从「问答」到「委托」\u003C\u002Fstrong>。你不再是在和一个聊天机器人对话，而是在给一个能动的执行者下达目标。\u003C\u002Fp>\n","2026-04-30",[11,12,13],"ai","agent","llm",false,[16,28,39,51,59,66,73,80,87,94,104,113,123,132,140,148,157,166,175,185,192,202,208,211,217,226,233,240,248,258,267,276,286,296,306,314,324,335,345,354,362,368,376,384,392,400,408,415],{"slug":17,"title":18,"description":19,"pub_date":20,"tags":21,"draft":14,"word_count":27},"ide-skills-guide","Agent Skills 完全指南：21 款第三方 Skill 深度评测与使用心得","全面评测 21 款第三方 Agent Skills，涵盖 Vue 生态、前端设计、构建工具、实用工具四大分类。从安装配置到实际使用场景，带你了解每个 Skill 的功能特点、最佳实践与使用心得。","2026-06-15",[12,22,23,24,25,26],"skills","AI","效率工具","前端","Vue",4169,{"slug":29,"title":30,"description":31,"pub_date":32,"tags":33,"draft":14,"word_count":38},"linux-kernel-skeleton-struct-funcptr-container_of","Linux 内核骨架：struct、函数指针与 container_of","读懂 Linux 内核源码的三件套：巨大的 struct 组合代替继承、函数指针表实现虚派发、container_of 宏从嵌入成员找回完整对象。","2026-05-09",[34,35,36,37],"linux","kernel","C","container_of",1369,{"slug":40,"title":41,"description":42,"pub_date":43,"tags":44,"draft":14,"word_count":50},"astro-complete-guide-2025","Astro 5 深度剖析：Islands 架构原理、构建优化与 Cloudflare Workers 边缘部署","从编译器视角解析 Astro 5 的 Islands 架构实现原理，Content Layer API 的 Vite 插件机制，Server Islands 的流式渲染，以及如何在 Cloudflare Workers + D1 边缘环境下榨干性能。","2026-05-08",[45,46,47,48,49],"astro","frontend","cloudflare","performance","architecture",3663,{"slug":52,"title":53,"description":54,"pub_date":55,"tags":56,"draft":14,"word_count":58},"llm-prompt-engineering","Prompt Engineering 实战：让 LLM 真正听话的技巧","System prompt 怎么写、Few-shot 怎么设计、Chain-of-Thought 原理，以及常见失败模式和调试方法。","2026-05-03",[11,13,57],"工程实践",1723,{"slug":60,"title":61,"description":62,"pub_date":55,"tags":63,"draft":14,"word_count":65},"rag-system-design","RAG 系统设计：从 naive 到 production-ready","Retrieval-Augmented Generation 不只是「向量数据库 + LLM」，分块策略、召回质量、重排序、缓存才是工程核心。",[11,64,13,57],"rag",1613,{"slug":67,"title":68,"description":69,"pub_date":55,"tags":70,"draft":14,"word_count":72},"git-advanced-workflow","Git 进阶工作流：rebase、cherry-pick、bisect 的正确使用","merge 会了，但 rebase 总搞错？bisect 找 bug 提交？interactive rebase 整理历史？这篇一次说清楚。",[71,57],"git",1396,{"slug":74,"title":75,"description":76,"pub_date":55,"tags":77,"draft":14,"word_count":79},"docker-practical-guide","Docker 实战：从会用到用好","会 docker run 不够，Dockerfile 最佳实践、多阶段构建、Compose 编排、镜像瘦身才是日常真正需要的。",[78,34,57],"docker",1268,{"slug":81,"title":82,"description":83,"pub_date":55,"tags":84,"draft":14,"word_count":86},"anthropics-skills-guide","anthropics\u002Fskills：Anthropic 官方 Agent Skills 仓库解析","Anthropic 官方开源的 Agent Skills 标准仓库，127k stars，解析 SKILL.md 规范、17 个示例 skill 的设计模式，以及如何在 Claude Code \u002F Claude.ai \u002F API 中使用",[11,85,12,22],"Claude",2090,{"slug":88,"title":89,"description":90,"pub_date":55,"tags":91,"draft":14,"word_count":93},"karpathy-claude-code-guidelines","Karpathy 的 LLM 编码批评与 CLAUDE.md 最佳实践","基于 Andrej Karpathy 对 LLM 编程助手的观察，forrestchang 提炼出一个 CLAUDE.md 文件，4 条原则解决 AI 编码的典型失控问题：乱猜假设、过度设计、乱改代码、目标不清",[11,85,92,57],"Claude Code",2699,{"slug":95,"title":96,"description":97,"pub_date":55,"tags":98,"draft":14,"word_count":103},"typescript-advanced-patterns","TypeScript 高级模式：让类型系统为你工作","基础 TS 会了但类型总是 any？条件类型、映射类型、模板字面量类型、infer 关键字才是 TS 的真正威力。",[99,100,101,102],"typescript","类型系统","前端工程","高级模式",1419,{"slug":105,"title":106,"description":107,"pub_date":55,"tags":108,"draft":14,"word_count":112},"linux-performance-tuning","Linux 性能调优实战：从 top 到 perf 的完整工具链","遇到性能问题不知道从哪下手？这篇建立系统化的排查思路，从 CPU\u002F内存\u002FIO\u002F网络逐层分析。",[34,109,110,111],"性能","运维","系统编程",1524,{"slug":114,"title":115,"description":116,"pub_date":55,"tags":117,"draft":14,"word_count":122},"python-functional-programming","Python 函数式编程：map\u002Ffilter\u002Freduce 之外","Python 不是纯函数式语言，但 functools、itertools、偏函数、闭包这些工具用好了能让代码简洁一个量级。",[118,119,120,121],"python","函数式","闭包","装饰器",1867,{"slug":124,"title":125,"description":126,"pub_date":55,"tags":127,"draft":14,"word_count":131},"python-oop-guide","Python 面向对象：__init__ 之外你需要知道的","Python OOP 不只是 class + __init__，魔术方法、描述符、元类才是真正的武器。",[118,128,129,130],"OOP","面向对象","魔术方法",1792,{"slug":133,"title":134,"description":135,"pub_date":55,"tags":136,"draft":14,"word_count":139},"python-data-structures","Python 内置数据结构深度解析","list、dict、set、tuple 不只是数据容器，搞懂它们的底层实现和时间复杂度，才能写出高性能 Python。",[118,137,109,138],"数据结构","算法",1517,{"slug":141,"title":142,"description":143,"pub_date":55,"tags":144,"draft":14,"word_count":147},"python-basics-quick-start","Python 快速上手：写给有编程基础的人","已经会其他语言，想快速掌握 Python 的语法特性和思维方式，这篇是捷径。",[118,145,146],"入门","基础",1607,{"slug":149,"title":150,"description":151,"pub_date":55,"tags":152,"draft":14,"word_count":156},"python-dataclass-pydantic","Python dataclass vs Pydantic：数据类选型指南","dataclass 是标准库的轻量选择，Pydantic v2 是带验证的重武器，什么时候用哪个，这篇说清楚。",[118,153,154,155],"dataclass","pydantic","数据验证",1323,{"slug":158,"title":159,"description":160,"pub_date":55,"tags":161,"draft":14,"word_count":165},"python-asyncio-practical","Python asyncio 实战：从回调地狱到协程优雅","asyncio 是 Python 异步编程的核心，搞懂 event loop、Task、gather 这些概念才能写出真正高效的异步代码。",[118,162,163,164],"asyncio","并发","网络编程",1258,{"slug":167,"title":168,"description":169,"pub_date":55,"tags":170,"draft":14,"word_count":174},"python-type-hints-guide","Python 类型注解完全指南：从入门到实践","Python 3.5+ 引入类型注解，配合 mypy\u002Fpyright 让 Python 也能享受静态类型检查的好处。",[118,171,172,173],"typescript-style","type-hints","工具链",1102,{"slug":176,"title":177,"description":178,"pub_date":179,"tags":180,"draft":14,"word_count":184},"pwa-install-update-button","PWA 踩坑：为什么安装按钮从来不出现","从 beforeinstallprompt 到 Service Worker waiting，把 PWA 的安装与更新提示真正做对","2026-05-02",[181,182,183],"pwa","javascript","web",1683,{"slug":186,"title":187,"description":188,"pub_date":189,"tags":190,"draft":14,"word_count":191},"openclaw-vs-hermes-agent","OpenClaw vs Hermes Agent：两个本地优先 Agent 的设计差异","OpenClaw（Novita AI）和 Hermes Agent（Nous Research）都是本地运行的个人 AI Agent，但在记忆系统、技能学习、运行环境和模型生态上走了不同的路。深入对比两种架构的核心差异。","2026-05-01",[11,12,13],1679,{"slug":193,"title":194,"description":195,"pub_date":189,"tags":196,"draft":14,"word_count":201},"cpp-random-design-patterns","C++ 设计模式实战：RAII、观察者、工厂","用现代 C++（C++17\u002F20）实现三种高频设计模式：RAII 资源管理、观察者模式事件系统、工厂模式插件架构。每种模式给出问题场景、实现代码和真实工程案例。",[197,198,199,200],"cpp","设计模式","c++17","工程",2613,{"slug":203,"title":204,"description":205,"pub_date":189,"tags":206,"draft":14,"word_count":207},"data-structures-fundamentals","数据结构基础：从数组到红黑树","系统梳理常用数据结构的核心原理、时间复杂度和适用场景。数组、链表、栈、队列、哈希表、二叉树、堆、图，每种结构附实现要点和 C++ 代码片段。",[137,138,197,146],3004,{"slug":4,"title":5,"description":6,"pub_date":9,"tags":209,"draft":14,"word_count":210},[11,12,13],2116,{"slug":212,"title":213,"description":214,"pub_date":9,"tags":215,"draft":14,"word_count":216},"ai-agent-memory","AI Agent 的记忆系统：从上下文窗口到长期记忆","深入拆解 AI Agent 的四种记忆类型、上下文窗口压缩策略、RAG 向量检索原理，以及三种典型失败模式和工程选型建议。",[11,12,64],2052,{"slug":218,"title":219,"description":220,"pub_date":9,"tags":221,"draft":14,"word_count":225},"network-proxy-vpn-guide","代理与翻墙技术原理：从 HTTP 代理到现代协议","深入解析代理与 VPN 的本质区别，梳理从 SOCKS5 到 Shadowsocks、V2Ray\u002FXray、Hysteria2 的协议演进，以及机场订阅的技术本质。",[222,223,224],"网络","代理","协议",2148,{"slug":227,"title":228,"description":229,"pub_date":9,"tags":230,"draft":14,"word_count":147},"algorithm-binary-search","二分查找：永远写不对？记住这个模板","彻底搞清楚二分查找的边界问题：闭区间和左闭右开两套模板、三道经典 LeetCode 题目完整 C++ 实现，以及二分答案的进阶思路。",[138,231,232,197],"二分查找","leetcode",{"slug":234,"title":235,"description":236,"pub_date":9,"tags":237,"draft":14,"word_count":239},"algorithm-sliding-window","滑动窗口算法：从暴力到 O(n) 的思维跃迁","系统讲解滑动窗口算法的核心模板、适用题型，配合三道经典 LeetCode 题目的完整 C++ 实现，彻底理解双指针收缩思路。",[138,238,232,197],"滑动窗口",1943,{"slug":241,"title":242,"description":243,"pub_date":9,"tags":244,"draft":14,"word_count":247},"network-clash-config","Clash \u002F Mihomo 配置详解：规则、策略组与分流","深入解析 Clash\u002FMihomo 的核心配置结构，包括代理节点、策略组类型、规则优先级、DNS fake-ip 模式，以及一份实用的完整配置模板。",[222,245,223,246],"clash","配置",1292,{"slug":249,"title":250,"description":251,"pub_date":252,"tags":253,"draft":14,"word_count":257},"hid-hotplug","HID 设备热插拔检测：从 udev 到 node-hid","在 Linux 上用 node-hid + usb 库实现可靠的 USB HID 设备热插拔检测，踩坑记录","2026-04-28",[197,254,34,255,256],"hid","nodejs","electron",2039,{"slug":259,"title":260,"description":261,"pub_date":262,"tags":263,"draft":14,"word_count":266},"electron-ipc-types","Electron IPC 类型安全：从 any 到完全类型化","用 TypeScript 泛型封装 Electron IPC，彻底消灭 any，preload 契约集中管理","2026-04-25",[256,99,264,265],"ipc","vue",1446,{"slug":268,"title":269,"description":270,"pub_date":271,"tags":272,"draft":14,"word_count":275},"element-plus-popover-hide","手动关闭多个 el-popover（不用 v-model:visible）","通过 ref + Reflect.get 调用 hide() 方法手动关闭 Element Plus Popover，解释 Vue3 Proxy 导致无法直接调用实例方法的原因。","2024-10-25",[265,273,274],"element-plus","vue3",1321,{"slug":277,"title":278,"description":279,"pub_date":280,"tags":281,"draft":14,"word_count":285},"vite-vue3-ts-elementplus-pinia","用 Vite+（vp）从零搭建 Vue3 + TypeScript + Element Plus + Pinia + Vue Router","使用 Vite+ 统一工具链（vp）一条命令搭建 Vue3 全家桶，涵盖按需导入、Pinia store、路由配置，以及常见坑的解决方案。","2024-08-27",[265,282,99,273,283,284],"vite","pinia","vite-plus",1960,{"slug":287,"title":288,"description":289,"pub_date":290,"tags":291,"draft":14,"word_count":295},"cef-lnk2038-iterator-debug-level","CEF LNK2038：解决 _ITERATOR_DEBUG_LEVEL 不匹配错误","分析 CEF（Chromium Embedded Framework）集成时出现的 LNK2038 _ITERATOR_DEBUG_LEVEL 链接错误，从根本原因到解决方案的完整指南。","2024-05-07",[197,292,293,294],"CEF","Visual Studio","链接错误",1509,{"slug":297,"title":298,"description":299,"pub_date":300,"tags":301,"draft":14,"word_count":305},"npm-electron-install-fix","彻底解决 npm 安装 Electron 失败的问题","分析 npm install electron 失败的根本原因（下载二进制超时\u002F被墙），通过国内镜像（npmmirror）彻底解决，并介绍多种备选方案和常见错误排查。","2024-03-01",[256,302,303,304],"npm","前端工具链","国内镜像",1494,{"slug":307,"title":308,"description":309,"pub_date":310,"tags":311,"draft":14,"word_count":313},"git-out-of-memory","解决 git 报错：Fatal: Out of memory, malloc failed","分析 git 大仓库操作时出现 Out of memory malloc failed 的根本原因，通过调整 pack.windowMemory、http.postBuffer 和 git repack 彻底解决。","2024-01-31",[71,34,312],"工具",2244,{"slug":315,"title":316,"description":317,"pub_date":318,"tags":319,"draft":14,"word_count":323},"vmware-tools-install","在 VMware 虚拟机中安装 open-vm-tools 完整指南","详解 VMware Tools 的作用、open-vm-tools 与官方 VMware Tools 的区别，以及在 Ubuntu 虚拟机中安装并生效的完整步骤和常见问题排查。","2023-11-21",[320,34,321,322],"VMware","Ubuntu","虚拟机",2523,{"slug":325,"title":326,"description":327,"pub_date":328,"tags":329,"draft":14,"word_count":334},"load-balancing-algorithms","负载均衡算法完全指南：从轮询到一致性哈希","系统梳理静态与动态负载均衡算法，涵盖轮询、随机、权重、IP Hash、一致性 Hash、最少连接、最快响应等，并对比 Nginx、Dubbo、Spring Cloud LoadBalancer 的实现差异。","2023-11-15",[330,331,332,333],"分布式","负载均衡","Nginx","微服务",1764,{"slug":336,"title":337,"description":338,"pub_date":339,"tags":340,"draft":14,"word_count":344},"win-cw2a-ca2w","ATL 字符串转换：CW2A 与 CA2W 完全指南","详解 ATL 宏 CW2A\u002FCA2W 在 Unicode 与 ANSI 之间的字符串转换用法、头文件依赖、USES_CONVERSION 宏的作用与常见陷阱。","2023-06-09",[197,341,342,343],"windows","ATL","字符串",1665,{"slug":346,"title":347,"description":348,"pub_date":339,"tags":349,"draft":14,"word_count":353},"csharp-sendmessage-cpp","C# 通过 SendMessage 向 C++ 窗口发送消息与字符串","使用 P\u002FInvoke 调用 user32.dll 的 SendMessage，从 C# 发送自定义 WM_USER 消息及字符串指针给 C++ 原生窗口，并在 C++ 侧正确接收和转换。",[350,197,341,351,352],"C#","互操作","PInvoke",1554,{"slug":355,"title":356,"description":357,"pub_date":358,"tags":359,"draft":14,"word_count":361},"win-postmessage-vector","Windows PostMessage 跨线程传递 std::vector 指针","通过 PostMessage 在 Windows 消息队列中传递 std::vector 指针，使用 reinterpret_cast 将指针装入 LPARAM，并在接收方正确释放内存。","2023-05-26",[197,341,360],"WinAPI",1823,{"slug":363,"title":364,"description":365,"pub_date":358,"tags":366,"draft":14,"word_count":367},"exe-dll-single-package","将 EXE 和 DLL 打包成单一可执行文件","介绍两种将 exe 和依赖 dll 打包成单文件的方案：Enigma Virtual Box 和 WinRAR 自解压，适合发布 Windows 桌面程序时简化分发流程。",[341,197,312],1619,{"slug":369,"title":370,"description":371,"pub_date":358,"tags":372,"draft":14,"word_count":375},"cpp-random-mt19937","C++ 现代随机数生成：用 mt19937 彻底告别 rand()","深入讲解为什么 rand() 不够用，以及如何用 C++11 的 \u003Crandom> 库正确生成高质量随机数，涵盖 mt19937、各种分布和线程安全。",[197,373,374],"c++11","random",1549,{"slug":377,"title":378,"description":379,"pub_date":380,"tags":381,"draft":14,"word_count":383},"win-startup-registry","C++ 实现程序开机自启动：注册表方式详解","通过操作 Windows 注册表 Run 键实现程序开机自启动，包括 HKCU 与 HKLM 区别、完整封装代码、工作目录问题和 UAC 权限处理。","2022-12-26",[341,197,382],"registry",1201,{"slug":385,"title":386,"description":387,"pub_date":388,"tags":389,"draft":14,"word_count":391},"mfc-cstring-wparam","MFC 中 CString 与 WPARAM 之间的转换","详解 MFC 消息传递中 CString 无法直接强转为 WPARAM 的原因，以及两种正确的转换方案，并介绍结构体指针传递的正确姿势。","2022-11-25",[390,197,341],"mfc",1546,{"slug":393,"title":394,"description":395,"pub_date":396,"tags":397,"draft":14,"word_count":399},"duilib-static-build","正确编译 Duilib 静态库：避免 ATL 依赖和链接错误","详解如何用 DuiLib_Static.vcxproj 编译 Duilib 静态库，解决 VARIANT 未定义、Unicode 配置不匹配和 ATL 依赖等常见问题。","2022-08-24",[197,398,341,390],"duilib",2639,{"slug":401,"title":402,"description":403,"pub_date":404,"tags":405,"draft":14,"word_count":407},"mfc-dpi-adaptive","MFC 界面自适应不同分辨率","MFC 对话框程序实现控件和字体随分辨率自动缩放的完整方案，附 DPI Awareness 配置说明","2022-08-17",[390,197,341,406],"dpi",1414,{"slug":409,"title":410,"description":411,"pub_date":412,"tags":413,"draft":14,"word_count":414},"mfc-drag-window","MFC 无标题栏窗口客户区拖动：三种方法对比","MFC 对话框去掉标题栏后如何实现拖动移动窗口，三种方案完整实现与适用场景分析","2022-08-16",[390,197,341],1633,{"slug":416,"title":417,"description":418,"pub_date":419,"tags":420,"draft":14,"word_count":422},"algorithm-number-complement","整数的补数：位运算掩码解法","LeetCode 476 题，用掩码 XOR 实现整数补数，附 C++\u002FPython\u002FJava 三种实现及补数与补码的区别","2021-03-08",[138,421,232],"位运算",1374,[]]