<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>AI on Last Stand</title><link>https://amatsuzero.github.io/LastStand/categories/ai/</link><description>Recent content in AI on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 21 Jun 2026 22:41:52 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/categories/ai/index.xml" rel="self" type="application/rss+xml"/><item><title>AI Agent</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/ai-agent/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/ai-agent/</guid><description>&lt;p&gt;ChatGPT能写文章、能回答问题，但你让它帮你订一张机票，它做不到。它能告诉你&amp;quot;你应该去携程搜一下&amp;quot;，但它没法真的打开网页、输入日期、比价、下单。&lt;/p&gt;
&lt;p&gt;**AI Agent（智能体）**就是为了解决这个问题——让LLM不仅能&amp;quot;想&amp;quot;，还能&amp;quot;做&amp;quot;。Agent = LLM + 工具使用 + 自主规划 + 记忆。&lt;/p&gt;
&lt;h2 id="一从聊天机器人到智能体"&gt;一、从聊天机器人到智能体&lt;/h2&gt;
&lt;h3 id="11-纯llm的局限"&gt;1.1 纯LLM的局限&lt;/h3&gt;
&lt;p&gt;一个纯粹的LLM本质上是一个&amp;quot;无状态的文本生成器&amp;quot;：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph LR
IN["输入文本"] --&gt; LLM["LLM"]
LLM --&gt; OUT["输出文本"]
&lt;/pre&gt;
&lt;p&gt;它有几个根本性的限制：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;限制&lt;/th&gt;
&lt;th&gt;表现&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;无法执行动作&lt;/td&gt;
&lt;td&gt;不能调API、不能操作文件、不能访问数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;无持久记忆&lt;/td&gt;
&lt;td&gt;每次对话结束后就&amp;quot;忘了&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;知识过时&lt;/td&gt;
&lt;td&gt;无法获取训练数据之后的信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;无法自主规划&lt;/td&gt;
&lt;td&gt;不能将复杂任务分解并逐步执行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单轮思考&lt;/td&gt;
&lt;td&gt;一次生成就结束，不能自我检查和修正&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="12-agent的定义"&gt;1.2 Agent的定义&lt;/h3&gt;
&lt;p&gt;AI Agent是一个以LLM为&amp;quot;大脑&amp;quot;的自主系统，能够：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;感知&lt;/strong&gt;：理解用户的意图和当前环境状态&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规划&lt;/strong&gt;：将复杂目标分解为可执行的步骤&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;行动&lt;/strong&gt;：调用外部工具完成具体操作&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;观察&lt;/strong&gt;：获取行动的结果&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反思&lt;/strong&gt;：根据结果调整策略&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;graph TD
USER["用户目标"] --&gt; PERCEIVE["感知&lt;br/&gt;理解意图"]
PERCEIVE --&gt; PLAN["规划&lt;br/&gt;分解任务"]
PLAN --&gt; ACT["行动&lt;br/&gt;调用工具"]
ACT --&gt; OBSERVE["观察&lt;br/&gt;获取结果"]
OBSERVE --&gt; REFLECT["反思&lt;br/&gt;是否完成？"]
REFLECT --&gt;|未完成| PLAN
REFLECT --&gt;|已完成| RESULT["返回结果"]
&lt;/pre&gt;
&lt;h2 id="二agent的核心组件"&gt;二、Agent的核心组件&lt;/h2&gt;
&lt;h3 id="21-架构总览"&gt;2.1 架构总览&lt;/h3&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph Agent ["AI Agent"]
LLM["LLM（大脑）"]
PLAN["规划模块"]
MEM["记忆系统"]
TOOL["工具集"]
end
USER["用户"] --&gt; LLM
LLM --&gt; PLAN
PLAN --&gt; LLM
LLM --&gt; MEM
MEM --&gt; LLM
LLM --&gt; TOOL
TOOL --&gt; LLM
LLM --&gt; USER
&lt;/pre&gt;
&lt;h3 id="22-llmagent的大脑"&gt;2.2 LLM：Agent的大脑&lt;/h3&gt;
&lt;p&gt;LLM负责理解、推理和决策。作为Agent大脑的LLM需要具备：&lt;/p&gt;</description></item><item><title>AI编程工具</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/ai%E7%BC%96%E7%A8%8B%E5%B7%A5%E5%85%B7/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/ai%E7%BC%96%E7%A8%8B%E5%B7%A5%E5%85%B7/</guid><description>&lt;p&gt;AI编程工具正在重塑软件开发的工作方式。从简单的代码补全到自主完成复杂任务的编程Agent，这个领域在短短两三年内经历了巨大的变化。本文梳理AI编程工具的核心概念、工作原理和实践方法。&lt;/p&gt;
&lt;h2 id="一ai编程工具的演进"&gt;一、AI编程工具的演进&lt;/h2&gt;
&lt;h3 id="11-三代ai编程工具"&gt;1.1 三代AI编程工具&lt;/h3&gt;
&lt;pre class="mermaid"&gt;graph LR
G1["第一代&lt;br/&gt;代码补全&lt;br/&gt;Copilot (2021)"] --&gt; G2["第二代&lt;br/&gt;对话式编程&lt;br/&gt;ChatGPT (2022)"]
G2 --&gt; G3["第三代&lt;br/&gt;编程Agent&lt;br/&gt;Cursor/Devin (2024+)"]
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;代际&lt;/th&gt;
&lt;th&gt;交互方式&lt;/th&gt;
&lt;th&gt;能力范围&lt;/th&gt;
&lt;th&gt;代表产品&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;第一代&lt;/td&gt;
&lt;td&gt;行内补全，按Tab接受&lt;/td&gt;
&lt;td&gt;单行/单函数级别&lt;/td&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第二代&lt;/td&gt;
&lt;td&gt;对话框问答&lt;/td&gt;
&lt;td&gt;代码片段级别&lt;/td&gt;
&lt;td&gt;ChatGPT、Claude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第三代&lt;/td&gt;
&lt;td&gt;Agent模式，自主执行&lt;/td&gt;
&lt;td&gt;跨文件/跨系统级别&lt;/td&gt;
&lt;td&gt;Cursor、Windsurf、Devin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="12-当前主流工具对比"&gt;1.2 当前主流工具对比&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;工具&lt;/th&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;核心特点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;IDE插件&lt;/td&gt;
&lt;td&gt;最早的AI编程助手，集成在VS Code/JetBrains等主流IDE中&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;独立IDE&lt;/td&gt;
&lt;td&gt;基于VS Code深度定制，Agent模式、多文件编辑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Windsurf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;独立IDE&lt;/td&gt;
&lt;td&gt;Codeium推出，强调&amp;quot;Flow&amp;quot;模式的流畅体验&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CLI工具&lt;/td&gt;
&lt;td&gt;终端中运行的编程Agent，适合命令行工作流&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Devin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;云端Agent&lt;/td&gt;
&lt;td&gt;全自主编程Agent，自带开发环境&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon Q Developer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;IDE插件&lt;/td&gt;
&lt;td&gt;AWS深度集成，擅长云原生开发&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="二ai编程工具的工作原理"&gt;二、AI编程工具的工作原理&lt;/h2&gt;
&lt;h3 id="21-代码补全的原理"&gt;2.1 代码补全的原理&lt;/h3&gt;
&lt;p&gt;代码补全是最基础的能力。以Copilot为例：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph LR
CTX["上下文收集&lt;br/&gt;当前文件内容&lt;br/&gt;打开的相关文件&lt;br/&gt;光标位置"] --&gt; PROMPT["构造Prompt"]
PROMPT --&gt; LLM["LLM&lt;br/&gt;（Codex/GPT-4）"]
LLM --&gt; SUGGEST["补全建议"]
SUGGEST --&gt; USER["用户&lt;br/&gt;Tab接受 / Esc拒绝"]
&lt;/pre&gt;
&lt;p&gt;上下文收集是关键——模型看到的上下文越好，补全质量越高：&lt;/p&gt;</description></item><item><title>Claude Code 源码导读：Agent 设计详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/claude-code-%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sun, 21 Jun 2026 22:41:52 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/claude-code-%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Claude Code 的 agent 到底是怎么被设计成一个能长时间工作、能分派子 agent、能记忆、能压缩上下文、也能可靠停下来的系统的？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude Code 最值得研究的地方，不是它“能调用工具”，而是它把模型、工具、记忆、上下文、后台任务、hook 和权限系统编成了一个稳定的 &lt;strong&gt;agent harness&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;一句话概括：Claude Code 的 agent 不是一个模型循环，而是三层循环叠在一起：主 &lt;code&gt;query&lt;/code&gt; 循环负责推理和工具回灌；工具循环负责受控执行和并发；任务循环负责子 agent、后台 agent、记忆整理和长任务生命周期。&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
User["用户输入 / 队列消息"] --&gt; Query["query.ts 主循环"]
Query --&gt; Model["流式模型调用"]
Model --&gt;|没有 tool_use| StopPath["停止路径&lt;br/&gt;stop hooks / token budget / completed"]
Model --&gt;|产生 tool_use| ToolLoop["工具执行循环"]
ToolLoop --&gt; Attach["附件注入&lt;br/&gt;记忆 / 变更文件 / 任务通知 / 技能"]
Attach --&gt; Query
Query --&gt; Compact["上下文治理&lt;br/&gt;tool budget / microcompact / autocompact / reactive compact"]
Query --&gt; Memory["记忆系统&lt;br/&gt;CLAUDE.md / AutoMem / Session Memory"]
Query --&gt; AgentTool["AgentTool"]
AgentTool --&gt; SubAgent["runAgent 子循环"]
SubAgent --&gt; LocalTask["LocalAgentTask&lt;br/&gt;前台 / 后台 / 可恢复"]
LocalTask --&gt; Attach
&lt;/pre&gt;
&lt;h2 id="一核心源码地图"&gt;一、核心源码地图&lt;/h2&gt;
&lt;p&gt;先把关键文件放在桌面上：&lt;/p&gt;</description></item><item><title>FoundationModels</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/foundationmodels/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/foundationmodels/</guid><description>&lt;p&gt;2025年WWDC上，Apple把Apple Intelligence背后的那个&amp;quot;设备端基础模型&amp;quot;第一次对开发者开放——这就是&lt;strong&gt;FoundationModels&lt;/strong&gt;框架。过去要在App里接入LLM，基本只有两条路：调OpenAI/Claude这类云端API，或者自己在端上集成llama.cpp、MLC、Core ML等推理框架。前者有隐私和成本问题，后者有工程门槛和包体积问题。FoundationModels试图提供第三条路：&lt;strong&gt;一个系统级的、免费的、离线可用的、原生Swift的LLM API&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;本文从框架定位开始，一路讲到Guided Generation、Tool Calling、Streaming、Adapter微调等细节，目标是让你在读完后能直接上手用它写出一个生产可用的功能。&lt;/p&gt;
&lt;h2 id="一foundationmodels是什么"&gt;一、FoundationModels是什么&lt;/h2&gt;
&lt;h3 id="11-一句话定义"&gt;1.1 一句话定义&lt;/h3&gt;
&lt;p&gt;FoundationModels是iOS 26 / macOS 26及之后的系统框架，提供对&lt;strong&gt;设备端Apple Intelligence语言模型&lt;/strong&gt;的编程访问能力。模型本身约3B参数，经过4-bit量化，常驻系统，不计入App包体积，所有推理在设备上完成。&lt;/p&gt;
&lt;h3 id="12-能做什么--不能做什么"&gt;1.2 能做什么 / 不能做什么&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;能做&lt;/th&gt;
&lt;th&gt;不能做&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;文本生成、摘要、分类、抽取、改写、翻译&lt;/td&gt;
&lt;td&gt;世界知识问答（模型太小，不适合当&amp;quot;百科&amp;quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;结构化输出（生成指定Swift类型）&lt;/td&gt;
&lt;td&gt;图像生成 / 视频生成&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;工具调用（Function Calling）&lt;/td&gt;
&lt;td&gt;嵌入向量生成（Embedding）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;短对话、小规模推理&lt;/td&gt;
&lt;td&gt;长上下文的复杂推理（窗口有限）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;完全离线、无需联网&lt;/td&gt;
&lt;td&gt;替代GPT-4这类前沿大模型&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;定位非常清楚：&lt;strong&gt;它是一个&amp;quot;端侧小而美&amp;quot;的模型，负责那些没必要上云、对延迟/隐私/成本敏感的任务。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="13-为什么值得ios开发者关注"&gt;1.3 为什么值得iOS开发者关注&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;零成本&lt;/strong&gt;：不像调OpenAI API，每token都花钱。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零延迟网络层&lt;/strong&gt;：首token延迟可以做到100ms级。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐私合规&lt;/strong&gt;：输入不出设备，符合医疗、金融、教育场景的合规要求。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;离线可用&lt;/strong&gt;：地铁、飞机、隧道里也能跑。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原生Swift DSL&lt;/strong&gt;：宏驱动的&lt;code&gt;@Generable&lt;/code&gt;、&lt;code&gt;Tool&lt;/code&gt;协议，跟SwiftUI一样&amp;quot;声明式&amp;quot;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;与系统深度集成&lt;/strong&gt;：可直接访问Apple Intelligence上下文（比如屏幕识别、个人数据等，受权限约束）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二整体架构"&gt;二、整体架构&lt;/h2&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph APP ["应用层"]
UI["SwiftUI / UIKit"]
VM["ViewModel"]
end
subgraph FM ["FoundationModels Framework"]
SLM["SystemLanguageModel&lt;br/&gt;模型句柄 + 可用性"]
SESSION["LanguageModelSession&lt;br/&gt;会话对象 / 上下文"]
GEN["Generable宏&lt;br/&gt;结构化输出"]
TOOL["Tool协议&lt;br/&gt;工具调用"]
STREAM["ResponseStream&lt;br/&gt;流式输出"]
GUARD["Guardrails&lt;br/&gt;安全过滤"]
end
subgraph SYSTEM ["系统层"]
ANE["Apple Neural Engine"]
GPU["GPU"]
MODEL["On-device Foundation Model&lt;br/&gt;≈3B params, 4-bit quant"]
ADAPTER["LoRA Adapters"]
end
UI --&gt; VM
VM --&gt; SESSION
SESSION --&gt; SLM
SESSION --&gt; GEN
SESSION --&gt; TOOL
SESSION --&gt; STREAM
SESSION --&gt; GUARD
SLM --&gt; MODEL
MODEL --&gt; ANE
MODEL --&gt; GPU
ADAPTER --&gt; MODEL
&lt;/pre&gt;
&lt;p&gt;几个关键抽象：&lt;/p&gt;</description></item><item><title>Function Calling与MCP</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/function-calling%E4%B8%8Emcp/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/function-calling%E4%B8%8Emcp/</guid><description>&lt;p&gt;LLM很聪明，但它被困在一个&amp;quot;文本沙箱&amp;quot;里——它只能接收文本、输出文本。要让LLM调用API、查数据库、操作文件，就需要一个&amp;quot;桥梁&amp;quot;协议来连接LLM与外部世界。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Function Calling&lt;/strong&gt;和**MCP（Model Context Protocol）**就是这样的桥梁。它们的目标相同——让LLM能调用外部工具——但设计理念和使用场景有很大不同。本文将详细对比这两种方案。&lt;/p&gt;
&lt;h2 id="一function-callingllm原生的工具调用"&gt;一、Function Calling：LLM原生的工具调用&lt;/h2&gt;
&lt;h3 id="11-基本原理"&gt;1.1 基本原理&lt;/h3&gt;
&lt;p&gt;Function Calling是LLM提供商（OpenAI、Anthropic、Google等）在模型层面支持的工具调用能力。核心思路是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;你告诉LLM有哪些函数可用（函数名、参数定义、功能描述）&lt;/li&gt;
&lt;li&gt;LLM根据用户的问题判断是否需要调用函数&lt;/li&gt;
&lt;li&gt;如果需要，LLM输出一个结构化的函数调用请求（而不是自然语言）&lt;/li&gt;
&lt;li&gt;你的代码执行这个函数，把结果返回给LLM&lt;/li&gt;
&lt;li&gt;LLM基于结果生成最终回答&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
participant U as 用户
participant App as 应用程序
participant LLM as LLM API
participant Tool as 外部工具/API
U-&gt;&gt;App: "北京今天天气怎么样？"
App-&gt;&gt;LLM: 用户消息 + 可用函数定义
LLM-&gt;&gt;App: 函数调用请求&lt;br/&gt;get_weather(city="北京")
App-&gt;&gt;Tool: 调用天气API
Tool-&gt;&gt;App: {"temp": 22, "weather": "晴"}
App-&gt;&gt;LLM: 函数执行结果
LLM-&gt;&gt;App: "北京今天天气晴朗，气温22°C"
App-&gt;&gt;U: 最终回答
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键点：LLM自身并不执行函数，它只是生成&amp;quot;我想调用这个函数&amp;quot;的结构化指令，真正的执行由应用程序完成。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="12-函数定义"&gt;1.2 函数定义&lt;/h3&gt;
&lt;p&gt;以OpenAI的格式为例，开发者需要用JSON Schema描述每个可用的函数：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;tools&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;get_weather&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;获取指定城市的当前天气信息&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;object&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;城市名称，如&amp;#39;北京&amp;#39;、&amp;#39;上海&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;enum&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;celsius&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;fahrenheit&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;温度单位&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;LLM通过阅读这个定义来理解：这个函数叫什么、干什么用、需要什么参数。&lt;strong&gt;description字段的质量直接影响LLM能否正确选择和调用函数。&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Harness Engineering 精读笔记</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/harness-engineering/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/harness-engineering/</guid><description>&lt;blockquote&gt;
&lt;p&gt;基于 2025.11 — 2026.03 期间 Anthropic、OpenAI、LangChain、Google DeepMind、Stanford 发布的九篇核心文章的精读整理。
目标：理解 Harness Engineering 是什么，以及大公司和学术机构在实践中做了哪些探索。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一什么是-harness-engineering"&gt;一、什么是 Harness Engineering？&lt;/h2&gt;
&lt;h3 id="11-harness-的定义"&gt;1.1 Harness 的定义&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;LangChain&lt;/strong&gt; 给出了最清晰的公式化定义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Agent = Model + Harness&lt;/strong&gt;
&amp;ldquo;If you&amp;rsquo;re not the model, you&amp;rsquo;re the harness.&amp;rdquo;
&amp;ldquo;A harness is every piece of code, configuration, and execution logic that isn&amp;rsquo;t the model itself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;具体来说，Harness 包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System Prompts&lt;/strong&gt; — 系统提示词，定义 Agent 的行为边界&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools / Skills / MCPs&lt;/strong&gt; — 工具集及其描述（文件读写、代码执行、浏览器操作等）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bundled Infrastructure&lt;/strong&gt; — 捆绑基础设施（文件系统、沙箱、浏览器）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orchestration Logic&lt;/strong&gt; — 编排逻辑（子 Agent 派生、任务交接、模型路由）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hooks / Middleware&lt;/strong&gt; — 确定性执行逻辑（压缩、续行、lint 检查等）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Anthropic&lt;/strong&gt; 不给 Harness 下抽象定义，而是通过实践来展示：他们用 &amp;ldquo;harness design&amp;rdquo; 和 &amp;ldquo;harnesses for long-running agents&amp;rdquo; 来描述围绕 Agent 执行循环的编排层。Anthropic 在博客中明确说：&amp;ldquo;harness design is key to performance at the frontier of agentic coding&amp;rdquo;。&lt;/p&gt;</description></item><item><title>LLM Wiki：Karpathy 提出的"后 RAG 时代"个人知识库范式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/llm-wiki/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/llm-wiki/</guid><description>&lt;p&gt;2026 年 4 月，Andrej Karpathy 在 GitHub Gist 上发布了一份名为 &lt;code&gt;llm-wiki.md&lt;/code&gt; 的&amp;quot;想法文档&amp;quot;（idea file），短短几天收获了 5000+ 星和 5000+ fork。这篇文档篇幅不长，却被评价为&amp;quot;后 RAG 时代&amp;quot;个人知识管理的一个**分类定义性（category-defining）**框架。&lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f"&gt;https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Karpathy 写这篇文档的风格非常有意思：它&lt;strong&gt;不是一份实现规范&lt;/strong&gt;，而是一份&amp;quot;可以复制粘贴给你自己的 LLM Agent（Claude Code、Codex、OpenCode/Pi 等）&amp;ldquo;的&lt;strong&gt;模式描述&lt;/strong&gt;。它告诉 Agent 模式的核心是什么，剩下的细节（目录结构、schema 约定、页面格式、工具链）交给用户和 Agent 一起协同演化。&lt;/p&gt;
&lt;p&gt;本文将详细拆解这份文档的核心思想，并结合社区讨论（scale 极限、Zettelkasten 替代方案、反对派观点等）给出一个完整解读。&lt;/p&gt;
&lt;h2 id="一问题起点rag-的每次从零开始"&gt;一、问题起点：RAG 的&amp;quot;每次从零开始&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;大多数人今天使用 LLM 处理文档的方式是 &lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ai/rag/"&gt;RAG（检索增强生成）&lt;/a&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把一堆文档上传到系统&lt;/li&gt;
&lt;li&gt;查询时 LLM 从原文中检索相关片段&lt;/li&gt;
&lt;li&gt;基于片段合成答案&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;NotebookLM、ChatGPT 文件上传、绝大多数 RAG 系统都是这个模式。&lt;/p&gt;
&lt;h3 id="11-rag-的根本局限没有累积"&gt;1.1 RAG 的根本局限：没有累积&lt;/h3&gt;
&lt;p&gt;Karpathy 点出了 RAG 的一个关键问题：&lt;strong&gt;LLM 每次都在从零开始重新发现知识&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;问一个需要综合 5 篇文档的微妙问题 → LLM 每次都要&lt;strong&gt;重新&lt;/strong&gt;找出相关片段，&lt;strong&gt;重新&lt;/strong&gt;拼接，&lt;strong&gt;重新&lt;/strong&gt;推理&lt;/li&gt;
&lt;li&gt;上一次你问过的关键问题的答案，下一次再问时不会被保留&lt;/li&gt;
&lt;li&gt;跨源的矛盾、交叉引用、细微的关联 —— 每次都要重新建立&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;什么都没有被&amp;quot;沉淀&amp;quot;下来。&lt;/strong&gt; 这就像每次考试都重新读一遍教科书，却从不做笔记、从不整理知识卡片、从不画思维导图。&lt;/p&gt;
&lt;h3 id="12-llm-wiki-的核心差异"&gt;1.2 LLM Wiki 的核心差异&lt;/h3&gt;
&lt;p&gt;LLM Wiki 提出了一个根本性的反转：&lt;/p&gt;</description></item><item><title>Prompt Engineering</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/prompt-engineering/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/prompt-engineering/</guid><description>&lt;p&gt;大语言模型（LLM）的能力边界很大程度上取决于你怎么跟它说话。同样的模型，一个精心设计的Prompt可以得到专业级的回答，一个随意的Prompt可能只得到平庸甚至错误的结果。Prompt Engineering就是研究如何有效地与LLM沟通的技术。&lt;/p&gt;
&lt;h2 id="一prompt的基本构成"&gt;一、Prompt的基本构成&lt;/h2&gt;
&lt;h3 id="11-一个prompt的解剖"&gt;1.1 一个Prompt的解剖&lt;/h3&gt;
&lt;p&gt;一个高质量的Prompt通常包含以下要素：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TD
P["完整的Prompt"] --&gt; R["角色&lt;br/&gt;Role"]
P --&gt; C["上下文&lt;br/&gt;Context"]
P --&gt; I["指令&lt;br/&gt;Instruction"]
P --&gt; E["示例&lt;br/&gt;Examples"]
P --&gt; F["格式要求&lt;br/&gt;Format"]
P --&gt; CO["约束&lt;br/&gt;Constraints"]
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;要素&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;角色&lt;/td&gt;
&lt;td&gt;设定模型的身份和专业背景&lt;/td&gt;
&lt;td&gt;&amp;ldquo;你是一位有10年经验的iOS架构师&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;上下文&lt;/td&gt;
&lt;td&gt;提供背景信息&lt;/td&gt;
&lt;td&gt;&amp;ldquo;我们的项目使用MVVM架构，Swift语言&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;指令&lt;/td&gt;
&lt;td&gt;明确说明任务&lt;/td&gt;
&lt;td&gt;&amp;ldquo;请review以下代码并指出问题&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;示例&lt;/td&gt;
&lt;td&gt;展示期望的输入输出格式&lt;/td&gt;
&lt;td&gt;给出一个输入-输出样例&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;格式要求&lt;/td&gt;
&lt;td&gt;指定输出的结构&lt;/td&gt;
&lt;td&gt;&amp;ldquo;以Markdown表格形式输出&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;约束&lt;/td&gt;
&lt;td&gt;限制条件&lt;/td&gt;
&lt;td&gt;&amp;ldquo;不超过500字&amp;quot;&amp;ldquo;只使用Swift标准库&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="12-system-prompt-vs-user-prompt"&gt;1.2 System Prompt vs User Prompt&lt;/h3&gt;
&lt;p&gt;在API调用中，消息分为不同的角色：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;role&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;system&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;你是一位资深iOS开发工程师，擅长性能优化。回答时给出具体的代码示例。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;role&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;如何优化UITableView的滚动性能？&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System Prompt&lt;/strong&gt;：设定模型的整体行为、角色和约束，贯穿整个对话&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Prompt&lt;/strong&gt;：具体的问题或指令&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assistant&lt;/strong&gt;：模型的历史回复，提供对话上下文&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二核心prompt技术"&gt;二、核心Prompt技术&lt;/h2&gt;
&lt;h3 id="21-zero-shot-prompting"&gt;2.1 Zero-Shot Prompting&lt;/h3&gt;
&lt;p&gt;直接给指令，不提供任何示例：&lt;/p&gt;</description></item><item><title>RAG（检索增强生成）</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/rag/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/rag/</guid><description>&lt;p&gt;大语言模型（LLM）能流畅地写文章、回答问题、编写代码，但它有一个根本性的局限：&lt;strong&gt;它的知识被冻结在训练数据截止的那一刻&lt;/strong&gt;。问它昨天发生了什么新闻？不知道。问它你公司内部的技术文档？更不知道。&lt;/p&gt;
&lt;p&gt;更棘手的是，LLM有时候会&amp;quot;一本正经地胡说八道&amp;quot;——这就是所谓的**幻觉（Hallucination）**问题。模型会自信满满地编造一个不存在的论文引用、一个错误的API参数、甚至一个虚构的历史事件。&lt;/p&gt;
&lt;p&gt;**RAG（Retrieval-Augmented Generation，检索增强生成）**正是为解决这些问题而生。它的核心思想简单而有效：&lt;strong&gt;在让LLM回答之前，先从外部知识库中检索相关信息，把这些信息塞到提示词（Prompt）里，让LLM基于真实资料来回答。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="一rag的核心思想"&gt;一、RAG的核心思想&lt;/h2&gt;
&lt;h3 id="11-一个直觉的类比"&gt;1.1 一个直觉的类比&lt;/h3&gt;
&lt;p&gt;想象你是一个闭卷考试的学生（这就是纯LLM）——只能靠记忆作答，记不清的地方就只能猜。&lt;/p&gt;
&lt;p&gt;现在允许你带一本参考书（这就是RAG）——遇到不确定的问题，先翻书找到相关段落，然后基于书中的内容来组织答案。&lt;/p&gt;
&lt;p&gt;显然，开卷考试的准确率会高得多。&lt;/p&gt;
&lt;h3 id="12-rag的核心价值"&gt;1.2 RAG的核心价值&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;LLM的局限&lt;/th&gt;
&lt;th&gt;RAG的解决方案&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;知识过期，无法获取训练截止后的信息&lt;/td&gt;
&lt;td&gt;随时更新知识库，实时生效&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;幻觉问题，生成不存在的信息&lt;/td&gt;
&lt;td&gt;基于真实文档生成，可追溯来源&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;垂直领域知识不足&lt;/td&gt;
&lt;td&gt;接入专业知识库，提供领域专业回答&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;更新成本高，Fine-tuning代价大&lt;/td&gt;
&lt;td&gt;只需更新知识库，成本低且灵活&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="13-rag的基本流程"&gt;1.3 RAG的基本流程&lt;/h3&gt;
&lt;pre class="mermaid"&gt;graph LR
Q["用户提问"] --&gt; R["检索器&lt;br/&gt;Retriever"]
KB["知识库"] --&gt; R
R --&gt; C["相关文档片段"]
C --&gt; P["构造Prompt&lt;br/&gt;问题 + 相关文档"]
P --&gt; LLM["大语言模型"]
LLM --&gt; A["生成回答"]
&lt;/pre&gt;
&lt;p&gt;三个核心步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;检索（Retrieve）&lt;/strong&gt;：根据用户的问题，从知识库中找到最相关的文档片段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;增强（Augment）&lt;/strong&gt;：将检索到的信息与原始问题一起构造成Prompt&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成（Generate）&lt;/strong&gt;：LLM基于增强后的Prompt生成回答&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="二从关键词到语义检索方式的演进"&gt;二、从关键词到语义：检索方式的演进&lt;/h2&gt;
&lt;h3 id="21-传统关键词搜索的局限"&gt;2.1 传统关键词搜索的局限&lt;/h3&gt;
&lt;p&gt;最简单的检索方式是关键词匹配。比如用户问&amp;quot;如何购买商品？&amp;quot;，搜索引擎会提取关键词&amp;quot;购买&amp;quot;、&amp;ldquo;商品&amp;rdquo;，然后去匹配包含这些词的文档。&lt;/p&gt;
&lt;p&gt;问题很明显：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文档中写的是&amp;quot;下单流程说明&amp;quot;——语义完全一致，但&lt;strong&gt;没有任何关键词重合&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;无法理解同义词：&amp;ldquo;购买&amp;quot;vs&amp;quot;下单&amp;quot;vs&amp;quot;采购&amp;quot;vs&amp;quot;买&amp;rdquo;&lt;/li&gt;
&lt;li&gt;必须精确匹配关键词，用词不同就检索不到&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们需要一种理解语义的检索方式。&lt;/p&gt;
&lt;h3 id="22-文本嵌入text-embedding"&gt;2.2 文本嵌入（Text Embedding）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;文本嵌入模型&lt;/strong&gt;（如OpenAI的text-embedding-3-small、BGE等）将文本转换为高维向量（通常512/768/1024/1536维），使得语义相近的文本在向量空间中距离相近：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;如何购买商品？&amp;#34; → [0.23, -0.15, 0.82, ...] (768维向量)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;下单流程说明&amp;#34; → [0.21, -0.12, 0.79, ...] ← 向量很近，语义匹配!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;今天天气真好&amp;#34; → [-0.65, 0.43, -0.21, ...] ← 向量很远
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在高维向量空间中，每个维度代表不同的语义特征（如情感倾向、主题领域、动作类型等）。语义相似的文本会在空间中聚集在一起——&amp;ldquo;购买&amp;rdquo;、&amp;ldquo;下单&amp;rdquo;、&amp;ldquo;采购&amp;quot;形成一个语义簇，而&amp;quot;天气预报&amp;quot;则远离这个簇。&lt;/p&gt;</description></item><item><title>Transformer架构原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/transformer%E6%9E%B6%E6%9E%84%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/transformer%E6%9E%B6%E6%9E%84%E5%8E%9F%E7%90%86/</guid><description>&lt;p&gt;ChatGPT、Claude、Gemini——这些模型的核心都是同一个架构：&lt;strong&gt;Transformer&lt;/strong&gt;。它在2017年由Google的论文&amp;quot;Attention Is All You Need&amp;quot;提出，彻底改变了自然语言处理（NLP）领域，随后席卷了计算机视觉、语音、蛋白质折叠等几乎所有AI领域。&lt;/p&gt;
&lt;p&gt;我们从最直觉的角度出发，一步步搞清楚Transformer到底在做什么。&lt;/p&gt;
&lt;h2 id="一从序列到序列transformer要解决什么问题"&gt;一、从序列到序列：Transformer要解决什么问题&lt;/h2&gt;
&lt;h3 id="11-语言的本质是序列"&gt;1.1 语言的本质是序列&lt;/h3&gt;
&lt;p&gt;一句话是一个词的序列：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;我 今天 很 开心&amp;#34; → [我, 今天, 很, 开心]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;语言模型的核心任务是：给定前面的词，预测下一个词。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;我 今天 很&amp;#34; → ?（开心？难过？忙碌？）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但词与词之间的关系非常复杂。&amp;ldquo;它&amp;quot;指代谁？&amp;ldquo;银行&amp;quot;是河岸还是金融机构？这取决于上下文中其他词的信息。&lt;/p&gt;
&lt;h3 id="12-rnn的困境"&gt;1.2 RNN的困境&lt;/h3&gt;
&lt;p&gt;在Transformer之前，处理序列的主流方法是循环神经网络（RNN）。RNN像一个人从左到右逐词阅读，用一个&amp;quot;记忆状态&amp;quot;来记住看过的内容：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph LR
X1["我"] --&gt; H1["h₁"]
H1 --&gt; H2["h₂"]
X2["今天"] --&gt; H2
H2 --&gt; H3["h₃"]
X3["很"] --&gt; H3
H3 --&gt; H4["h₄"]
X4["开心"] --&gt; H4
&lt;/pre&gt;
&lt;p&gt;问题在于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;长距离依赖困难&lt;/strong&gt;：信息需要经过很多步才能从序列开头传到末尾，容易丢失&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无法并行&lt;/strong&gt;：必须逐步处理，前一步完成才能开始后一步，训练很慢&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transformer的核心洞察是：&lt;strong&gt;不需要逐步处理，让序列中的每个位置直接与所有其他位置交互&lt;/strong&gt;。这就是&amp;quot;注意力（Attention）&amp;ldquo;机制。&lt;/p&gt;
&lt;h2 id="二词嵌入给词语一个数学身份"&gt;二、词嵌入：给词语一个数学身份&lt;/h2&gt;
&lt;h3 id="21-从独热编码到词向量"&gt;2.1 从独热编码到词向量&lt;/h3&gt;
&lt;p&gt;计算机不认识&amp;quot;猫&amp;rdquo;、&amp;ldquo;狗&amp;quot;这样的文字。我们需要把词转换成数字。&lt;/p&gt;
&lt;p&gt;最朴素的方式是&lt;strong&gt;独热编码（One-Hot Encoding）&lt;/strong&gt;：假设词汇表有50,000个词，每个词用一个50,000维的向量表示，只有对应位置是1，其余全是0。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;猫&amp;#34; → [0, 0, ..., 1, ..., 0, 0] (第3721个位置是1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;狗&amp;#34; → [0, 0, ..., 0, 1, ..., 0, 0] (第5042个位置是1)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;问题：在这种表示下，&amp;ldquo;猫&amp;quot;和&amp;quot;狗&amp;quot;的距离与&amp;quot;猫&amp;quot;和&amp;quot;经济学&amp;quot;的距离一样远——完全丢失了语义信息。&lt;/p&gt;</description></item><item><title>iOS中AI Chat实战</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/ios%E4%B8%ADai-chat%E5%AE%9E%E6%88%98/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/ios%E4%B8%ADai-chat%E5%AE%9E%E6%88%98/</guid><description>&lt;p&gt;做一个能跑的AI聊天Demo只需要几十行代码：拼一个HTTP请求、把模型返回的文本显示出来即可。但要做一个&lt;strong&gt;达到生产级体验&lt;/strong&gt;的AI Chat，就会面对一堆并不&amp;quot;AI&amp;quot;的工程问题：字怎么一个个&amp;quot;蹦&amp;quot;出来？Markdown怎么边流边渲染？模型想让前端弹一个卡片甚至一个表单，该怎么办？用户点击卡片里的按钮怎么回传给模型？&lt;/p&gt;
&lt;p&gt;本文以iOS为实现目标，系统梳理AI Chat的工程架构，重点讲清楚两件事：&lt;strong&gt;流式输出&lt;/strong&gt;与&lt;strong&gt;A2UI（Agent to UI）&lt;/strong&gt;，同时覆盖工具调用、取消、多模态、端侧推理等常见高级能力。&lt;/p&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;一个完整的iOS AI Chat客户端，通常可以拆成如下几层：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph UI ["展示层"]
LIST["消息列表&lt;br/&gt;UICollectionView / List"]
CELL["消息Cell&lt;br/&gt;文本 / Markdown / A2UI Surface"]
INPUT["输入区&lt;br/&gt;文本 / 图片 / 语音"]
end
subgraph VM ["ViewModel层"]
STATE["会话状态机"]
STREAM["流式拼装器"]
TOOL["工具执行器"]
end
subgraph NET ["网络层"]
SSE["SSE / HTTP 分块"]
PARSER["协议解析&lt;br/&gt;OpenAI / Claude / A2UI"]
end
subgraph DATA ["数据层"]
DB["消息持久化&lt;br/&gt;GRDB / WCDB / CoreData"]
CTX["上下文裁剪&lt;br/&gt;Token预算"]
end
INPUT --&gt; STATE
STATE --&gt; NET
NET --&gt; PARSER
PARSER --&gt; STREAM
STREAM --&gt; CELL
STREAM --&gt; TOOL
TOOL --&gt; NET
STATE --&gt; DB
DB --&gt; CTX
CTX --&gt; NET
&lt;/pre&gt;
&lt;p&gt;几个关键特征：&lt;/p&gt;</description></item><item><title>反向传播算法</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD%E7%AE%97%E6%B3%95/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD%E7%AE%97%E6%B3%95/</guid><description>&lt;p&gt;在上一篇文章中，我们构建了一个神经网络，了解了前向传播是如何产生预测的，也知道了损失函数可以衡量预测有多差。但我们遗留了最核心的问题：&lt;strong&gt;那13,002个参数到底该怎么调整，才能让网络变得更好？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是反向传播算法（Backpropagation）要回答的问题。它是神经网络学习的核心引擎，几乎所有现代深度学习的训练都建立在它之上。&lt;/p&gt;
&lt;h2 id="一梯度下降从直觉开始"&gt;一、梯度下降：从直觉开始&lt;/h2&gt;
&lt;h3 id="11-一个简单的类比"&gt;1.1 一个简单的类比&lt;/h3&gt;
&lt;p&gt;想象你站在一片浓雾中的山地上，看不到全貌，但你能感受到脚下地面的倾斜方向。你的目标是找到最低的山谷。最自然的策略是什么？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;顺着脚下最陡的下坡方向走一小步。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就是**梯度下降（Gradient Descent）**的核心思想。&lt;/p&gt;
&lt;h3 id="12-数学表述"&gt;1.2 数学表述&lt;/h3&gt;
&lt;p&gt;假设损失函数 $L$ 取决于所有参数 $\theta = (w_1, w_2, ..., w_n, b_1, b_2, ..., b_m)$。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;梯度&lt;/strong&gt;是一个向量，指向损失增长最快的方向：&lt;/p&gt;
$$\nabla L = \left(\frac{\partial L}{\partial w_1}, \frac{\partial L}{\partial w_2}, \cdots, \frac{\partial L}{\partial b_m}\right)$$&lt;p&gt;梯度的每个分量告诉我们：如果微微增大某个参数，损失会增加多少。&lt;/p&gt;
&lt;p&gt;要降低损失，我们朝梯度的&lt;strong&gt;反方向&lt;/strong&gt;迈步：&lt;/p&gt;
$$\theta_{\text{new}} = \theta_{\text{old}} - \eta \cdot \nabla L$$&lt;p&gt;其中 $\eta$ 是&lt;strong&gt;学习率（learning rate）&lt;/strong&gt;，控制每一步的步长。&lt;/p&gt;
&lt;h3 id="13-学习率的微妙之处"&gt;1.3 学习率的微妙之处&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;学习率&lt;/th&gt;
&lt;th style="text-align: left"&gt;下降行为&lt;/th&gt;
&lt;th style="text-align: left"&gt;结果&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;太小&lt;/td&gt;
&lt;td style="text-align: left"&gt;每步挪动极小，到达局部最小值后就停住了，无法跳出&lt;/td&gt;
&lt;td style="text-align: left"&gt;收敛极慢，可能困在局部最小值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;太大&lt;/td&gt;
&lt;td style="text-align: left"&gt;一步跨过了最低点，又跨回来，反复来回&lt;/td&gt;
&lt;td style="text-align: left"&gt;在最低点附近震荡，甚至发散&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;合适&lt;/td&gt;
&lt;td style="text-align: left"&gt;每步大小适中，沿着曲面稳步走向谷底&lt;/td&gt;
&lt;td style="text-align: left"&gt;稳步下降，逐渐逼近最优解&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="14-梯度下降的关键问题"&gt;1.4 梯度下降的关键问题&lt;/h3&gt;
&lt;p&gt;现在整个问题归结为一件事：&lt;strong&gt;怎么高效地计算 $\nabla L$，即损失对每一个参数的偏导数？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你可能会想：对每个参数微微扰动一下，看看损失变化了多少。但如果有13,002个参数，每个参数都扰动一次，就需要做13,002次前向传播——太慢了。&lt;/p&gt;</description></item><item><title>神经网络原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%8E%9F%E7%90%86/</guid><description>&lt;p&gt;想象你手写了一个数字&amp;quot;3&amp;quot;，然后拿给计算机看——它是怎么&amp;quot;认出&amp;quot;这是3而不是8的？这个看似简单的问题，背后隐藏着整个深度学习的核心思想。让我们从最直觉的方式开始，一层一层揭开神经网络的面纱。&lt;/p&gt;
&lt;h2 id="一从像素到数字问题的本质"&gt;一、从像素到数字：问题的本质&lt;/h2&gt;
&lt;h3 id="11-手写数字识别"&gt;1.1 手写数字识别&lt;/h3&gt;
&lt;p&gt;假设我们有一张28x28像素的灰度手写数字图片。每个像素是一个0到1之间的数字——0代表全黑，1代表全白。这意味着一张图片其实就是一个包含784个数字的列表。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;图片 → [0.0, 0.0, 0.12, 0.85, 0.93, ..., 0.0] (784个数字)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们的目标是设计一个函数，输入这784个数字，输出10个数字，分别代表这张图是0~9每个数字的概率：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;f(784个像素值) → [P(0), P(1), P(2), ..., P(9)]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;比如输入一张手写的&amp;quot;3&amp;quot;，我们期望输出类似：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[0.01, 0.02, 0.05, 0.89, 0.01, 0.01, 0.00, 0.01, 0.00, 0.00]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;3&amp;#34;的概率最高
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这就是神经网络要解决的问题。但关键问题是：这个函数 &lt;code&gt;f&lt;/code&gt; 长什么样？&lt;/p&gt;
&lt;h3 id="12-为什么传统编程行不通"&gt;1.2 为什么传统编程行不通&lt;/h3&gt;
&lt;p&gt;你可能会想：能不能写一堆if-else规则？比如&amp;quot;如果上方有一个圆弧，下方也有一个圆弧，那就是3&amp;quot;。&lt;/p&gt;
&lt;p&gt;问题在于：人类写字的方式千变万化。同一个&amp;quot;3&amp;quot;，有人写得圆润，有人写得尖锐，有人偏左，有人偏右。你几乎不可能用明确的规则覆盖所有情况。&lt;/p&gt;
&lt;p&gt;我们需要的是一种&lt;strong&gt;从数据中自动学习规则&lt;/strong&gt;的方法——这就是神经网络。&lt;/p&gt;
&lt;h2 id="二神经网络的结构"&gt;二、神经网络的结构&lt;/h2&gt;
&lt;h3 id="21-神经元最基本的单元"&gt;2.1 神经元：最基本的单元&lt;/h3&gt;
&lt;p&gt;让我们从最简单的单元开始。一个&lt;strong&gt;神经元&lt;/strong&gt;本质上就是一个持有数字的容器。这个数字叫做&lt;strong&gt;激活值（activation）&lt;/strong&gt;，取值范围通常在0到1之间。&lt;/p&gt;
&lt;p&gt;你可以把它想象成一个灯泡：0表示完全熄灭，1表示完全点亮，中间的值表示不同亮度。&lt;/p&gt;
&lt;h3 id="22-层神经元的组织方式"&gt;2.2 层：神经元的组织方式&lt;/h3&gt;
&lt;p&gt;神经网络把神经元组织成&lt;strong&gt;层（layer）&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph LR
subgraph 输入层 [输入层 - 784个神经元]
I1[像素1]
I2[像素2]
I3[...]
I784[像素784]
end
subgraph 隐藏层1 [隐藏层1 - 16个神经元]
H1_1[h1]
H1_2[h2]
H1_3[...]
H1_16[h16]
end
subgraph 隐藏层2 [隐藏层2 - 16个神经元]
H2_1[h1]
H2_2[h2]
H2_3[...]
H2_16[h16]
end
subgraph 输出层 [输出层 - 10个神经元]
O0[0]
O1[1]
O2[...]
O9[9]
end
I1 --&gt; H1_1
I1 --&gt; H1_2
I784 --&gt; H1_16
H1_1 --&gt; H2_1
H1_16 --&gt; H2_16
H2_1 --&gt; O0
H2_16 --&gt; O9
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输入层&lt;/strong&gt;：784个神经元，每个对应一个像素值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐藏层&lt;/strong&gt;：中间的层（这里用2层，每层16个神经元）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输出层&lt;/strong&gt;：10个神经元，对应数字0~9&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为什么叫&amp;quot;隐藏层&amp;quot;？因为在训练数据中，我们只知道输入（像素）和输出（标签），中间层在&amp;quot;学什么&amp;quot;我们并不直接指定——它们是被自动学出来的。&lt;/p&gt;</description></item><item><title>OpenClaw 源码导读（三）：Agent Harness — 为"每一家 LLM 都能兜住"而生的执行管线</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-agent-harness/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-agent-harness/</guid><description>&lt;blockquote&gt;
&lt;p&gt;系列第一篇把 OpenClaw 的架构地图摊开，第二篇深入 Gateway 控制平面。这一篇，我们钻进整个项目的心脏——&lt;code&gt;src/agents/&lt;/code&gt;，看 OpenClaw 怎么处理最复杂的一件事：&lt;strong&gt;当 Gateway 接到一条用户消息之后，怎么把它变成一轮真正的 LLM turn + Tool 循环&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这一层代码的体量和复杂度非常惊人：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/agents/pi-embedded-runner/run.ts&lt;/code&gt; 单文件 &lt;strong&gt;2160 行&lt;/strong&gt;，是整个 agent 循环的驱动器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/agents/pi-embedded-runner/compact.ts&lt;/code&gt; &lt;strong&gt;1148 行&lt;/strong&gt;，专门处理上下文压缩。&lt;/li&gt;
&lt;li&gt;整个 &lt;code&gt;src/agents/&lt;/code&gt; 目录有 &lt;strong&gt;830+ 个文件&lt;/strong&gt;，光 &lt;code&gt;anthropic-*.ts&lt;/code&gt; 就有近 20 个（为了 Messages API 的各种 edge case）。&lt;/li&gt;
&lt;li&gt;同时支持 &lt;strong&gt;Anthropic、OpenAI、Google Gemini、Bedrock、Vertex、OpenRouter、Z.AI/GLM、MiniMax、Qwen、Ollama、Kilocode&lt;/strong&gt; 等十多个 provider。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但这些&amp;quot;量&amp;quot;的背后，是一个&lt;strong&gt;只有一个接口的核心抽象：AgentHarness&lt;/strong&gt;。本文就从这个抽象出发，一路看到 2160 行循环如何处置真实世界里十几类失败。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一harness-抽象只有一个-runattempt"&gt;一、Harness 抽象：只有一个 &lt;code&gt;runAttempt&lt;/code&gt;&lt;/h2&gt;
&lt;h3 id="1-为什么不用-langchain-风格的agent-framework"&gt;1. 为什么不用 LangChain 风格的&amp;quot;Agent Framework&amp;quot;&lt;/h3&gt;
&lt;p&gt;读过 LangChain 或 CrewAI 的人第一眼会期望看到 &lt;code&gt;AgentExecutor&lt;/code&gt;、&lt;code&gt;AgentChain&lt;/code&gt;、&lt;code&gt;Memory&lt;/code&gt;、&lt;code&gt;Callback&lt;/code&gt;、&lt;code&gt;Tool&lt;/code&gt; 这些类。OpenClaw 里&lt;strong&gt;一个都没有&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;它的选择是：&lt;strong&gt;把整个 agent 循环当成一个黑盒&lt;/strong&gt;，对外只暴露一个接口：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-30:39:src/agents/harness/types.ts" data-lang="30:39:src/agents/harness/types.ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AgentHarness&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;label&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pluginId?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;supports&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;AgentHarnessSupportContext&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AgentHarnessSupport&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;runAttempt&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;params&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;AgentHarnessAttemptParams&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Promise&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;AgentHarnessAttemptResult&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;compact&lt;/span&gt;&lt;span style="color:#f92672"&gt;?&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;params&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;AgentHarnessCompactParams&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Promise&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;AgentHarnessCompactResult&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;undefined&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reset&lt;/span&gt;&lt;span style="color:#f92672"&gt;?&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;params&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;AgentHarnessResetParams&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Promise&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;void&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dispose&lt;/span&gt;&lt;span style="color:#f92672"&gt;?&lt;/span&gt;()&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Promise&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;void&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;五个方法，其中三个可选：&lt;/p&gt;</description></item><item><title>OpenClaw 源码导读（四）：Channels、Nodes 与扩展生态</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-channels%E4%B8%8E%E6%89%A9%E5%B1%95%E7%94%9F%E6%80%81/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-channels%E4%B8%8E%E6%89%A9%E5%B1%95%E7%94%9F%E6%80%81/</guid><description>&lt;blockquote&gt;
&lt;p&gt;前三篇我们看清了 OpenClaw 的三副骨架：架构全景、Gateway 控制平面、Agent Harness 执行管线。这一篇是压轴篇，我们看它的&amp;quot;血肉&amp;quot;——&lt;strong&gt;&lt;code&gt;channels/&lt;/code&gt;、&lt;code&gt;node-host/&lt;/code&gt;、&lt;code&gt;canvas-host/&lt;/code&gt;、&lt;code&gt;plugins/&lt;/code&gt;、&lt;code&gt;skills/&lt;/code&gt;、&lt;code&gt;sandbox/&lt;/code&gt;&lt;/strong&gt;。OpenClaw 真正&amp;quot;好用&amp;quot;的感觉，是从这一层来的：一条消息从 WhatsApp 进来、触发 iOS 上的摄像头、在 Android 上渲染一张 Canvas、最后把结果发回 Slack 线程——整个过程中 Gateway 本身一行代码都不需要改。&lt;/p&gt;
&lt;p&gt;本文涵盖 &lt;strong&gt;118 个 channel/provider extension、53 个 skill、iOS/macOS/Android node 客户端、A2UI Canvas 协议、以及 Docker sandbox 的整套隔离模型&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一channels118-个-extension-是怎么插进来的"&gt;一、Channels：118 个 extension 是怎么&amp;quot;插&amp;quot;进来的&lt;/h2&gt;
&lt;h3 id="1-channelplugin-接口"&gt;1. ChannelPlugin 接口&lt;/h3&gt;
&lt;p&gt;OpenClaw 所有 channel（微信、Telegram、Slack、iMessage、IRC、Discord……）本质上都是实现同一个接口 &lt;code&gt;ChannelPlugin&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-53:96:src/channels/plugins/types.plugin.ts" data-lang="53:96:src/channels/plugins/types.plugin.ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ChannelPlugin&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ResolvedAccount&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;any&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Probe &lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;unknown&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Audit &lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;unknown&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelId&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;meta&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelMeta&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;capabilities&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelCapabilities&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;defaults&lt;/span&gt;&lt;span style="color:#f92672"&gt;?:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;queue&lt;/span&gt;&lt;span style="color:#f92672"&gt;?:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;debounceMs?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reload&lt;/span&gt;&lt;span style="color:#f92672"&gt;?:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;configPrefixes&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[]; &lt;span style="color:#a6e22e"&gt;noopPrefixes?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[] };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setupWizard?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelPluginSetupWizard&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;config&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelConfigAdapter&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ResolvedAccount&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;configSchema?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelConfigSchema&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setup?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelSetupAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pairing?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelPairingAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;security?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelSecurityAdapter&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ResolvedAccount&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;groups?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelGroupAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mentions?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelMentionAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;outbound?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelOutboundAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;status?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelStatusAdapter&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ResolvedAccount&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Probe&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Audit&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;gatewayMethods?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;gateway?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelGatewayAdapter&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ResolvedAccount&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;auth?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelAuthAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;approvalCapability?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelApprovalCapability&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;elevated?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelElevatedAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;commands?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelCommandAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;lifecycle?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelLifecycleAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;secrets?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelSecretsAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;allowlist?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelAllowlistAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;doctor?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelDoctorAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;bindings?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelConfiguredBindingProvider&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;conversationBindings?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelConversationBindingSupport&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;streaming?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelStreamingAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;threading?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelThreadingAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;messaging?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelMessagingAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;agentPrompt?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelAgentPromptAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;directory?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelDirectoryAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resolver?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelResolverAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;actions?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelMessageActionAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;heartbeat?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelHeartbeatAdapter&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;agentTools?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;ChannelAgentToolFactory&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ChannelAgentTool&lt;/span&gt;[];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个接口一共有 &lt;strong&gt;40 多个可选的 adapter&lt;/strong&gt;，每个对应一种能力：&lt;/p&gt;</description></item><item><title>OpenClaw 源码导读（二）：Gateway 控制平面 — 一条 WebSocket 连上所有人</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-gateway%E6%8E%A7%E5%88%B6%E5%B9%B3%E9%9D%A2/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-gateway%E6%8E%A7%E5%88%B6%E5%B9%B3%E9%9D%A2/</guid><description>&lt;blockquote&gt;
&lt;p&gt;在系列第一篇里我们看到，OpenClaw 的核心隐喻是 &lt;strong&gt;&amp;ldquo;Gateway 是控制平面&amp;rdquo;&lt;/strong&gt;。它不存转储消息、不排队、不持久化事件流，而是一个长在 127.0.0.1:18789 上的&lt;strong&gt;状态化 RPC 服务器&lt;/strong&gt;，所有客户端（CLI、macOS.app、iOS/Android Node、WebChat 浏览器、Canvas iframe）都靠一条 WebSocket 接入。&lt;/p&gt;
&lt;p&gt;这一篇拆开控制平面的五个层面：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;进程入口&lt;/strong&gt;：CLI 怎么从 &lt;code&gt;openclaw gateway&lt;/code&gt; 走到 Node 进程常驻&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebSocket 协议&lt;/strong&gt;：握手帧、RPC 帧、Event 帧、状态快照与版本号&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;鉴权矩阵&lt;/strong&gt;：Token / Password / Device Token / Bootstrap Token / Tailscale Whois / Trusted Proxy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pairing&lt;/strong&gt;：陌生客户端怎么合法加入（setup code、pairing store、allowFrom）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session 模型&lt;/strong&gt;：Session Key 组成规则、多 Agent 路由、Session ID 模糊匹配&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;注：下文所有 &lt;code&gt;src/&lt;/code&gt; 路径都指 &lt;a href="https://github.com/openclaw/openclaw"&gt;openclaw/openclaw&lt;/a&gt; 仓库根下。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一cli-到-gateway-的六段路径"&gt;一、CLI 到 Gateway 的六段路径&lt;/h2&gt;
&lt;p&gt;第一篇概览过 &lt;code&gt;src/entry.ts&lt;/code&gt; 和 &lt;code&gt;src/cli/run-main.ts&lt;/code&gt;，这里按调用序重新画一遍，把每个关键函数在 graph 上标出来：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
A0["openclaw gateway --port 18789"] --&gt; A1
A1["entry.ts&lt;br/&gt;main guard + process.title"] --&gt; A2
A2["normalizeEnv + enableCompileCache()"] --&gt; A3
A3["ensureCliRespawnReady()&lt;br/&gt;按需 spawn 子 Node"] --&gt; A4
A4["parseCliContainerArgs&lt;br/&gt;parseCliProfileArgs"] --&gt; A5
A5["tryHandleRootVersionFastPath&lt;br/&gt;tryHandleRootHelpFastPath"] --&gt;|miss| A6
A6["runMainOrRootHelp → runCli(argv)"] --&gt; B0
B0["run-main.ts&lt;br/&gt;container? container in progress"] --&gt; B1
B1["loadCliDotEnv (~/.openclaw/.env)"] --&gt; B2
B2["assertSupportedRuntime (Node≥22.16)"] --&gt; B3
B3["tryRouteCli（fast-path 子命令路由）"] --&gt;|miss| B4
B4["buildProgram() + commander 注册"] --&gt; B5
B5["installUnhandledRejectionHandler"] --&gt; B6
B6["registerPluginCliCommandsFromValidatedConfig (lazy)"] --&gt; B7
B7["program.parseAsync"] --&gt; C0
C0["gateway 命令匹配 → gatewayCommandAction"] --&gt; C1
C1["lock 文件 + 端口 acquire"] --&gt; C2
C2["HTTP/WS server 启动"] --&gt; C3
C3["channels/plugins/cron/canvas-host 启动"] --&gt; C4["Ready"]
&lt;/pre&gt;
&lt;h3 id="1-为什么要自己-spawn-自己"&gt;1. 为什么要自己 &lt;code&gt;spawn&lt;/code&gt; 自己&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ensureCliRespawnReady()&lt;/code&gt; 是 &lt;code&gt;src/entry.ts&lt;/code&gt; 里最容易被忽视但非常重要的段落：&lt;/p&gt;</description></item><item><title>OpenClaw 源码导读（一）：架构总览 — 为"单个主人"而设计的 AI Gateway</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ai/openclaw-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/</guid><description>&lt;blockquote&gt;
&lt;p&gt;2025 年 11 月，&lt;a href="https://steipete.me"&gt;Peter Steinberger&lt;/a&gt;（PSPDFKit 创始人、前著名 iOS 社区人物）把自己折腾出来的个人 AI 助手 Molty 开源为 &lt;strong&gt;OpenClaw&lt;/strong&gt;。短短几个月，仓库吃到 35 万+ star、93 个 release、360 多个 contributor，核心代码量在 TypeScript/Swift/Kotlin/Go/Python 之间横跨 40 多万行。它和 Claude Code、Codex CLI 乍看都是&amp;quot;跑在本地的 CLI Agent&amp;quot;，但设计哲学完全不同——Claude Code 是一个&lt;strong&gt;编程助手&lt;/strong&gt;，OpenClaw 是一个长在你设备上的&lt;strong&gt;私人秘书&lt;/strong&gt;：它挂在 WhatsApp/Telegram/iMessage/微信 的 IM 客户端后面，能自己发消息、自己开浏览器、自己调用 iOS/Android 上的摄像头和麦克风。&lt;/p&gt;
&lt;p&gt;本文是 OpenClaw 源码导读系列的第一篇，目标是把整个项目的&amp;quot;地图&amp;quot;摊开。先讲清楚它要解决什么问题、在怎样的信任模型下运行，再把仓库 100 多个顶层模块拎出来分类，最后给出后续系列文章的导航。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一它到底是什么"&gt;一、它到底是什么&lt;/h2&gt;
&lt;h3 id="1-一句话定义"&gt;1. 一句话定义&lt;/h3&gt;
&lt;p&gt;OpenClaw 官方给自己的定位是 &lt;em&gt;&amp;ldquo;Personal AI Assistant. Any OS. Any Platform. The lobster way.&amp;rdquo;&lt;/em&gt; 翻译过来就是：&lt;strong&gt;一个在你自己设备上运行、从你自己现有的聊天工具里和你对话的个人 AI 助手&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这个定位里藏着三个关键差异：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Personal&lt;/strong&gt;：它不是多租户 SaaS，也不是团队协作工具，而是&lt;strong&gt;单一主人&lt;/strong&gt;的私人助手。整个信任模型就是为&amp;quot;只有一个 operator&amp;quot;优化的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Any OS / Any Platform&lt;/strong&gt;：Gateway 是 Node 进程，可以跑在 macOS/Linux/Windows(WSL2)、甚至 Fly.io/Docker/NAS 上；客户端包含 iOS/Android/macOS 原生 App，还有 Web Dashboard。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The lobster way&lt;/strong&gt;：作者把它拟人化成一只太空龙虾 Molty，这是一个品牌/吉祥物层面的设计，但也反映了项目的&amp;quot;玩心&amp;quot;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-和-claude-code-对比两个相似却完全不同的-cli-agent"&gt;2. 和 Claude Code 对比：两个相似却完全不同的 CLI Agent&lt;/h3&gt;
&lt;p&gt;由于作者 Steipete 本身是 Claude Code 的重度用户和 Anthropic 的合作者，社区最常问的问题就是&amp;quot;和 Claude Code 有啥区别&amp;quot;。这里先画一张对比表：&lt;/p&gt;</description></item><item><title>AITools</title><link>https://amatsuzero.github.io/LastStand/posts/mcp/</link><pubDate>Wed, 03 Jun 2026 09:03:11 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/mcp/</guid><description>&lt;h2 id="function-calling"&gt;Function Calling&lt;/h2&gt;
&lt;h3 id="21-要解决的问题"&gt;2.1 要解决的问题&lt;/h3&gt;
&lt;p&gt;传统聊天大模型只会说话，没有工具调用能力，这使得大模型：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;无法感知环境：无法与外部数据源交互，如通过 API 查询网页、查看用户本地文件、访问远程数据库等等&lt;/li&gt;
&lt;li&gt;无法改变环境：无法帮用户实际执行任务，如跑代码、发邮件、上传作业等&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="22-如何解决问题"&gt;2.2 如何解决问题&lt;/h3&gt;
&lt;h4 id="后端--llm-传统方案"&gt;后端 + LLM 传统方案&lt;/h4&gt;
&lt;h5 id="工作流程"&gt;工作流程&lt;/h5&gt;
&lt;p&gt;&lt;img alt="alt text" loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/mcp/tradition_way.png"&gt;&lt;/p&gt;
&lt;h5 id="存在的问题"&gt;存在的问题&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;是否调用工具、调用什么工具由后端负责判断，逻辑复杂且容易误判&lt;/strong&gt;。
AI 这么智能，为什么不让它来帮我判断？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调用工具的参数由后端负责构建，难度很大&lt;/strong&gt;。
AI 这么智能，为什么不让它来帮我生成参数？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;广义的 Function Calling&lt;/strong&gt; 是指让大模型能够调用外部工具的一种技术实现：先向大模型提供可用函数的列表及说明，由大模型在对话过程中智能判断是否需要调用函数，并自动生成调用所需的参数，最终用文字返回符合约定格式的函数调用请求。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;狭义的 Function Calling&lt;/strong&gt; 特指大模型提供商在模型内部与 API 层面做了支持的一种能力，它最早由 OpenAI 引入：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在模型层面：模型提供商需对大模型进行特别优化，使其具备根据上下文正确选择合适函数、生成有效参数的能力（比如有监督微调、强化学习）。&lt;/li&gt;
&lt;li&gt;在 API 层面：模型提供商需额外开放对 Function Calling 的支持（比如 GPT API 中提供了一个 &lt;code&gt;functions&lt;/code&gt; 参数）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="function-calling-方案"&gt;Function Calling 方案&lt;/h3&gt;
&lt;h4 id="基于提示词的-function-calling"&gt;基于提示词的 Function Calling&lt;/h4&gt;
&lt;h5 id="工作流程-1"&gt;工作流程&lt;/h5&gt;
&lt;p&gt;&lt;img alt="alt text" loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/mcp/function_call_based_on_prompt.png"&gt;&lt;/p&gt;
&lt;details class="md-details"&gt;
&lt;summary&gt;System Prompt 示例&lt;/summary&gt;
&lt;div class="md-details-body"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;System Prompt 示例
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# 你的角色
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;你是一个函数调用助手，我将提供多个函数的定义信息，包括函数名称、作用、参数及参数类型。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# 你的任务
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 根据用户的输入，判断是否需要调用某个函数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 如果需要，请**严格按照以下格式**输出函数调用指令：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{ &amp;#34;name&amp;#34;: &amp;#34;函数名&amp;#34;, &amp;#34;arguments&amp;#34;: { &amp;#34;参数名&amp;#34;: &amp;#34;参数值&amp;#34; } }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# 函数定义信息
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. **get_weather**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 作用：查询指定城市的天气情况
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 参数：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -`city`（string）：城市名称
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. **get_time**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 作用：查询指定城市的当前时间
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 参数：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - `city`（string）：城市名称
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;h5 id="存在的问题-1"&gt;存在的问题&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;输出格式不稳定。如调用指令中存在多余自然语言。&lt;/li&gt;
&lt;li&gt;容易出现幻觉。模型可能编造并不存在的函数名或参数。
大模型提供商能否对模型进行微调、强化学习，提升大模型在这一方面的能力？&lt;/li&gt;
&lt;li&gt;对开发者依赖度高。函数描述、调用指令格式、提示词逻辑完全由开发者设计。
函数描述、调用指令格式能否由大模型提供商来指定？系统提示词中的&amp;quot;说明与规则&amp;quot;逻辑能否由大模型提供商来兜底？&lt;/li&gt;
&lt;li&gt;上下文冗长，Token 消耗大。为确保调用逻辑正确，往往需要在 system prompt 中加入大量说明与规则。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="基于-api-的-function-calling"&gt;基于 API 的 Function Calling&lt;/h4&gt;
&lt;h5 id="工作流程-2"&gt;工作流程&lt;/h5&gt;
&lt;p&gt;&lt;img alt="alt text" loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/mcp/function_call_based_on_api.png"&gt;&lt;/p&gt;</description></item></channel></rss>