<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux on 小盒子的技术分享</title><link>https://xiaobox.github.io/tags/linux/</link><description>Recent content in Linux on 小盒子的技术分享</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 11 Mar 2026 10:14:30 +0000</lastBuildDate><atom:link href="https://xiaobox.github.io/tags/linux/index.xml" rel="self" type="application/rss+xml"/><item><title>OpenClaw 爆火背后：它不是聊天机器人，而是一套真正会做事的 AI 系统</title><link>https://xiaobox.github.io/p/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/</link><pubDate>Wed, 11 Mar 2026 10:14:30 +0000</pubDate><guid>https://xiaobox.github.io/p/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/cover.jpg" alt="Featured image of post OpenClaw 爆火背后：它不是聊天机器人，而是一套真正会做事的 AI 系统" /&gt;&lt;p&gt;如果你最近在 GitHub 上关注过 AI Agent 领域，大概率已经看到过 OpenClaw。到 2026 年 3 月 10 日，它的 GitHub 仓库已经来到约 297k stars，超过了 React 的约 244k 和 Linux 的约 222k。更重要的不是数字本身，而是它火起来的方式：它不是靠一个漂亮网页，也不是靠一个“会聊天的套壳”，而是靠一整套&lt;strong&gt;把大模型接入真实消息渠道、真实设备、真实浏览器、真实文件系统的系统架构&lt;/strong&gt;，硬生生把“AI 助手”做成了一个长期在线的工程系统。&lt;/p&gt;
&lt;p&gt;但如果你只把 OpenClaw 理解成“接了很多 IM 的机器人”，你会完全错过它最有价值的部分。OpenClaw 官方 README 写得很直白：“&lt;strong&gt;The Gateway is just the control plane — the product is the assistant.&lt;/strong&gt;” 这句话几乎就是读懂整个项目的钥匙。它的重点从来不是“有多少入口”，而是：&lt;strong&gt;有没有一个统一控制面，把消息、状态、路由、模型、工具、节点、权限和安全边界收在一起&lt;/strong&gt;。 README、架构文档和 Vision 文档都在强调同一件事：OpenClaw 想做的是“真正会做事的 AI”，运行在你的设备、你的渠道、你的规则之内。&lt;/p&gt;
&lt;p&gt;这篇文章，我想尽量回答七个问题：&lt;/p&gt;
&lt;p&gt;1.它到底是什么？&lt;/p&gt;
&lt;p&gt;2.它为什么会采用现在这套架构？&lt;/p&gt;
&lt;p&gt;3.Gateway 到底在系统里扮演什么角色？&lt;/p&gt;
&lt;p&gt;4.Agent 是怎么运行起来的？&lt;/p&gt;
&lt;p&gt;5.Memory、Workspace、Session 为什么是它的关键设计？&lt;/p&gt;
&lt;p&gt;6.多 Agent、节点、工具体系是怎么拼到一起的？&lt;/p&gt;
&lt;p&gt;7.以及最后，为什么它值得被看作下一代 AI 助手的典型系统样本。&lt;/p&gt;
&lt;p&gt;在回答这些问题之前，我不得不说，现在龙虾有些过热了，对于想 “卖铲子” 的公司当然觉得这是好事，于是他们推波助澜，但对于专业人士不能人云亦云。openClaw 有它优秀的一面，也有被炒作夸大的一面，应该客观地看。&lt;/p&gt;
&lt;h2 id="一openclaw-的本质不是聊天机器人而是个人-ai-助手控制面"&gt;&lt;a href="#%e4%b8%80openclaw-%e7%9a%84%e6%9c%ac%e8%b4%a8%e4%b8%8d%e6%98%af%e8%81%8a%e5%a4%a9%e6%9c%ba%e5%99%a8%e4%ba%ba%e8%80%8c%e6%98%af%e4%b8%aa%e4%ba%ba-ai-%e5%8a%a9%e6%89%8b%e6%8e%a7%e5%88%b6%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;一、OpenClaw 的本质，不是聊天机器人，而是“个人 AI 助手控制面”
&lt;/h2&gt;&lt;p&gt;一句话定义 OpenClaw，我会这样说：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OpenClaw = 一个以 Gateway 为中心的个人 AI 助手控制平面，下面挂着嵌入式 agent runtime、会话系统、工具系统、消息渠道、节点设备和安全边界。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个定义不是我自己拔高出来的，而是官方文档本身就在往这个方向写。&lt;/p&gt;
&lt;p&gt;●README 说它是“你运行在自己设备上的 personal AI assistant”；&lt;/p&gt;
&lt;p&gt;●架构文档说它是一个 single long-lived Gateway，拥有所有 messaging surfaces；&lt;/p&gt;
&lt;p&gt;●Vision 文档则把它描述为“the AI that actually does things”，运行在你的设备、你的渠道、你的规则里。&lt;/p&gt;
&lt;p&gt;把这些信息放在一起看，你会发现 OpenClaw 的设计起点根本不是一个“聊天 UI”，而是一个&lt;strong&gt;长期在线、可被多入口触发、可调用工具、可连接设备、可持续维护状态的 AI 系统。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/001-edb50d9b.png"&gt;&lt;/p&gt;
&lt;p&gt;这也是为什么我认为 OpenClaw 更接近“控制面”而不是“应用层”。在很多 AI 产品里，用户打开网页，输入问题，后端调一下模型，返回一段文本，交互就结束了。OpenClaw 则完全不是这种形态。它默认有一个长期运行的 Gateway 进程，消息渠道接到这个 Gateway，上层的 CLI、Control UI、WebChat 接这个 Gateway，macOS/iOS/Android/headless 节点也接这个 Gateway，甚至定时任务、exec approvals、pairing 和 health 事件都围绕 Gateway 展开。也就是说，&lt;strong&gt;Gateway 不是一个消息转发器，而是系统中枢。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/002-4ba00a5d.png"&gt;&lt;/p&gt;
&lt;h2 id="二gateway-为什么是-openclaw-最关键的设计"&gt;&lt;a href="#%e4%ba%8cgateway-%e4%b8%ba%e4%bb%80%e4%b9%88%e6%98%af-openclaw-%e6%9c%80%e5%85%b3%e9%94%ae%e7%9a%84%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;二、Gateway 为什么是 OpenClaw 最关键的设计
&lt;/h2&gt;&lt;p&gt;OpenClaw 官方架构文档里最重要的一句话，是它把 Gateway 明确成 &lt;strong&gt;single control plane&lt;/strong&gt;。一个长期运行的 Gateway 拥有所有 messaging surfaces；control-plane clients 通过 WebSocket 连进来；nodes 也通过 WebSocket 连进来，但会声明自己是 &lt;code&gt;role: node&lt;/code&gt;；Canvas host 也由 Gateway 的 HTTP server 提供，而且默认和 Gateway 共用 127.0.0.1:18789 这个端口。&lt;/p&gt;
&lt;p&gt;这意味着什么？意味着 OpenClaw 的系统设计不是“每个端各做一套逻辑”，而是“先做一个统一控制面，再让所有端接入它”。这在工程上有三个非常大的好处。&lt;/p&gt;
&lt;p&gt;第一，&lt;strong&gt;状态是统一的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;会话在哪里维护？在 Gateway。&lt;/p&gt;
&lt;p&gt;路由在哪里决策？在 Gateway。&lt;/p&gt;
&lt;p&gt;设备配对、认证 token、事件广播、健康状态、cron、工具审批在哪里收敛？还是在 Gateway。&lt;/p&gt;
&lt;p&gt;这让系统不会因为前端入口变多而出现多套状态、多个事实来源。&lt;/p&gt;
&lt;p&gt;第二，&lt;strong&gt;协议是统一的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Gateway protocol 文档明确写了：OpenClaw 不是“随便传一段 JSON”，而是有明确握手流程和版本约束的 WebSocket 协议。服务端先发 &lt;code&gt;connect.challenge&lt;/code&gt;，客户端再带着 &lt;code&gt;device identity&lt;/code&gt;、&lt;code&gt;role&lt;/code&gt;、&lt;code&gt;scopes&lt;/code&gt;、&lt;code&gt;caps&lt;/code&gt;、&lt;code&gt;auth&lt;/code&gt;、签名等参数发起 connect，通过后才返回 hello-ok。协议版本有 minProtocol/maxProtocol 协商，协议 schema 由 TypeBox 定义，再生成 JSON Schema 以及 Swift model。对一个跨 CLI、网页、桌面、移动端、节点设备的系统来说，这种 typed protocol 的价值非常高。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/003-1f7f4ec8.png"&gt;&lt;/p&gt;
&lt;p&gt;第三，&lt;strong&gt;能力是统一暴露的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;比如 Control UI 不是一个独立后端，而是 Gateway 在同一端口上提供的浏览器管理界面；WebChat 直接连 Gateway WebSocket；nodes 也不是第二套服务，而是带 &lt;code&gt;role:node&lt;/code&gt; 的外围设备。也就是说，OpenClaw 并不是“一个 App + 一堆外挂”，而是“一个控制面 + 多个表面”。&lt;/p&gt;
&lt;p&gt;很多人第一次看 OpenClaw，会把注意力放在“它居然支持这么多渠道”。但真正懂架构的人，会先看 Gateway。因为能不能把多个入口、多种设备、多条事件流、多种工具执行方式，全都压到一个长期运行的控制面里，决定了它到底是“一个功能”还是“一个系统”。OpenClaw 的做法很明确：&lt;strong&gt;先有控制面，再有助手&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="三它最强的抽象不是对话框而是-agentsession-和-route"&gt;&lt;a href="#%e4%b8%89%e5%ae%83%e6%9c%80%e5%bc%ba%e7%9a%84%e6%8a%bd%e8%b1%a1%e4%b8%8d%e6%98%af%e5%af%b9%e8%af%9d%e6%a1%86%e8%80%8c%e6%98%af-agentsession-%e5%92%8c-route" class="header-anchor"&gt;&lt;/a&gt;三、它最强的抽象，不是对话框，而是 Agent、Session 和 Route
&lt;/h2&gt;&lt;p&gt;很多 AI 产品最基础的抽象单位是“聊天窗口”。OpenClaw 不是。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/004-717935e1.png"&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 的真正基础模型，是：&lt;/p&gt;
&lt;p&gt;●&lt;strong&gt;谁来回复（Agent）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;●&lt;strong&gt;回复落在哪段连续上下文里（Session）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;●&lt;strong&gt;一条消息应该被路由到哪个 agent 和哪个 session（Route）&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="agent一颗完整隔离的大脑"&gt;&lt;a href="#agent%e4%b8%80%e9%a2%97%e5%ae%8c%e6%95%b4%e9%9a%94%e7%a6%bb%e7%9a%84%e5%a4%a7%e8%84%91" class="header-anchor"&gt;&lt;/a&gt;Agent：一颗完整隔离的大脑
&lt;/h3&gt;&lt;p&gt;Multi-Agent 文档里写得很清楚：一个 agent 是一个 &lt;strong&gt;fully scoped brain&lt;/strong&gt;，拥有&lt;/p&gt;
&lt;p&gt;●自己的 workspace&lt;/p&gt;
&lt;p&gt;●自己的 agentDir&lt;/p&gt;
&lt;p&gt;●自己的 auth profiles&lt;/p&gt;
&lt;p&gt;●自己的 session store&lt;/p&gt;
&lt;p&gt;它的文件、人格、配置、认证信息和会话历史都是围绕这个 agent 单独组织的。默认路径也很清晰：&lt;/p&gt;
&lt;p&gt;●workspace 在 &lt;code&gt;~/.openclaw/workspace&lt;/code&gt; 或 &lt;code&gt;workspace-&amp;lt;agentId&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;●session 存在 &lt;code&gt;~/.openclaw/agents/&amp;lt;agentId&amp;gt;/sessions&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;●auth profile 在 &lt;code&gt;~/.openclaw/agents/&amp;lt;agentId&amp;gt;/agent/auth-profiles.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这件事非常重要。因为这说明 OpenClaw 的多 Agent，不是“在一个上下文里换不同 system prompt 假装多人格”，而是&lt;strong&gt;真的把状态、身份、凭证和工作目录做成了隔离单元&lt;/strong&gt;。但要注意，这种独立是为了让系统跑得更有条理，属于“防君子不防小人”的内部隔离。官方的意思很明确：同一个网关（Gateway）里的 Agent 默认都是“自己人”，不能把互不信任、甚至带有敌意的任务强行塞进同一个网关里，它并没有提供那种级别的安全防御。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/005-b96b6812.png"&gt;&lt;/p&gt;
&lt;h3 id="session上下文连续性的主键"&gt;&lt;a href="#session%e4%b8%8a%e4%b8%8b%e6%96%87%e8%bf%9e%e7%bb%ad%e6%80%a7%e7%9a%84%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;Session：上下文连续性的主键
&lt;/h3&gt;&lt;p&gt;Session 文档里有一句特别关键的话：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;OpenClaw treats one direct-chat session per agent as primary.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;这句话可以理解成：&lt;strong&gt;对每一个 agent，OpenClaw 都认为它有一个“主私聊会话”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 默认会将一个 Agent 接收到的所有私聊（Direct Message, DM）都汇聚到一个主会话里（即 &lt;code&gt;agent:&amp;lt;agentId&amp;gt;:&amp;lt;mainKey&amp;gt;&lt;/code&gt;）。对于群聊、频道或特定的话题（Thread），则会自动拆分独立处理。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;对于 direct chat， agent 有一个规范意义上的主会话；默认所有 DM 都往这里归并，以保证连续性。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;假设你有一个 agent 叫 main。默认情况下：&lt;/p&gt;
&lt;p&gt;●你在 Web UI 私聊它一次&lt;/p&gt;
&lt;p&gt;●之后又在 CLI 私聊它&lt;/p&gt;
&lt;p&gt;●再后来在手机端私聊它&lt;/p&gt;
&lt;p&gt;如果这些都被识别为 direct chat，而且你没有改 session.dmScope，那么这些私聊会折叠进同一个主 session,这样做的好处是：&lt;strong&gt;agent 会把这些私聊视为同一条连续对话，而不是三个彼此割裂的会话&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;默认的主会话机制在单用户场景下很完美，但在&lt;strong&gt;多用户场景&lt;/strong&gt;下就是一个巨大的安全漏洞。&lt;/p&gt;
&lt;p&gt;如果 Alice 和 Bob 都去私聊同一个 Agent，在默认配置下，他们实际上是在向同一个“上下文沙箱”里写入数据。这就好比两个人共用一个日记本：&lt;/p&gt;
&lt;p&gt;●Alice 刚和 Agent 聊完财务密码。&lt;/p&gt;
&lt;p&gt;●Bob 接着去问 Agent“我们刚才聊了什么？”&lt;/p&gt;
&lt;p&gt;●Agent 就会直接把 Alice 的密码复述给 Bob，造成严重的信息泄露。&lt;/p&gt;
&lt;p&gt;为了应对多用户场景，OpenClaw 提供了 &lt;code&gt;session.dmScope&lt;/code&gt; 配置，允许你在架构层面把私聊的上下文切分成更安全的细粒度：&lt;/p&gt;
&lt;p&gt;●按发信人隔离（&lt;code&gt;per-peer&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;●按频道+发信人隔离。(&lt;code&gt;per-channel-peer&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;●按账号+频道+发信人隔离(&lt;code&gt;per-account-channel-peer&lt;/code&gt;)。&lt;/p&gt;
&lt;p&gt;⚠️ 如果你在开发面向多用户的 AI Agent，&lt;strong&gt;绝对不能盲目使用默认的私聊配置&lt;/strong&gt;。必须根据业务需求，通过调整 &lt;code&gt;dmScope&lt;/code&gt; 将用户的对话状态彻底隔离开，防止你的 Agent 变成一个没有隐私边界的“大喇叭”。&lt;/p&gt;
&lt;h3 id="route决定消息进入哪颗大脑"&gt;&lt;a href="#route%e5%86%b3%e5%ae%9a%e6%b6%88%e6%81%af%e8%bf%9b%e5%85%a5%e5%93%aa%e9%a2%97%e5%a4%a7%e8%84%91" class="header-anchor"&gt;&lt;/a&gt;Route：决定消息进入哪颗大脑
&lt;/h3&gt;&lt;p&gt;Channel Routing 文档把消息路由规则写得非常明确，一条消息发过来，绝对不是“哪个 Agent 闲着就扔给谁”，而是像网关（Gateway）匹配规则一样，必须严格按照优先级一层层往下筛，直到找到唯一确定的接收者。&lt;/p&gt;
&lt;p&gt;我们可以用**“公司收发室分拣快递”**来打个比方，看一下这 5 层降级（Fallback）匹配规则：&lt;/p&gt;
&lt;p&gt;1.&lt;strong&gt;精准单聊 (Exact peer match)&lt;/strong&gt;：快递单上写着“直接交到张三本人手里”。&lt;/p&gt;
&lt;p&gt;○明确的点对点直接交互，优先级最高。&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;跟帖/线程继承 (Parent peer match)&lt;/strong&gt;：快递单没写名字，但备注了“这是昨天那个加急件的补充材料”。收发室一查昨天是李四负责的，直接给李四。&lt;/p&gt;
&lt;p&gt;○识别 Thread 或上下文，让同一个 Agent 连贯处理同一个话题。&lt;/p&gt;
&lt;p&gt;3.&lt;strong&gt;平台级群组与角色 (Discord guild+roles / Slack team)&lt;/strong&gt;：快递写着“给财务部经理”或“给核心开发组”。&lt;/p&gt;
&lt;p&gt;○根据外部平台（如 Discord/Slack）的特定权限组或大团队来分配对应的 Agent。&lt;/p&gt;
&lt;p&gt;4.&lt;strong&gt;账号与频道 (Account / Channel)&lt;/strong&gt;：快递写着“送到 3 楼会议室”或“交给官方客服号”。&lt;/p&gt;
&lt;p&gt;○匹配特定的聊天频道或绑定的公共账号。&lt;/p&gt;
&lt;p&gt;5.&lt;strong&gt;默认兜底 (Default agent)&lt;/strong&gt;：啥也没写清楚的无主件，统统扔给“前台总机”处理。&lt;/p&gt;
&lt;p&gt;○如果上面所有条件都未命中，最后由默认的 Agent 统一接管。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/006-a89a97a1.png"&gt;&lt;/p&gt;
&lt;p&gt;这意味着 OpenClaw 的“消息归属”不是模糊的。一条消息不是“谁在线谁回”，而是经过一套确定性规则，先判定该由哪个 agent 接管，再决定落到哪个 session 里。&lt;/p&gt;
&lt;p&gt;所以 OpenClaw 能天然处理这些现实世界场景：&lt;/p&gt;
&lt;p&gt;●同一个 Gateway 托管多个 agent；&lt;/p&gt;
&lt;p&gt;●一个 Telegram 群给 work agent；&lt;/p&gt;
&lt;p&gt;●一个 WhatsApp 家庭群给 family agent；&lt;/p&gt;
&lt;p&gt;●一个 Slack team 给 support agent；&lt;/p&gt;
&lt;h2 id="四agent-不是外挂调用而是嵌入式运行时"&gt;&lt;a href="#%e5%9b%9bagent-%e4%b8%8d%e6%98%af%e5%a4%96%e6%8c%82%e8%b0%83%e7%94%a8%e8%80%8c%e6%98%af%e5%b5%8c%e5%85%a5%e5%bc%8f%e8%bf%90%e8%a1%8c%e6%97%b6" class="header-anchor"&gt;&lt;/a&gt;四、Agent 不是外挂调用，而是嵌入式运行时
&lt;/h2&gt;&lt;p&gt;很多人对 OpenClaw 最大的误解，是把它当成了一个简单的“任务调度员”——以为它只是在收到消息时，拉起一个外部的子进程（Subprocess）去跑一下，或者通过接口（RPC）远程调一下就完事了。&lt;/p&gt;
&lt;p&gt;但架构文档明确指出：OpenClaw 是将 Agent 运行时“原生内嵌”到自己的网关里的。 它不是把 Agent 当作一个不可控的外部黑盒，而是直接在内部实例化 Agent 的核心会话（AgentSession）。&lt;/p&gt;
&lt;p&gt;Pi Integration Architecture 文档写得非常明确：OpenClaw &lt;strong&gt;不是&lt;/strong&gt; 把 pi 作为 subprocess 或 RPC mode 的外部黑盒去调用，而是直接导入并实例化 pi 的 AgentSession，通过 createAgentSession() 把 agent runtime 嵌入 到自己的消息网关架构里。&lt;/p&gt;
&lt;p&gt;这种“深度内嵌”的架构设计，直接赋予了系统 6 大核心优势：&lt;/p&gt;
&lt;p&gt;1.&lt;strong&gt;全局生命周期掌控&lt;/strong&gt;： 从对话的创建、挂起、恢复到销毁，网关层拥有绝对的控制权。&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;动态能力扩展&lt;/strong&gt;： 可以在运行时，随时把自定义的外部工具“塞”给 Agent 使用。&lt;/p&gt;
&lt;p&gt;3.&lt;strong&gt;“看人下菜碟”的人设&lt;/strong&gt;： 能够根据消息来源（不同的平台渠道或上下文），动态切换 Agent 的系统提示词。&lt;/p&gt;
&lt;p&gt;4.&lt;strong&gt;强悍的记忆管理&lt;/strong&gt;： 不仅能持久化保存对话，还支持高级的“记忆压缩（Compaction）”防止上下文爆满，甚至支持像 Git 一样对对话“开分支（Branching）”。&lt;/p&gt;
&lt;p&gt;5.&lt;strong&gt;智能凭证轮询&lt;/strong&gt;： 在多个账号或 API Key 之间自动无缝切换，轻松应对并发和限流问题。&lt;/p&gt;
&lt;p&gt;6.&lt;strong&gt;模型厂商解绑&lt;/strong&gt;： 底层的大模型想换就换，完全不受单一服务商（如 OpenAI、Anthropic）的绑架。&lt;/p&gt;
&lt;p&gt;简单来说，OpenClaw 走的是“直接收编”的路线，它把 Agent 的核心大脑直接“拔”过来，原生种植在了自己的神经中枢里。这就好比你不再是打电话咨询外部专家，而是直接把这位专家招进了自家的核心指挥部。正因为“人”彻底成了内部员工，你才能拥有上帝视角般的掌控力：你可以全面接管他的作息安排（会话生命周期），随时往他手里塞各种定制兵器（动态注入工具），根据不同场合要求他扮演不同的角色（按渠道切换提示词），像操作代码仓库一样去整理甚至分叉他的记忆（支持压缩与分支的持久化），甚至连他背后的“脑力供应商”（随时无缝切换各家大模型）和权限账号，都能在底层悄无声息地替他自动轮换。说白了，OpenClaw 不是在和 Agent “跨部门合作”，而是直接把 Agent 融为了自己身体的一部分。换句话说，&lt;strong&gt;OpenClaw 不是“在用一个 agent”，而是“在拥有一个 agent runtime，并把它纳入自己的控制面”。这也是它跟很多“外接 Agent SDK 的应用层产品”最大的差别之一。别人只是调用，OpenClaw 是接管&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/007-b6154044.png"&gt;&lt;/p&gt;
&lt;h2 id="五agent-loop一条消息的真实旅程"&gt;&lt;a href="#%e4%ba%94agent-loop%e4%b8%80%e6%9d%a1%e6%b6%88%e6%81%af%e7%9a%84%e7%9c%9f%e5%ae%9e%e6%97%85%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;五、Agent Loop：一条消息的&amp;quot;真实旅程&amp;quot;
&lt;/h2&gt;&lt;p&gt;前面我们讲了 Gateway 如何把消息路由到正确的 Agent。现在让我们跟随一条消息，看看它进入 OpenClaw 后，到底经历了什么。&lt;/p&gt;
&lt;h3 id="不是一次请求而是一个完整生命周期"&gt;&lt;a href="#%e4%b8%8d%e6%98%af%e4%b8%80%e6%ac%a1%e8%af%b7%e6%b1%82%e8%80%8c%e6%98%af%e4%b8%80%e4%b8%aa%e5%ae%8c%e6%95%b4%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f" class="header-anchor"&gt;&lt;/a&gt;不是&amp;quot;一次请求&amp;quot;，而是一个完整生命周期
&lt;/h3&gt;&lt;p&gt;如果你习惯了网页聊天框的&amp;quot;发消息→等回复&amp;quot;模式，OpenClaw 的处理方式会让你有点意外。&lt;/p&gt;
&lt;p&gt;传统模式：&lt;/p&gt;
&lt;p&gt;⚡ 代码片段&lt;code&gt;用户发消息 → 后端调用模型 → 返回文本 → 结束&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 模式：&lt;/p&gt;
&lt;p&gt;⚡ 代码片段&lt;code&gt;用户发消息 → 分配 runId → 解析 session → 装配上下文 → 运行 agent → 流式返回事件 → 持久化 session → 结束&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这一条链路，实际上就是你给 OpenClaw 发一句话之后，系统内部真实发生的事情。它不是“一次 HTTP 请求”，而是一个完整的运行生命周期。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/008-b98e49e5.png"&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 把你的消息视为一个&lt;strong&gt;进程而非请求&lt;/strong&gt;。它会给这个进程分配ID、监控生命周期、管理并发、持久化状态。&lt;/p&gt;
&lt;h3 id="并发控制为什么同一聊天窗口的消息要排队"&gt;&lt;a href="#%e5%b9%b6%e5%8f%91%e6%8e%a7%e5%88%b6%e4%b8%ba%e4%bb%80%e4%b9%88%e5%90%8c%e4%b8%80%e8%81%8a%e5%a4%a9%e7%aa%97%e5%8f%a3%e7%9a%84%e6%b6%88%e6%81%af%e8%a6%81%e6%8e%92%e9%98%9f" class="header-anchor"&gt;&lt;/a&gt;并发控制：为什么同一聊天窗口的消息要&amp;quot;排队&amp;quot;？
&lt;/h3&gt;&lt;p&gt;想象一下这个场景：你在 Telegram 连续发了三条消息：&lt;/p&gt;
&lt;p&gt;●“帮我查一下明天天气”&lt;/p&gt;
&lt;p&gt;●“顺便看看日程”&lt;/p&gt;
&lt;p&gt;●“把第一封邮件标为已读”&lt;/p&gt;
&lt;p&gt;如果这三条消息并发执行，会发生什么？&lt;/p&gt;
&lt;p&gt;●Agent 可能先处理了邮件，再处理天气&lt;/p&gt;
&lt;p&gt;●Session 历史会乱序写入&lt;/p&gt;
&lt;p&gt;●工具调用可能互相冲突&lt;/p&gt;
&lt;p&gt;OpenClaw 的解决方案很简单：每个 session 串行化执行。这不是性能问题，而是状态一致性问题。长期在线的助手，必须保证&amp;quot;记忆&amp;quot;不会被乱序操作搞乱。是&lt;strong&gt;防止工具竞争和状态污染&lt;/strong&gt;的工程必要选择。&lt;/p&gt;
&lt;h3 id="流式事件你看到的不是打字动画而是真实的工作过程"&gt;&lt;a href="#%e6%b5%81%e5%bc%8f%e4%ba%8b%e4%bb%b6%e4%bd%a0%e7%9c%8b%e5%88%b0%e7%9a%84%e4%b8%8d%e6%98%af%e6%89%93%e5%ad%97%e5%8a%a8%e7%94%bb%e8%80%8c%e6%98%af%e7%9c%9f%e5%ae%9e%e7%9a%84%e5%b7%a5%e4%bd%9c%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;流式事件：你看到的不是&amp;quot;打字动画&amp;quot;，而是真实的工作过程
&lt;/h3&gt;&lt;p&gt;OpenClaw 的流式输出，不是简单的&amp;quot;逐字显示&amp;quot;，而是三种事件流：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/009-19119b2c.png"&gt;&lt;/p&gt;
&lt;p&gt;为什么要这样设计？ 因为这让用户能真正&amp;quot;看到 AI 在工作&amp;quot;。不是动画，不是假进度条，而是系统内部真实发生的事件被推送到前端。它的体验更像一个&amp;quot;正在办公的助手&amp;quot;而非&amp;quot;死寂的输入框&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/010-67135bf9.png"&gt;&lt;/p&gt;
&lt;h2 id="六真正让它像一个人的不是模型而是-workspacesystem-prompt-和-memory"&gt;&lt;a href="#%e5%85%ad%e7%9c%9f%e6%ad%a3%e8%ae%a9%e5%ae%83%e5%83%8f%e4%b8%80%e4%b8%aa%e4%ba%ba%e7%9a%84%e4%b8%8d%e6%98%af%e6%a8%a1%e5%9e%8b%e8%80%8c%e6%98%af-workspacesystem-prompt-%e5%92%8c-memory" class="header-anchor"&gt;&lt;/a&gt;六、真正让它“像一个人”的，不是模型，而是 Workspace、System Prompt 和 Memory
&lt;/h2&gt;&lt;p&gt;很多人体验 OpenClaw 后会有一种明显感觉：它比普通网页聊天更像一个“持续存在的助手”。这种感觉，核心不是来自模型，而是来自它对&lt;strong&gt;工作区、提示词和记忆&lt;/strong&gt;的系统化设计&lt;/p&gt;
&lt;h3 id="workspaceai-的家而不是一个临时目录"&gt;&lt;a href="#workspaceai-%e7%9a%84%e5%ae%b6%e8%80%8c%e4%b8%8d%e6%98%af%e4%b8%80%e4%b8%aa%e4%b8%b4%e6%97%b6%e7%9b%ae%e5%bd%95" class="header-anchor"&gt;&lt;/a&gt;Workspace：AI 的家，而不是一个临时目录
&lt;/h3&gt;&lt;p&gt;简单说，Workspace 就是 AI 的&amp;quot;家&amp;quot;：&lt;/p&gt;
&lt;p&gt;●它有固定的位置（~/.openclaw/workspace/）&lt;/p&gt;
&lt;p&gt;●它有固定的文件结构&lt;/p&gt;
&lt;p&gt;●它是 AI 长期工作的地方，不是临时落脚点&lt;/p&gt;
&lt;p&gt;OpenClaw 在 Workspace 里约定了一整套&amp;quot;说明书文件&amp;quot;：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/011-71f8b973.png"&gt;&lt;/p&gt;
&lt;p&gt;这个设计特别妙。因为它把很多系统会偷偷塞进 prompt 模板或数据库里的东西，变成了&lt;strong&gt;用户可见、可读、可改、可备份&lt;/strong&gt;的文件系统资产。你不是在“配一个人设”，而是在维护一个 AI 的长期工作环境。&lt;/p&gt;
&lt;p&gt;这里有一个非常重要的提醒：&lt;strong&gt;workspace 是默认工作目录，但不是硬沙箱（hard sandbox）；相对路径默认在 workspace 内解析，但绝对路径仍可能访问宿主机其它位置，除非你开启 sandbox。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="system-prompt每次运行都在编译上下文"&gt;&lt;a href="#system-prompt%e6%af%8f%e6%ac%a1%e8%bf%90%e8%a1%8c%e9%83%bd%e5%9c%a8%e7%bc%96%e8%af%91%e4%b8%8a%e4%b8%8b%e6%96%87" class="header-anchor"&gt;&lt;/a&gt;System Prompt：每次运行都在&amp;quot;编译上下文&amp;quot;
&lt;/h3&gt;&lt;p&gt;OpenClaw 不是把用户的问题直接扔给模型，而是每次都重新构建一份完整的上下文：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ 代码片段System Prompt 结构：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;├── Tooling（可用工具列表）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;├── Safety（安全规则）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;├── Skills（技能列表）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;├── Workspace Context（工作区文件）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;├── Documentation（相关文档）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;├── Current Date &amp;amp; Time（当前时间）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;└── Runtime（运行环境信息）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Context 文档还补充了细节：默认会把 AGENTS.md、SOUL.md、TOOLS.md、IDENTITY.md、USER.md、HEARTBEAT.md、BOOTSTRAP.md 等文件作为 Project Context 注入系统提示；技能本身只会注入“技能列表和描述”，真正的 SKILL.md 需要模型按需读取。&lt;/p&gt;
&lt;p&gt;类比：&lt;/p&gt;
&lt;p&gt;●传统聊天：像&amp;quot;临时起意打电话&amp;quot;&lt;/p&gt;
&lt;p&gt;●OpenClaw：像&amp;quot;开会前先发会议议程和背景资料&amp;quot;&lt;/p&gt;
&lt;h3 id="memory真正写到磁盘才算记住"&gt;&lt;a href="#memory%e7%9c%9f%e6%ad%a3%e5%86%99%e5%88%b0%e7%a3%81%e7%9b%98%e6%89%8d%e7%ae%97%e8%ae%b0%e4%bd%8f" class="header-anchor"&gt;&lt;/a&gt;Memory：真正写到磁盘，才算记住
&lt;/h3&gt;&lt;p&gt;Memory 文档里我最喜欢的一句话是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;The files are the source of truth; the model only “remembers” what gets written to disk.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;OpenClaw 默认的记忆结构非常简单，但非常工程化:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ 代码片段workspace/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; ├── memory/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; │ ├── 2026-03-10.md ← 今天的日志
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; │ ├── 2026-03-09.md ← 昨天的日志
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; │ └── ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; └── MEMORY.md ← 长期、精炼的永久记忆
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;两种记忆的区别：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/012-105dfd4a.png"&gt;&lt;/p&gt;
&lt;h3 id="检索机制不是只有文件也不是只有向量"&gt;&lt;a href="#%e6%a3%80%e7%b4%a2%e6%9c%ba%e5%88%b6%e4%b8%8d%e6%98%af%e5%8f%aa%e6%9c%89%e6%96%87%e4%bb%b6%e4%b9%9f%e4%b8%8d%e6%98%af%e5%8f%aa%e6%9c%89%e5%90%91%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;检索机制：不是&amp;quot;只有文件&amp;quot;，也不是&amp;quot;只有向量&amp;quot;
&lt;/h3&gt;&lt;p&gt;OpenClaw 使用&lt;strong&gt;混合检索&lt;/strong&gt;,它明确暴露了两个 agent-facing tools：&lt;/p&gt;
&lt;p&gt;●memory_search 负责检索&lt;/p&gt;
&lt;p&gt;●memory_get 负责精确读取某个 Markdown 文件或行段&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ 代码片段用户问&amp;#34;我上次出差去哪了？&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; BM25 关键词检索 ← 精确匹配&amp;#34;出差&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; 向量语义检索 ← 理解&amp;#34;去哪了&amp;#34;是问目的地
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; MMR 重排序 ← 去重、多样化
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;9&lt;/span&gt;&lt;span class="cl"&gt; 返回最相关的几条记忆片段
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/013-94c69879.png"&gt;&lt;/p&gt;
&lt;h3 id="记忆刷新在遗忘前先存档"&gt;&lt;a href="#%e8%ae%b0%e5%bf%86%e5%88%b7%e6%96%b0%e5%9c%a8%e9%81%97%e5%bf%98%e5%89%8d%e5%85%88%e5%ad%98%e6%a1%a3" class="header-anchor"&gt;&lt;/a&gt;记忆刷新：在&amp;quot;遗忘&amp;quot;前先&amp;quot;存档&amp;quot;
&lt;/h3&gt;&lt;p&gt;OpenClaw 有一个很巧妙的设计：&lt;code&gt;pre-compaction memory flush&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;当 session 接近上下文上限（比如对话太长，快塞不进模型窗口了），OpenClaw 会：&lt;/p&gt;
&lt;p&gt;●触发一次&amp;quot;静默回合&amp;quot;（用户看不到）&lt;/p&gt;
&lt;p&gt;●提醒模型：“把值得记住的信息写入记忆文件”&lt;/p&gt;
&lt;p&gt;●然后再压缩上下文&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/014-d04133a7.png"&gt;&lt;/p&gt;
&lt;h2 id="七工具体系分层设计不是堆砌功能"&gt;&lt;a href="#%e4%b8%83%e5%b7%a5%e5%85%b7%e4%bd%93%e7%b3%bb%e5%88%86%e5%b1%82%e8%ae%be%e8%ae%a1%e4%b8%8d%e6%98%af%e5%a0%86%e7%a0%8c%e5%8a%9f%e8%83%bd" class="header-anchor"&gt;&lt;/a&gt;七、工具体系：分层设计，不是堆砌功能
&lt;/h2&gt;&lt;p&gt;如果说 Gateway 是控制面，Session 是状态骨架，那么 Tools / Plugins / Skills 就是 OpenClaw 的执行肌肉。&lt;/p&gt;
&lt;p&gt;OpenClaw 的工具体系有三个层次，很多人会混淆。让我们分清楚：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/015-934c8d77.png"&gt;&lt;/p&gt;
&lt;h3 id="tools第一等公民"&gt;&lt;a href="#tools%e7%ac%ac%e4%b8%80%e7%ad%89%e5%85%ac%e6%b0%91" class="header-anchor"&gt;&lt;/a&gt;Tools：第一等公民
&lt;/h3&gt;&lt;p&gt;OpenClaw 暴露的是 &lt;strong&gt;first-class agent tools&lt;/strong&gt;，不是外挂脚本。 包括 browser、canvas、nodes、cron、gateway、session 相关工具、agents_list、image、pdf、message、exec 等。&lt;/p&gt;
&lt;p&gt;OpenClaw 没有把“能力调用”做成 prompt 技巧，而是做成了&lt;strong&gt;运行时契约&lt;/strong&gt;。Tool list 和 tool schema 会进入模型上下文；tool allow/deny、tool profiles、per-agent 工具策略、provider-specific 工具策略和 sandbox 工具策略共同决定模型实际能拿到哪些工具&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/016-1395dff2.png"&gt;&lt;/p&gt;
&lt;h3 id="plugins扩展系统本身"&gt;&lt;a href="#plugins%e6%89%a9%e5%b1%95%e7%b3%bb%e7%bb%9f%e6%9c%ac%e8%ba%ab" class="header-anchor"&gt;&lt;/a&gt;Plugins：扩展系统本身
&lt;/h3&gt;&lt;p&gt;插件是运行在 Gateway 内部的代码模块，可以：&lt;/p&gt;
&lt;p&gt;●注册新的 RPC 方法&lt;/p&gt;
&lt;p&gt;●添加新的 HTTP 路由&lt;/p&gt;
&lt;p&gt;●注册新的工具&lt;/p&gt;
&lt;p&gt;●启动后台服务&lt;/p&gt;
&lt;p&gt;类比：&lt;/p&gt;
&lt;p&gt;●Skills：像&amp;quot;使用说明书&amp;quot;&lt;/p&gt;
&lt;p&gt;●Tools：像&amp;quot;内置功能&amp;quot;&lt;/p&gt;
&lt;p&gt;●Plugins：像&amp;quot;给系统装新器官&amp;quot;&lt;/p&gt;
&lt;h3 id="skills教-ai-如何做事"&gt;&lt;a href="#skills%e6%95%99-ai-%e5%a6%82%e4%bd%95%e5%81%9a%e4%ba%8b" class="header-anchor"&gt;&lt;/a&gt;Skills：教 AI 如何做事
&lt;/h3&gt;&lt;p&gt;每个 Skill 就是一个目录，核心是 SKILL.md——一份详细的操作指南。Skill 的三个来源（优先级从高到低）：&lt;/p&gt;
&lt;p&gt;●&lt;code&gt;&amp;lt;workspace&amp;gt;/skills/&lt;/code&gt;：当前工作区专属&lt;/p&gt;
&lt;p&gt;●&lt;code&gt;~/.openclaw/skills/&lt;/code&gt;：用户私有技能&lt;/p&gt;
&lt;p&gt;●Bundled skills：系统内置技能&lt;/p&gt;
&lt;p&gt;与Plugins的本质区别:Plugins是给手机增加新硬件（如外接摄像头）；Skills是相机APP里的&amp;quot;夜景模式&amp;quot;说明书。&lt;/p&gt;
&lt;h2 id="八node让-ai-有手有眼"&gt;&lt;a href="#%e5%85%abnode%e8%ae%a9-ai-%e6%9c%89%e6%89%8b%e6%9c%89%e7%9c%bc" class="header-anchor"&gt;&lt;/a&gt;八、Node：让 AI “有手有眼”
&lt;/h2&gt;&lt;p&gt;OpenClaw 严格区分了两个概念：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/017-7e75b671.png"&gt;&lt;/p&gt;
&lt;p&gt;为什么这样设计？&lt;/p&gt;
&lt;p&gt;如果把它们混在一起：&lt;/p&gt;
&lt;p&gt;●Telegram Bot 只能干 Telegram 允许的事&lt;/p&gt;
&lt;p&gt;●WhatsApp Bot 只能干 WhatsApp 允许的事&lt;/p&gt;
&lt;p&gt;每个渠道都要重新实现一遍&amp;quot;控制电脑&amp;quot;的能力&lt;/p&gt;
&lt;p&gt;OpenClaw 的设计：&lt;/p&gt;
&lt;p&gt;●所有消息渠道都汇聚到 Gateway&lt;/p&gt;
&lt;p&gt;●所有设备能力也汇聚到 Gateway&lt;/p&gt;
&lt;p&gt;Gateway 负责调度：“这个 Telegram 消息需要控制 iPhone，我来协调”&lt;/p&gt;
&lt;h3 id="node-是什么"&gt;&lt;a href="#node-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;Node 是什么？
&lt;/h3&gt;
 &lt;blockquote&gt;
 &lt;p&gt;node 是 companion device，可以是 macOS、iOS、Android 或 headless 设备；它通过和 operator 一样的 Gateway WebSocket 接入，但使用 role: &amp;ldquo;node&amp;rdquo;，向 Gateway 暴露一组命令面，比如 canvas.&lt;em&gt;、camera.&lt;/em&gt;、device.&lt;em&gt;、notifications.&lt;/em&gt;、system.*，再由 node.invoke 触发。官方还特别强调：nodes are peripherals, not gateways。消息还是落在 Gateway，不是落在 node&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;Node 是一台&amp;quot;伴侣设备&amp;quot;，它：&lt;/p&gt;
&lt;p&gt;●通过 WebSocket 连接到 Gateway&lt;/p&gt;
&lt;p&gt;●向 Gateway 暴露一组能力（camera、notifications、system…）&lt;/p&gt;
&lt;p&gt;●等待 Gateway 的指令&lt;/p&gt;
&lt;p&gt;类比：&lt;/p&gt;
&lt;p&gt;●Gateway：大脑&lt;/p&gt;
&lt;p&gt;●消息渠道：耳朵和嘴&lt;/p&gt;
&lt;p&gt;●Node：手和脚&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/018-094dd77e.png"&gt;&lt;/p&gt;
&lt;p&gt;没有 Node 的话：&lt;/p&gt;
&lt;p&gt;●Telegram Bot 无法直接控制你的 iPhone&lt;/p&gt;
&lt;p&gt;●需要你自己手动截图,再发给 Bot&lt;/p&gt;
&lt;p&gt;●AI 无法真正&amp;quot;替你做事&amp;quot;&lt;/p&gt;
&lt;p&gt;有了 Node：&lt;/p&gt;
&lt;p&gt;●AI 可以跨设备协同工作&lt;/p&gt;
&lt;p&gt;●你在 Telegram 发指令,它在你的 Mac 上执行&lt;/p&gt;
&lt;p&gt;●真正的&amp;quot;个人助手&amp;quot;体验&lt;/p&gt;
&lt;h2 id="九安全边界诚实比承诺更重要"&gt;&lt;a href="#%e4%b9%9d%e5%ae%89%e5%85%a8%e8%be%b9%e7%95%8c%e8%af%9a%e5%ae%9e%e6%af%94%e6%89%bf%e8%af%ba%e6%9b%b4%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;九、安全边界：诚实比承诺更重要
&lt;/h2&gt;&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/019-9b4d83b0.png"&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 的安全模型假设的是 &lt;strong&gt;one trusted operator boundary per gateway&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 的安全文档非常诚实，这句话翻译成人话是：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/020-fe2dc05d.png"&gt;&lt;/p&gt;
&lt;p&gt;这意味着：如果你把Gateway密码给朋友，让他也连进来，你们的对话历史、文件访问、记忆内容默认不隔离。这不是漏洞，是设计选择——为了简化架构，OpenClaw牺牲了多租户隔离，换取单用户场景下的极致能力。&lt;/p&gt;
&lt;h3 id="安全层次"&gt;&lt;a href="#%e5%ae%89%e5%85%a8%e5%b1%82%e6%ac%a1" class="header-anchor"&gt;&lt;/a&gt;安全层次
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;⚡&lt;/span&gt; &lt;span class="err"&gt;代码片段外层：公网&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;外部消息源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;第一道门：&lt;/span&gt;&lt;span class="n"&gt;Gateway&lt;/span&gt; &lt;span class="err"&gt;入口保护&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="err"&gt;认证&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;challenge&lt;/span&gt; &lt;span class="err"&gt;签名验证&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="err"&gt;校验&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pairing&lt;/span&gt; &lt;span class="err"&gt;审批&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;第二道门：权限控制&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="err"&gt;角色&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;scopes&lt;/span&gt; &lt;span class="err"&gt;权限范围&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;第三道门：执行保护&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;tool&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="err"&gt;（工具策略）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;approvals&lt;/span&gt;&lt;span class="err"&gt;（执行审批）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sandbox&lt;/span&gt;&lt;span class="err"&gt;（沙箱隔离）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;allowlist&lt;/span&gt;&lt;span class="err"&gt;（白名单）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;内层：高风险边界&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;trusted&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="err"&gt;插件和&lt;/span&gt; &lt;span class="n"&gt;Gateway&lt;/span&gt; &lt;span class="err"&gt;同等权限&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/021-58fc1d46.png"&gt;&lt;/p&gt;
&lt;h3 id="sandbox可以隔离也可以放行"&gt;&lt;a href="#sandbox%e5%8f%af%e4%bb%a5%e9%9a%94%e7%a6%bb%e4%b9%9f%e5%8f%af%e4%bb%a5%e6%94%be%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;Sandbox：可以隔离，也可以放行
&lt;/h3&gt;&lt;p&gt;OpenClaw 的沙箱设计非常灵活：&lt;/p&gt;
&lt;p&gt;配置维度：&lt;/p&gt;
&lt;p&gt;●mode：off / non-main / all（是否启用沙箱）&lt;/p&gt;
&lt;p&gt;●scope：session / agent / shared（沙箱范围）&lt;/p&gt;
&lt;p&gt;●workspaceAccess：none / ro / rw（工作区访问权限）&lt;/p&gt;
&lt;p&gt;实际用法举例：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/022-0a65a7e5.png"&gt;&lt;/p&gt;
&lt;h3 id="浏览器隔离不是接管你的-chrome"&gt;&lt;a href="#%e6%b5%8f%e8%a7%88%e5%99%a8%e9%9a%94%e7%a6%bb%e4%b8%8d%e6%98%af%e6%8e%a5%e7%ae%a1%e4%bd%a0%e7%9a%84-chrome" class="header-anchor"&gt;&lt;/a&gt;浏览器隔离：不是接管你的 Chrome
&lt;/h3&gt;&lt;p&gt;OpenClaw不会接管你的日常Chrome（那里面可能有银行登录态），而是拉起独立的Chrome Profile：&lt;/p&gt;
&lt;p&gt;●独立的Cookie、缓存、扩展&lt;/p&gt;
&lt;p&gt;●Agent专用，与你的个人浏览数据隔离&lt;/p&gt;
&lt;p&gt;●支持截图、点击、PDF生成，但无法访问你个人的浏览器历史&lt;/p&gt;
&lt;p&gt;这是&amp;quot;能力&amp;quot;与&amp;quot;安全&amp;quot;的折中：AI需要浏览器自动化，但不能拥有你的全部数字生活。&lt;/p&gt;
&lt;h2 id="十为什么这是个人ai操作系统的雏形"&gt;&lt;a href="#%e5%8d%81%e4%b8%ba%e4%bb%80%e4%b9%88%e8%bf%99%e6%98%af%e4%b8%aa%e4%ba%baai%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e7%9a%84%e9%9b%8f%e5%bd%a2" class="header-anchor"&gt;&lt;/a&gt;十、为什么这是&amp;quot;个人AI操作系统&amp;quot;的雏形？
&lt;/h2&gt;&lt;p&gt;OpenClaw 之所以值得研究，不是因为它 GitHub stars 多，而是因为它回答了一个未来会越来越重要的问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果 AI 不再是网页对话框，而是一个长期在线、能操作设备、能记住一切的助手，它的系统架构应该长什么样？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 的答案是：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-11-openclaw-bao-huo-bei-hou-ta-bu-shi-liao-tian-ji-qi-ren-er-sh/023-c6731cdd.png"&gt;&lt;/p&gt;
&lt;p&gt;这套答案不一定是终局，也还远没到“完美”。Vision 文档自己都说，项目还很早，当前重点依然是 security、safe defaults、bug fixes、stability 和 setup reliability。也就是说，它依然在快速迭代，仍然带着实验性。&lt;/p&gt;
&lt;p&gt;但它已经足够有代表性。因为它第一次比较完整地把“个人 AI 助手”这件事，从概念拉成了系统工程：&lt;/p&gt;
&lt;p&gt;●消息不再只是消息，而是事件入口；&lt;/p&gt;
&lt;p&gt;●模型不再只是回答器，而是运行时里的推理核心；&lt;/p&gt;
&lt;p&gt;●工具不再只是 function calling 演示，而是被策略、审批和沙箱约束的系统调用；&lt;/p&gt;
&lt;p&gt;●记忆不再只是“模型好像记得”，而是落到磁盘、可检索、可审计、可 Git 备份的工作区资产&lt;/p&gt;
&lt;h3 id="它具备了操作系统的味道"&gt;&lt;a href="#%e5%ae%83%e5%85%b7%e5%a4%87%e4%ba%86%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e7%9a%84%e5%91%b3%e9%81%93" class="header-anchor"&gt;&lt;/a&gt;它具备了&amp;quot;操作系统&amp;quot;的味道
&lt;/h3&gt;&lt;p&gt;不是说它替代 Windows 或 macOS，而是说它有那种系统级的感觉：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ 代码片段传统应用：打开 → 用 → 关闭
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;操作系统：开机 → 长期运行 → 管理所有应用 → 关机
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;传统 AI：聊天 → 结束
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;OpenClaw：启动 Gateway → 长期在线 → 管理所有 Agent → 关闭
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最后，再强调一次：&lt;strong&gt;OpenClaw 的本质，不是一个接了很多渠道的聊天 Bot，而是一套以 Gateway 为控制面、以 Agent/Session/Memory 为状态骨架、以工具与节点为执行面，把大模型真正接入现实世界的个人 AI 助手系统。&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Kimi K2.5 模型接入 Claude Code 完全指南</title><link>https://xiaobox.github.io/p/2026-01-28-kimi-k2-5-mo-xing-jie-ru-claude-code-wan-quan-zhi-nan/</link><pubDate>Wed, 28 Jan 2026 08:20:02 +0000</pubDate><guid>https://xiaobox.github.io/p/2026-01-28-kimi-k2-5-mo-xing-jie-ru-claude-code-wan-quan-zhi-nan/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-01-28-kimi-k2-5-mo-xing-jie-ru-claude-code-wan-quan-zhi-nan/cover.jpg" alt="Featured image of post Kimi K2.5 模型接入 Claude Code 完全指南" /&gt;&lt;h1 id="kimi-k25-模型接入-claude-code-完全指南"&gt;&lt;a href="#kimi-k25-%e6%a8%a1%e5%9e%8b%e6%8e%a5%e5%85%a5-claude-code-%e5%ae%8c%e5%85%a8%e6%8c%87%e5%8d%97" class="header-anchor"&gt;&lt;/a&gt;Kimi K2.5 模型接入 Claude Code 完全指南
&lt;/h1&gt;&lt;p&gt;Claude Code 是 Anthropic 推出的官方命令行工具，让开发者能够在终端中与 Claude AI 进行交互式编程。通过简单的环境变量配置，你可以将 Claude Code 的后端从默认的 Claude 模型切换到 Kimi K2.5 模型，享受更强大的中文理解和代码生成能力。&lt;/p&gt;
&lt;p&gt;本文将详细介绍如何在 macOS、Linux 和 Windows 系统上完成配置，让你能够快速开始使用 Kimi K2.5 驱动 Claude Code。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="准备工作"&gt;&lt;a href="#%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;准备工作
&lt;/h2&gt;&lt;p&gt;在开始配置之前，请确保你已经完成以下准备工作：&lt;/p&gt;
&lt;p&gt;1.&lt;strong&gt;安装 Claude Code&lt;/strong&gt;：如果尚未安装，请参考 Anthropic 官方文档 进行安装&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;获取 Kimi API Key&lt;/strong&gt;：前往 Kimi 开放平台 注册账号并获取 API Key&lt;/p&gt;
&lt;p&gt;3.&lt;strong&gt;确认终端环境&lt;/strong&gt;：确保你使用的是 bash、zsh 或 PowerShell 等常见 shell&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="核心配置项"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e9%85%8d%e7%bd%ae%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;核心配置项
&lt;/h2&gt;&lt;p&gt;将 Kimi K2.5 接入 Claude Code 需要配置三个关键环境变量：&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;th&gt;值&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;API 基础地址&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;https://api.kimi.com/coding/&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;你的 Kimi API 密钥&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;sk-kimi-xxxxxxxx&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;使用的模型名称&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;kimi-for-coding&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-01-28-kimi-k2-5-mo-xing-jie-ru-claude-code-wan-quan-zhi-nan/001-98f88421.png"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="macos--linux-配置方法"&gt;&lt;a href="#macos--linux-%e9%85%8d%e7%bd%ae%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;macOS / Linux 配置方法
&lt;/h2&gt;&lt;h3 id="方法一临时配置当前终端会话"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%e4%b8%80%e4%b8%b4%e6%97%b6%e9%85%8d%e7%bd%ae%e5%bd%93%e5%89%8d%e7%bb%88%e7%ab%af%e4%bc%9a%e8%af%9d" class="header-anchor"&gt;&lt;/a&gt;方法一：临时配置（当前终端会话）
&lt;/h3&gt;&lt;p&gt;如果你只想在当前终端会话中使用 Kimi K2.5，可以直接执行以下命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;⚡&lt;/span&gt; &lt;span class="n"&gt;bash片段export&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;coding&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;-*************************&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;coding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;配置完成后，启动 Claude Code：&lt;/p&gt;
&lt;p&gt;⚡ bash片段&lt;code&gt;claude&lt;/code&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：这种方式只在当前终端窗口有效，关闭窗口后配置会失效。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="方法二永久配置推荐"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%e4%ba%8c%e6%b0%b8%e4%b9%85%e9%85%8d%e7%bd%ae%e6%8e%a8%e8%8d%90" class="header-anchor"&gt;&lt;/a&gt;方法二：永久配置（推荐）
&lt;/h3&gt;&lt;p&gt;为了让配置在每次打开终端时自动生效，你需要将环境变量添加到 shell 配置文件中。&lt;/p&gt;
&lt;h4 id="1-确定你的-shell-类型"&gt;&lt;a href="#1-%e7%a1%ae%e5%ae%9a%e4%bd%a0%e7%9a%84-shell-%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;1. 确定你的 shell 类型
&lt;/h4&gt;&lt;p&gt;⚡ bash片段&lt;code&gt;echo $SHELL&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;●如果输出 &lt;code&gt;/bin/zsh&lt;/code&gt;，使用 &lt;strong&gt;~/.zshrc&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;●如果输出 &lt;code&gt;/bin/bash&lt;/code&gt;，使用 &lt;strong&gt;~/.bashrc&lt;/strong&gt; 或 &lt;strong&gt;~/.bash_profile&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="2-编辑配置文件"&gt;&lt;a href="#2-%e7%bc%96%e8%be%91%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;2. 编辑配置文件
&lt;/h4&gt;&lt;p&gt;使用你喜欢的编辑器打开配置文件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ bash片段# 对于 zsh 用户
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;nano ~/.zshrc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;# 对于 bash 用户
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;nano ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="3-添加环境变量"&gt;&lt;a href="#3-%e6%b7%bb%e5%8a%a0%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;3. 添加环境变量
&lt;/h4&gt;&lt;p&gt;在文件末尾添加以下内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;⚡&lt;/span&gt; &lt;span class="n"&gt;bash片段&lt;/span&gt;&lt;span class="c1"&gt;# Kimi K2.5 for Claude Code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;coding&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;-**********************************&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;coding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="4-保存并生效"&gt;&lt;a href="#4-%e4%bf%9d%e5%ad%98%e5%b9%b6%e7%94%9f%e6%95%88" class="header-anchor"&gt;&lt;/a&gt;4. 保存并生效
&lt;/h4&gt;&lt;p&gt;保存文件后，运行以下命令使配置生效：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ bash片段# 对于 zsh 用户
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;source ~/.zshrc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;# 对于 bash 用户
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;source ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="5-验证配置"&gt;&lt;a href="#5-%e9%aa%8c%e8%af%81%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;5. 验证配置
&lt;/h4&gt;&lt;p&gt;⚡ bash片段&lt;code&gt;echo $ANTHROPIC_MODEL&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;如果输出 &lt;code&gt;kimi-for-coding&lt;/code&gt;，说明配置成功。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-01-28-kimi-k2-5-mo-xing-jie-ru-claude-code-wan-quan-zhi-nan/002-187e4585.png"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="windows-配置方法"&gt;&lt;a href="#windows-%e9%85%8d%e7%bd%ae%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;Windows 配置方法
&lt;/h2&gt;&lt;h3 id="方法一powershell-临时配置"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%e4%b8%80powershell-%e4%b8%b4%e6%97%b6%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;方法一：PowerShell 临时配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ powershell片段$env:ANTHROPIC_BASE_URL = &amp;#34;https://api.kimi.com/coding/&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;$env:ANTHROPIC_API_KEY = &amp;#34;sk-kimi-*************************&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;$env:ANTHROPIC_MODEL = &amp;#34;kimi-for-coding&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="方法二系统环境变量永久配置"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%e4%ba%8c%e7%b3%bb%e7%bb%9f%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f%e6%b0%b8%e4%b9%85%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;方法二：系统环境变量（永久配置）
&lt;/h3&gt;&lt;p&gt;1.按 &lt;code&gt;Win + R&lt;/code&gt;，输入 &lt;code&gt;sysdm.cpl&lt;/code&gt; 打开系统属性&lt;/p&gt;
&lt;p&gt;2.点击 &lt;strong&gt;高级&lt;/strong&gt; → &lt;strong&gt;环境变量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;3.在 &lt;strong&gt;用户变量&lt;/strong&gt; 区域点击 &lt;strong&gt;新建&lt;/strong&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;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;https://api.kimi.com/coding/&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;sk-kimi-*********************&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;kimi-for-coding&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;1.点击 &lt;strong&gt;确定&lt;/strong&gt; 保存&lt;/p&gt;
&lt;p&gt;2.&lt;strong&gt;重启终端&lt;/strong&gt; 使配置生效&lt;/p&gt;
&lt;h3 id="方法三powershell-配置文件"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%e4%b8%89powershell-%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;方法三：PowerShell 配置文件
&lt;/h3&gt;&lt;p&gt;在 PowerShell 中执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;⚡ powershell片段# 创建配置文件（如果不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;if (!(Test-Path $PROFILE)) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; New-Item -Path $PROFILE -Type File -Force
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;# 添加环境变量
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;Add-Content $PROFILE &amp;#34;`n$env:ANTHROPIC_BASE_URL = &amp;#39;https://api.kimi.com/coding/&amp;#39;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;Add-Content $PROFILE &amp;#34;`n$env:ANTHROPIC_API_KEY = &amp;#39;sk-kimi-*************************&amp;#39;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;9&lt;/span&gt;&lt;span class="cl"&gt;Add-Content $PROFILE &amp;#34;`n$env:ANTHROPIC_MODEL = &amp;#39;kimi-for-coding&amp;#39;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="验证连接"&gt;&lt;a href="#%e9%aa%8c%e8%af%81%e8%bf%9e%e6%8e%a5" class="header-anchor"&gt;&lt;/a&gt;验证连接
&lt;/h2&gt;&lt;p&gt;配置完成后，启动 Claude Code 并验证是否成功连接到 Kimi K2.5：&lt;/p&gt;
&lt;p&gt;⚡ bash片段&lt;code&gt;claude&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在 Claude Code 中，输入 &lt;code&gt;/model&lt;/code&gt; 查看当前使用的模型：&lt;/p&gt;
&lt;p&gt;如果返回的信息中包含 Kimi 或 kimi-for-coding，说明配置成功。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-01-28-kimi-k2-5-mo-xing-jie-ru-claude-code-wan-quan-zhi-nan/003-ed1fab23.png"&gt;&lt;/p&gt;</description></item><item><title>Gemini 3 介绍</title><link>https://xiaobox.github.io/p/2025-11-19-gemini-3-jie-shao/</link><pubDate>Wed, 19 Nov 2025 13:22:13 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-11-19-gemini-3-jie-shao/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-11-19-gemini-3-jie-shao/cover.jpg" alt="Featured image of post Gemini 3 介绍" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;Gemini应用每月用户超过6.5亿，超过70%的云服务客户在使用我们的人工智能，1300万开发者基于我们的生成式模型进行了开发，而这仅仅是我们所看到的影响的一小部分。 &amp;ndash; Google CEO Sundar Pichai&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;每一代 Gemini 都在以往的基础上不断发展，让你能够做更多事情。&lt;/p&gt;
&lt;p&gt;●Gemini 1 在原生多模态和长上下文窗口方面的突破，拓展了可处理信息的种类以及数量。&lt;/p&gt;
&lt;p&gt;●Gemini 2为智能体能力奠定了基础，并在推理与思考方面突破了前沿，助力完成更复杂的任务和构想，使 Gemini 2.5 Pro在LMArena上占据榜首超过六个月。&lt;/p&gt;
&lt;p&gt;今天 ，Google 终于憋出了大招，正式发布了 Gemini 3 系列。Google 这次明显是想通过 “Agentic（代理化）” 和 “Generative UI（生成式 UI）” 这两张牌，彻底改变我们开发和使用 AI 的方式。&lt;/p&gt;
&lt;h2 id="一核心模型不再只是-陪聊而是-干活-的"&gt;&lt;a href="#%e4%b8%80%e6%a0%b8%e5%bf%83%e6%a8%a1%e5%9e%8b%e4%b8%8d%e5%86%8d%e5%8f%aa%e6%98%af-%e9%99%aa%e8%81%8a%e8%80%8c%e6%98%af-%e5%b9%b2%e6%b4%bb-%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;一、核心模型：不再只是 “陪聊”，而是 “干活” 的
&lt;/h2&gt;&lt;p&gt;这次发布的重头戏有两个模型版本：&lt;/p&gt;
&lt;p&gt;1.Gemini 3 Pro&lt;/p&gt;
&lt;p&gt;○定位： 这是新的主力模型，Google 称之为 “最智能的模型”。&lt;/p&gt;
&lt;p&gt;○最大亮点 ——“Vibe Coding”：你不需要写精确的 prompt 或者伪代码，只需要用自然语言描述你想要的 “感觉（vibe）” 或功能，它就能生成全栈应用。比如 “做一个复古风格的太空射击游戏，障碍物要随着合成波音乐跳动”，它能直接给你生成带 UI 和交互的成品。&lt;/p&gt;
&lt;p&gt;○能力提升： 推理能力大幅增强，官方数据说在 LMArena 上 Elo 分数飙到了 1501（目前榜首）。&lt;/p&gt;
&lt;p&gt;○适用场景： 日常高频任务、代码生成、多模态理解（视频/图像/音频）。&lt;/p&gt;
&lt;p&gt;2.Gemini 3 Deep Think&lt;/p&gt;
&lt;p&gt;○定位： 专门用来 “死磕” 难题的推理模型，仅面向 Google AI Ultra 订阅用户。&lt;/p&gt;
&lt;p&gt;○对标对象： 显然是 OpenAI 的 o1 / o3 系列。&lt;/p&gt;
&lt;p&gt;○恐怖的数据： 在 Humanity&amp;rsquo;s Last Exam（人类终极考试）这个测试集上，Gemini 3 Pro 得分 37.5%，而 Deep Think 版本能干到 41.0%（作为对比，上一代 Gemini 2.5 Pro 只有 21.6%）。这意味着在数学、科学研究等需要深度思考的领域，它的可靠性会有质的飞跃。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-11-19-gemini-3-jie-shao/001-7f39bd1d.png"&gt;&lt;/p&gt;
&lt;h2 id="二-ai-ide-google-antigravity-反重力"&gt;&lt;a href="#%e4%ba%8c-ai-ide-google-antigravity-%e5%8f%8d%e9%87%8d%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;二、 AI IDE ：Google Antigravity (反重力)
&lt;/h2&gt;&lt;p&gt;Google 推出了一个全新的 Agentic IDE，叫 Google Antigravity&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-11-19-gemini-3-jie-shao/002-ad66a4c5.png"&gt;&lt;/p&gt;
&lt;p&gt;●这是什么？ 别把它想成 VS Code 的插件。这是一个独立的 IDE，专门为 “AI 代理开发” 设计的。&lt;/p&gt;
&lt;p&gt;●核心逻辑变了： 以前我们是用 Copilot 写代码（AI 辅助你），现在你是 “架构师”，你定义任务，Antigravity 里的 Agents（代理）去执行。&lt;/p&gt;
&lt;p&gt;●它能干嘛？&lt;/p&gt;
&lt;p&gt;○全自主干活： 代理可以在编辑器写代码、在终端跑命令、在浏览器里预览调试，三者打通。&lt;/p&gt;
&lt;p&gt;○Artifacts（产物）： 代理不仅仅是吐代码，还会生成任务清单、实施计划、甚至截图，让你像验收工作一样去 Check 它的产出。&lt;/p&gt;
&lt;p&gt;○模型任选： 这一点很良心，除了 Gemini 3，它居然支持 Anthropic 的 Claude Sonnet 4.5 和 OpenAI 的 GPT - OSS。Google 这次格局打开了，意思是 “用最好的工具解决问题”。&lt;/p&gt;
&lt;p&gt;这玩意儿就是冲着 Cursor 来的，而且试图在 “自主性” 上更进一步。建议大家赶紧去下个 Preview 版试试，特别是 Mac/Windows/Linux 都支持。&lt;/p&gt;
&lt;h2 id="三-用户体验革命generative-ui-生成式-ui"&gt;&lt;a href="#%e4%b8%89-%e7%94%a8%e6%88%b7%e4%bd%93%e9%aa%8c%e9%9d%a9%e5%91%bdgenerative-ui-%e7%94%9f%e6%88%90%e5%bc%8f-ui" class="header-anchor"&gt;&lt;/a&gt;三、 用户体验革命：Generative UI (生成式 UI)
&lt;/h2&gt;&lt;p&gt;Google 认为：“最好的 UI 是不需要设计的，是生成的。”&lt;/p&gt;
&lt;p&gt;Google 认为，AI 的回答不应该只是一堆文字。Gemini 3 引入了 Generative UI（生成式用户界面）&lt;/p&gt;
&lt;p&gt;●动态生成组件： 当用户问 “帮我规划去罗马的旅行” 时，它不再只是列个文字清单，而是可能会直接生成一个 “交互式的行程卡片”，或者当你问房贷时，直接生成一个 “房贷计算器组件”。&lt;/p&gt;
&lt;p&gt;●底层技术： 依靠 Gemini 3 强大的代码生成能力，即时生成前端代码并在客户端渲染。&lt;/p&gt;
&lt;p&gt;●Dynamic View： 在 Gemini App 里，这被称为 “Dynamic View”。它能根据你的意图，现场 “手搓” 一个最适合当前场景的 UI 界面给你。&lt;/p&gt;
&lt;p&gt;未来的 AI 应用，界面可能不再是写死的，而是 “流式生成” 的。&lt;/p&gt;
&lt;h2 id="四-实战与性能-benchmarks"&gt;&lt;a href="#%e5%9b%9b-%e5%ae%9e%e6%88%98%e4%b8%8e%e6%80%a7%e8%83%bd-benchmarks" class="header-anchor"&gt;&lt;/a&gt;四、 实战与性能 (Benchmarks)
&lt;/h2&gt;&lt;p&gt;如果不看跑分就不是科技圈了。简单列几个吓人的数据：&lt;/p&gt;
&lt;p&gt;●LMArena Elo: 1501 (目前世界第一)。&lt;/p&gt;
&lt;p&gt;●MathArena Apex: 23.4% (这是个新出的超难数学竞赛基准，其他模型基本是个位数，Claude 4.5 是 1.6%，GPT-5.1 是 1.0%&amp;hellip; Gemini 3 这个分数有点断层领先的意思)。&lt;/p&gt;
&lt;p&gt;●SWE-bench Verified (代码能力): 76.2%。虽然比 Claude 的 77.2% 略低一点点，但在 Antigravity 环境下的综合表现（Agentic coding）可能会更强。&lt;/p&gt;
&lt;p&gt;●多模态: 视频理解 (Video-MMMU) 达到了 87.6%，以后扔给它一段长视频让它总结或者找细节，应该会非常准。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-11-19-gemini-3-jie-shao/003-49ccf38a.png"&gt;&lt;/p&gt;
&lt;h2 id="五-生态整合这才是-google-恐怖的地方"&gt;&lt;a href="#%e4%ba%94-%e7%94%9f%e6%80%81%e6%95%b4%e5%90%88%e8%bf%99%e6%89%8d%e6%98%af-google-%e6%81%90%e6%80%96%e7%9a%84%e5%9c%b0%e6%96%b9" class="header-anchor"&gt;&lt;/a&gt;五、 生态整合（这才是 Google 恐怖的地方）
&lt;/h2&gt;&lt;p&gt;Google 把 Gemini 3 塞进了所有角落：&lt;/p&gt;
&lt;p&gt;●Search: 搜索里加了 “AI Mode”，而且支持 “Thinking” 开关。以后搜复杂问题（比如做攻略、查论文），搜索体验会完全不同。&lt;/p&gt;
&lt;p&gt;●Android Studio: 安卓开发的同事注意了，Gemini 3 已经进驻，不仅是补全代码，还能帮你写 UI、查 Bug。&lt;/p&gt;
&lt;p&gt;●Gemini CLI: 对于运维和后端同事，新的 CLI 允许你在终端里直接用自然语言让 Gemini 3 帮你执行复杂的 Shell 命令组合，甚至排查云端服务的 Log。&lt;/p&gt;
&lt;p&gt;●Firebase: 推出了 &amp;ldquo;Firebase AI Logic&amp;rdquo;，后端逻辑也能由 AI 驱动了。&lt;/p&gt;
&lt;h2 id="六-总结与建议"&gt;&lt;a href="#%e5%85%ad-%e6%80%bb%e7%bb%93%e4%b8%8e%e5%bb%ba%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;六、 总结与建议
&lt;/h2&gt;&lt;p&gt;Gemini 3 无疑是一次 “能力的平权”&lt;/p&gt;
&lt;p&gt;Gemini 3 不仅仅是 “更快更强”，它在尝试定义 AI 的下一阶段：&lt;/p&gt;
&lt;p&gt;1.从 Chat 到 Agent: 不再是 “一问一答”，而是 “通过代理解决多步骤复杂任务”。&lt;/p&gt;
&lt;p&gt;2.从 Text 到 UI: 输出形式从文本扩展到了动态界面。&lt;/p&gt;
&lt;p&gt;给产研内部的建议：&lt;/p&gt;
&lt;p&gt;●开发同学： 务必尝试 Google Antigravity 和 Gemini CLI。如果它真能像宣传那样自主改 Bug、重构代码，我们的开发效率可能会有质变。&lt;/p&gt;
&lt;p&gt;●产品同学： 关注 Generative UI 的交互模式。我们的 AI 产品是否也可以不仅仅吐文字，而是根据用户需求动态生成交互组件？&lt;/p&gt;
&lt;p&gt;●模型同学： 重点关注 Deep Think 的推理模式，看看 Google 是如何通过增加推理时间（Test-time compute）来换取高质量输出的。&lt;/p&gt;
&lt;p&gt;目前 Gemini 3 Pro 已经在 Gemini App 和 AI Studio 里能用了，Deep Think 还要等几周。大家可以先去玩玩 Pro 版的 “Vibe Coding”&lt;/p&gt;</description></item><item><title>从初始化一个现代 python 项目中学习到的东西</title><link>https://xiaobox.github.io/p/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/</link><pubDate>Sun, 27 Apr 2025 06:57:05 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/cover.jpg" alt="Featured image of post 从初始化一个现代 python 项目中学习到的东西" /&gt;&lt;h2 id="uv"&gt;&lt;a href="#uv" class="header-anchor"&gt;&lt;/a&gt;uv
&lt;/h2&gt;&lt;p&gt;我准备用 uv 初始化一个 python 项目&lt;/p&gt;
&lt;h3 id="环境"&gt;&lt;a href="#%e7%8e%af%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;环境
&lt;/h3&gt;&lt;p&gt;我用的是苹果笔记本 MacBookPro ，具体的操作系统及硬件参数如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/001-7b50b558.png"&gt;&lt;/p&gt;
&lt;h3 id="uv-的介绍与安装"&gt;&lt;a href="#uv-%e7%9a%84%e4%bb%8b%e7%bb%8d%e4%b8%8e%e5%ae%89%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;uv 的介绍与安装
&lt;/h3&gt;
 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;uv 是一个使用 Rust 编写的工具，可以用来替代 pip、pipenv、pipx、poetry、virtualenv 等工具的使用，甚至还可以用来管理系统中所安装的 Python 发行版。uv 借鉴了很多现代语言中对于项目依赖的管理方式，项目中对于依赖的管理要远远优于使用 pip 和requirements.txt的方式。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;我之前用过 pip 、pipx 等工具，发现 uv 确实要快不少。具体有多快呢？ github 上有个图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/002-23c27ef6.png"&gt;&lt;/p&gt;
&lt;p&gt;🚀速度比传统 pip 快 10-100倍。&lt;/p&gt;
&lt;p&gt;根据官网的介绍，uv 主要支持以下功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持版本锁定的项目依赖管理。&lt;/li&gt;
&lt;li&gt;支持直接运行 Python 脚本。&lt;/li&gt;
&lt;li&gt;支持对系统中安装的 Python 进行管理，支持多版本 Python 共存。&lt;/li&gt;
&lt;li&gt;支持 Python 包的发布和安装。&lt;/li&gt;
&lt;li&gt;支持兼容 pip 的应用接口。&lt;/li&gt;
&lt;li&gt;支持 Cargo 模式的项目工作区管理。&lt;/li&gt;
&lt;li&gt;更优化的全局支持库缓存。&lt;/li&gt;
&lt;li&gt;运行无需 Rust 或者 Python 支持。&lt;/li&gt;
&lt;li&gt;支持 Windows、macOS 和 Linux 系统&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;uv 对多 python 版本和环境的管理很不错，这样你就可以一个项目指定一个特定的 Python 版本，放心使用，想怎么折腾怎么折腾，不会影响全局。&lt;/p&gt;
&lt;p&gt;最近比较火的 MCP 很多也是用 uv 运行的，因为用 uv 命令可以直接运行 python 脚本。&lt;/p&gt;
&lt;p&gt;uv 的安装非常简单：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# macOS和Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;curl -LsSf https://astral.sh/uv/install.sh &lt;span class="p"&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Windows PowerShell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;powershell -ExecutionPolicy ByPass -c &lt;span class="s2"&gt;&amp;#34;irm https://astral.sh/uv/install.ps1 | iex&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="uv-对-python-的环境管理"&gt;&lt;a href="#uv-%e5%af%b9-python-%e7%9a%84%e7%8e%af%e5%a2%83%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;uv 对 Python 的环境管理
&lt;/h3&gt;&lt;p&gt;首先用 uv 管理一下我们本机安装的 Python 环境。即到底安装了几个、哪些版本的 python。&lt;/p&gt;
&lt;p&gt;可以用 &lt;code&gt;uv python list&lt;/code&gt; 查看，像这样：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/003-cd779d4c.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到我已经安装了多个版本的 python。 在后面建项目的时候，我选用 3.13 这个版本。当然你也可以根据你的情况下载新的需要使用的版本。这里给出一组相关命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;uv python install，安装指定版本的 Python。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;uv python list，列出系统中当前已经安装的 Python 版本。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;uv python find，查找一个已经安装的 Python 版本。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;uv python pin，固定当前项目使用指定的 Python 版本。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;uv python uninstall，卸载指定版本的 Python。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;比如我要安装 3.12 这个版本，我就可以这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;uv python install 3.13
&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" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;uv python uninstall 3.13 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="uv-进行项目管理"&gt;&lt;a href="#uv-%e8%bf%9b%e8%a1%8c%e9%a1%b9%e7%9b%ae%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;uv 进行项目管理
&lt;/h3&gt;&lt;p&gt;python 的环境有了以后，我们就可以新建项目了，建项目的时候也要用 uv 来进行初始化。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;uv 的项目管理功能更多的借鉴了 Rust 中 Cargo 工具的项目管理理念。但主要区别是 uv 是通过项目目录中的pyproject.toml文件来完成项目管理的。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;uv init myproject
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;初始化后会生成以下几个文件 ：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/004-32d38507.png"&gt;&lt;/p&gt;
&lt;p&gt;虽然 uv init myproject 会帮你创建项目目录和 pyproject.toml，但默认 不会自动创建虚拟环境（env），所以我们需要手动创建。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;# 手动创建虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;uv venv --python 3.13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;# 激活虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;source .venv/bin/activate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;虚拟环境激活后，项目中会多一个.venv 文件夹。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-27-cong-chu-shi-hua-yi-ge-xian-dai-python-xiang-mu-zhong-xue-xi/005-3a39005f.png"&gt;&lt;/p&gt;
&lt;p&gt;接下来我们要自己创建一下源码目录和测试目录：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;mkdir -p src tests
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;到这里工程的相关目录我们就先到此为止，基本上创建完了，然后我们来编辑&lt;/p&gt;
&lt;p&gt;pyproject.toml 配置文件。&lt;/p&gt;
&lt;h3 id="toml-配置文件"&gt;&lt;a href="#toml-%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;toml 配置文件
&lt;/h3&gt;&lt;p&gt;我们先介绍一下 toml 文件，可能有些朋友不怎么了解它，比如搞 java 开发的。&lt;/p&gt;
&lt;p&gt;TOML（Tom&amp;rsquo;s Obvious, Minimal Language）是一种配置文件格式，设计目标是&lt;strong&gt;易读、易写、易于解析&lt;/strong&gt;，非常适合作为程序的配置语言，尤其是在现代的跨平台开发中被广泛采用。&lt;/p&gt;
&lt;p&gt;你看这名字是不是觉得肯定跟 Tom 大哥有关系？&lt;/p&gt;
&lt;p&gt;对，因为 TOML 由 GitHub 联合创始人 Tom Preston-Werner 在 2013 年发起，用以替代 JSON、INI 等配置格式在可读性和灵活性上的不足。&lt;/p&gt;
&lt;p&gt;不过吧，后来这大哥（和她媳妇）不在 GitHub 干了，因为他们的一些不光彩的行为。具体是什么就不多说了，想八卦一下的可以去查查。&lt;/p&gt;
&lt;p&gt;toml 配置文件用途广泛，常用于以下场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用程序运行时配置&lt;/li&gt;
&lt;li&gt;包管理工具（如 Python 的 pyproject.toml、Rust 的 Cargo.toml）&lt;/li&gt;
&lt;li&gt;构建工具配置（如 poetry.toml, uv.toml）&lt;/li&gt;
&lt;li&gt;数据库或服务连接信息等环境参数配置&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;举个例子吧：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;# 数据库配置
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;[database]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;server = &amp;#34;192.168.1.1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;ports = [ 8001, 8001, 8002 ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;enabled = true
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;# 应用信息
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;[app]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;name = &amp;#34;MyApp&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;version = &amp;#34;1.0.0&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;release_date = 2025-04-25T12:00:00Z
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TOML 的特点可以总结为：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;“比 JSON 更适合人读，比 YAML 更适合程序解析。”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;它已经成为现代软件开发中最流行的配置文件格式之一，特别是在需要 &lt;strong&gt;清晰结构 + 丰富类型 + 可维护性&lt;/strong&gt; 的场景中表现出色。&lt;/p&gt;
&lt;p&gt;常见语言的支持情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python：tomli / toml / pytoml / tomllib（Python 3.11 原生支持）&lt;/li&gt;
&lt;li&gt;Rust：官方包管理工具 Cargo 就使用 TOML 格式的 Cargo.toml&lt;/li&gt;
&lt;li&gt;Go：支持 BurntSushi/toml 库&lt;/li&gt;
&lt;li&gt;Node.js：支持 @iarna/toml 等多个库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;常见用途：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 包管理：pyproject.toml（PEP 518 标准）&lt;/li&gt;
&lt;li&gt;Rust 项目管理：Cargo.toml&lt;/li&gt;
&lt;li&gt;Web 项目配置：netlify.toml&lt;/li&gt;
&lt;li&gt;DevOps 工具：例如 uv 的配置也是用 toml 文件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TOML 与其他格式的对比：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;特性&lt;/th&gt;
 &lt;th&gt;TOML&lt;/th&gt;
 &lt;th&gt;JSON&lt;/th&gt;
 &lt;th&gt;YAML&lt;/th&gt;
 &lt;th&gt;INI&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;中&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;❌ 不支持&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;✅ 多&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;✅ 全面&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;✅ 低&lt;/td&gt;
 &lt;td&gt;❌ 偏高&lt;/td&gt;
 &lt;td&gt;✅ 极低&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;你看，TOML 作为配置文件感觉很不错对吧。&lt;/p&gt;
&lt;p&gt;我们关于 TOML 的介绍就到此为止，现在来说一下我们这个初始化的新项目中的 pyproject.toml 文件要写成什么样。&lt;/p&gt;
&lt;p&gt;就这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hatchling&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;hatchling.build&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;myproject&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;一个基于Python 3.13.3的项目&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;readme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;README.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;requires&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;gt;=3.13&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;xiaobox&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;xiaobox@gmail.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;pytest&amp;gt;=7.4.3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fastapi&amp;gt;=0.110.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uvicorn&amp;gt;=0.27.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;httpx&amp;gt;=0.27.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;classifiers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Programming Language :: Python :: 3.13&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;License :: OSI Approved :: MIT License&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Operating System :: OS Independent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;myproject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;src.main:main&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;Homepage&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://github.com/yourusername/myproject&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;Bug Tracker&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://github.com/yourusername/myproject/issues&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;black&amp;gt;=23.1.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;isort&amp;gt;=5.12.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;37&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mypy&amp;gt;=1.5.1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;38&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;39&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;40&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;41&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;testpaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tests&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;42&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;43&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;44&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;45&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;py313&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;46&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;47&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isort&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;48&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;49&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;line_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;50&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;51&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hatch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wheel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;52&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;别小看了这个文件，它可是一个使用了 Hatch 构建工具、遵循 PEP 621 和现代 Python 项目结构规范的项目配置，涵盖了运行依赖、开发依赖、CLI 脚本、格式化工具配置、测试路径和打包目标，非常完整规范。&lt;/p&gt;
&lt;p&gt;所以我们得逐行解释一下这个重要的文件。&lt;/p&gt;
&lt;h3 id="toml-配置文件的逐行解释"&gt;&lt;a href="#toml-%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e7%9a%84%e9%80%90%e8%a1%8c%e8%a7%a3%e9%87%8a" class="header-anchor"&gt;&lt;/a&gt;toml 配置文件的逐行解释
&lt;/h3&gt;&lt;p&gt;我们上面的配置文件是一个标准的 Python 项目使用 &lt;code&gt;pyproject.toml&lt;/code&gt; 来管理构建系统、依赖、工具配置的典型示例。下面我们来拆解和解释一下。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;✅ &lt;code&gt;[build-system]&lt;/code&gt;：构建系统配置（PEP 517 标准）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;[build-system]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;requires = [&amp;#34;hatchling&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;build-backend = &amp;#34;hatchling.build&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requires&lt;/code&gt;：构建该项目所需的构建工具，这里是 &lt;code&gt;hatchling&lt;/code&gt;，必须先安装。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build-backend&lt;/code&gt;：指定用哪个构建后端来执行打包任务，这里是 &lt;code&gt;hatchling.build&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;hatchling 有点儿类似 java 中的 Maven 或 Gradle，都是用来执行自动化构建流程的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Maven 是把 java 代码编译、构建成 jar 包，方便管理依赖、分发、版本控制&lt;/li&gt;
&lt;li&gt;hatchling 是把 python 代码构建成 Wheel（.whl 文件）或 Source Distribution（.tar.gz 或 .zip 文件），也是为了做依赖管理、分发和版本控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;总结来说：&lt;strong&gt;Python 的构建是将代码和依赖打包成 .whl 或 .tar.gz，类似于 Java 打包成 .jar。核心目的是简化分发、确保环境一致性、自动化依赖管理。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;✅ &lt;code&gt;[project]&lt;/code&gt;：项目的核心元信息（PEP 621 标准）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;[project]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;name = &amp;#34;myproject&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;项目名称，最终发布到 PyPI 时会用这个名字。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;version = &amp;#34;0.1.0&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;当前版本号。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;description = &amp;#34;一个基于Python 3.13.3的项目&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;简短的项目说明。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;readme = &amp;#34;README.md&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;指定项目的 README 文件，将作为 PyPI 上项目首页的介绍内容。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;requires-python = &amp;#34;&amp;gt;=3.13&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;要求的 Python 版本最低为 3.13。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;authors = [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; {name = &amp;#34;xiaobox&amp;#34;, email = &amp;#34;xiaobox@gmail.com&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;作者信息，支持多个，用列表表示。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;dependencies = [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;pytest&amp;gt;=7.4.3&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;fastapi&amp;gt;=0.110.0&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;uvicorn&amp;gt;=0.27.0&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;httpx&amp;gt;=0.27.0&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;项目的运行时依赖库，在安装时会自动安装这些包。这里我加入了 pytest、&lt;strong&gt;fastapi&lt;/strong&gt; 的依赖，因为我想把这个项目作为一个 api 服务提供出去。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;classifiers = [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;Programming Language :: Python :: 3.13&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;License :: OSI Approved :: MIT License&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;Operating System :: OS Independent&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;用于 PyPI 分类（帮助搜索和筛选）。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-projectscripts定义可执行命令如-cli"&gt;&lt;a href="#-projectscripts%e5%ae%9a%e4%b9%89%e5%8f%af%e6%89%a7%e8%a1%8c%e5%91%bd%e4%bb%a4%e5%a6%82-cli" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[project.scripts]&lt;/code&gt;：定义可执行命令（如 CLI）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;[project.scripts]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;myproject = &amp;#34;src.main:main&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;安装后运行 &lt;code&gt;myproject&lt;/code&gt; 命令会调用 &lt;code&gt;src/main.py&lt;/code&gt; 中的 &lt;code&gt;main()&lt;/code&gt; 函数。（我们需要提前把之前的 main.py 文件要先移动到 /src 目录下）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-projecturls项目的相关链接非必须"&gt;&lt;a href="#-projecturls%e9%a1%b9%e7%9b%ae%e7%9a%84%e7%9b%b8%e5%85%b3%e9%93%be%e6%8e%a5%e9%9d%9e%e5%bf%85%e9%a1%bb" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[project.urls]&lt;/code&gt;：项目的相关链接（非必须）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;[project.urls]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&amp;#34;Homepage&amp;#34; = &amp;#34;https://github.com/yourusername/myproject&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&amp;#34;Bug Tracker&amp;#34; = &amp;#34;https://github.com/yourusername/myproject/issues&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;为项目指定一些有用的链接，如主页、问题反馈页等。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-projectoptional-dependencies可选依赖比如开发环境"&gt;&lt;a href="#-projectoptional-dependencies%e5%8f%af%e9%80%89%e4%be%9d%e8%b5%96%e6%af%94%e5%a6%82%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[project.optional-dependencies]&lt;/code&gt;：可选依赖（比如开发环境）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;[project.optional-dependencies]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;dev = [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;black&amp;gt;=23.1.0&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;isort&amp;gt;=5.12.0&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;mypy&amp;gt;=1.5.1&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们为开发环境安装了三个库：black、isort 和 mypy&lt;/p&gt;
&lt;p&gt;介绍一下这三个工具&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;black：是一个 Python 代码格式化工具。自动把你的 Python 代码排版成统一风格，比如：缩进、换行、空格都按标准格式处理，让你的 Python 代码看起来更整齐、统一，无需自己动手排版。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;isort：是一个 Python 导入（import）语句自动排序工具。自动整理文件顶部的 import 语句，比如按字母顺序排列，分组标准库、第三方库、自定义模块，保持导入部分有序且规范。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mypy：是一个 Python 静态类型检查工具。检查你的代码里的类型注解（type hints）是不是正确，比如函数参数和返回值类型对不对，帮你在写代码时发现类型出错的地方，提前避免 bug。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-toolpytestpytest-配置"&gt;&lt;a href="#-toolpytestpytest-%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[tool.pytest]&lt;/code&gt;：Pytest 配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;testpaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tests&amp;#34;&lt;/span&gt;&lt;span class="p"&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;code&gt;pytest&lt;/code&gt; 会从 &lt;code&gt;tests/&lt;/code&gt; 目录开始查找测试文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-toolblack代码格式化工具-black-的配置"&gt;&lt;a href="#-toolblack%e4%bb%a3%e7%a0%81%e6%a0%bc%e5%bc%8f%e5%8c%96%e5%b7%a5%e5%85%b7-black-%e7%9a%84%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[tool.black]&lt;/code&gt;：代码格式化工具 Black 的配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;py313&amp;#34;&lt;/span&gt;&lt;span class="p"&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;设置代码的行最大长度为 88（默认值），目标 Python 版本是 3.13。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-toolisortimport-排序工具-isort-的配置"&gt;&lt;a href="#-toolisortimport-%e6%8e%92%e5%ba%8f%e5%b7%a5%e5%85%b7-isort-%e7%9a%84%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[tool.isort]&lt;/code&gt;：import 排序工具 isort 的配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isort&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;line_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;88&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;code&gt;black&lt;/code&gt; 的风格对 import 排序。&lt;/li&gt;
&lt;li&gt;设置行长度为 88，与 black 保持一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="-toolhatchbuildtargetswheelhatchling-打包配置"&gt;&lt;a href="#-toolhatchbuildtargetswheelhatchling-%e6%89%93%e5%8c%85%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;✅ &lt;code&gt;[tool.hatch.build.targets.wheel]&lt;/code&gt;：Hatchling 打包配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hatch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wheel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class="p"&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;code&gt;src&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;用一句话总结下这个 &lt;code&gt;pyproject.toml&lt;/code&gt; 配置文件 ：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“这是一个使用 Hatch 构建工具、遵循 PEP 621 和现代 Python 项目结构规范的项目配置，涵盖了运行依赖、开发依赖、CLI 脚本、格式化工具配置、测试路径和打包目标，非常完整规范。”&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="安装和更新依赖"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e5%92%8c%e6%9b%b4%e6%96%b0%e4%be%9d%e8%b5%96" class="header-anchor"&gt;&lt;/a&gt;安装和更新依赖
&lt;/h3&gt;&lt;p&gt;上面这个文件编辑完成后，我们就可以 安装项目和开发依赖了：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;uv pip install -e &amp;#34;.[dev]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果后面你更新了 &lt;code&gt;pyproject.toml&lt;/code&gt; 文件可以执行以下命令来 “手动刷新” 一个依赖库：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;uv sync --extra dev 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;加入 &lt;code&gt;--extra dev&lt;/code&gt; 参数是因为 &lt;code&gt;uv sync&lt;/code&gt; 默认只安装 [project.dependencies] 中列出的正式依赖。&lt;/p&gt;
&lt;p&gt;不会自动安装 [project.optional-dependencies]（比如 dev 里面的 black、isort、mypy）&lt;/p&gt;
&lt;p&gt;&lt;code&gt;uv sync --extra dev&lt;/code&gt; 的意思是：除了正式依赖，还要把 [project.optional-dependencies.dev] 里的东西也同步上&lt;/p&gt;
&lt;h3 id="uvlock"&gt;&lt;a href="#uvlock" class="header-anchor"&gt;&lt;/a&gt;uv.lock
&lt;/h3&gt;&lt;p&gt;当执行完 &lt;code&gt;uv sync --extra dev&lt;/code&gt; ，安装好依赖好， uv 会在项目根路径生成一个 &lt;code&gt;uv.lock&lt;/code&gt; 文件 。uv.lock 是 锁定依赖版本 的文件。&lt;/p&gt;
&lt;p&gt;它的作用是：把 pyproject.toml 里描述的依赖（比如 &amp;ldquo;fastapi&amp;gt;=0.110.0&amp;rdquo; 这样比较宽松的范围），具体锁定成明确、唯一的版本（比如 &amp;ldquo;fastapi==0.110.1&amp;rdquo;）。&lt;/p&gt;
&lt;p&gt;这样，每次安装时，不管谁来安装（你自己、你的同事、你的服务器），大家安装的依赖版本都是一模一样的，不会因为小版本不同导致奇怪的 bug。&lt;/p&gt;
&lt;p&gt;uv.lock 是自动生成、自动管理的。不需手动编辑。&lt;/p&gt;
&lt;h2 id="其他"&gt;&lt;a href="#%e5%85%b6%e4%bb%96" class="header-anchor"&gt;&lt;/a&gt;其他
&lt;/h2&gt;&lt;p&gt;其他的，如 fastapi 相关的、 打 docker 镜像部署什么的相对本文主题超纲了，就不在本文中过多描述了。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;本文我们分享了用 uv 初始化和管理 Python 项目的完整流程。&lt;/p&gt;
&lt;p&gt;从安装 uv 开始，我介绍了它为什么比传统工具（pip、pipx、poetry 等）更快更好用，以及 uv 在多 Python 版本管理、依赖锁定、项目初始化方面带来的便利。&lt;/p&gt;
&lt;p&gt;随后，详细讲了如何用 uv 管理本地 Python 环境、新建项目、创建虚拟环境、编辑 pyproject.toml 配置，并逐步解释了各个配置项的作用&lt;/p&gt;
&lt;p&gt;整体来看，uv 提供了一套现代、规范、高效的 Python 项目管理方案，非常适合用来打基础，后续无论是开发 API、打包 Docker 镜像，还是部署上线，都能有条不紊地进行。&lt;/p&gt;
&lt;p&gt;同时我们通过在项目创建的过程中看到各语言（java、nodejs&amp;hellip;）都相通或类似的工程 “最佳实践”，真是应了那句话：“大道至简，真理趋同”&lt;/p&gt;</description></item><item><title>Redis6.0 以后为什么使用了多线程？</title><link>https://xiaobox.github.io/p/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/</link><pubDate>Mon, 18 Nov 2024 02:04:32 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/cover.jpg" alt="Featured image of post Redis6.0 以后为什么使用了多线程？" /&gt;&lt;p&gt;Redis 所谓的单线程并不是所有工作都是只有一个线程在执行，而是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的，Redis 在处理客户端的请求时包括获取 (socket 读）、解析、执行、内容返回 (socket 写） 等都由一个顺序串行的主线程处理。&lt;/p&gt;
&lt;p&gt;这就是所谓的“&lt;strong&gt;单线程&lt;/strong&gt;”。这也是 Redis 对外提供键值存储服务的主要流程。
由于 Redis 在处理命令的时候是单线程作业的，所以会有一个 Socket 队列，每一个到达的服务端命令来了之后都不会马上被执行，而是进入队列，然后被线程的事件分发器逐个执行。如下图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/001-b7c0094d.png"&gt;&lt;/p&gt;
&lt;p&gt;至于 Redis 的其他功能， 比如持久化、异步删除、集群数据同步等等，其实是由额外的线程执行的。 可以这么说，Redis 工作线程是单线程的。但是在 4.0 之后，对于整个 Redis 服务来说，还是多线程运作的。&lt;/p&gt;
&lt;h2 id="60-之前为什么要使用单线程"&gt;&lt;a href="#60-%e4%b9%8b%e5%89%8d%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e4%bd%bf%e7%94%a8%e5%8d%95%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;6.0 之前为什么要使用单线程
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/002-55bc246f.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在使用 Redis 时，Redis 主要受限是在内存和网络上，CPU 几乎没有性能瓶颈的问题。&lt;/li&gt;
&lt;li&gt;以 Linux 系统为例子，在 Linux 系统上 Redis 通过 pipelining 可以处理 100w 个请求每秒，而应用程序的计算复杂度主要是 O(N) 或 O(log(N)) ，不会消耗太多 CPU。&lt;/li&gt;
&lt;li&gt;使用了单线程后，提高了可维护性。多线程模型在某些方面表现优异，却增加了程序执行顺序的不确定性，并且带来了并发读写的一系列问题，增加了系统复杂度。同时因为线程切换、加解锁，甚至死锁，造成一定的性能损耗。&lt;/li&gt;
&lt;li&gt;Redis 通过 AE 事件模型以及 IO 多路复用等技术，拥有超高的处理性能，因此没有使用多线程的必要&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="60-之后的多线程主要解决什么问题"&gt;&lt;a href="#60-%e4%b9%8b%e5%90%8e%e7%9a%84%e5%a4%9a%e7%ba%bf%e7%a8%8b%e4%b8%bb%e8%a6%81%e8%a7%a3%e5%86%b3%e4%bb%80%e4%b9%88%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;6.0 之后的多线程主要解决什么问题
&lt;/h2&gt;&lt;p&gt;近年来底层网络硬件性能越来越好，Redis 的性能瓶颈逐渐体现在网络 I/O 的读写上，单个线程处理网络 I/O 读写的速度跟不上底层网络硬件执行的速度。&lt;/p&gt;
&lt;p&gt;Redis 在处理网络数据时，调用 epoll 的过程是阻塞的，这个过程会阻塞线程。如果并发量很高，达到万级别的 QPS，就会形成瓶颈，影响整体吞吐能力&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/003-e1c54fcd.png"&gt;&lt;/p&gt;
&lt;p&gt;既然读写网络的 read/write 系统调用占用了 Redis 执行期间大部分 CPU 时间，那么要想真正做到提速，必须改善网络 IO 性能。我们可以从这两个方面来优化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提高网络 IO 性能，典型实现方式比如使用 DPDK 来替代内核网络栈的方式&lt;/li&gt;
&lt;li&gt;使用多线程，这样可以充分利用多核 CPU，同类实现案例比如 Memcached。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;协议栈优化的这种方式跟 Redis 关系不大，所以最便捷高效的方式就是支持多线程。总结起来，redis 支持多线程就是以下两个原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以充分利用服务器 CPU 的多核资源，而主线程明显只能利用一个&lt;/li&gt;
&lt;li&gt;多线程任务可以分摊 Redis 同步 IO 读写负荷，降低耗时&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;6.0 版本优化之后，主线程和多线程网络 IO 的执行流程如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/004-51bc3556.png"&gt;&lt;/p&gt;
&lt;p&gt;具体步骤如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主线程建立连接，并接受数据，并将获取的 socket 数据放入等待队列；&lt;/li&gt;
&lt;li&gt;通过轮询的方式将 socket 读取出来并分配给 IO 线程；&lt;/li&gt;
&lt;li&gt;之后主线程保持阻塞，一直等到 IO 线程完成 socket 读取和解析；&lt;/li&gt;
&lt;li&gt;I/O 线程读取和解析完成之后，返回给主线程 ，主线程开始执行 Redis 命令；&lt;/li&gt;
&lt;li&gt;执行完 Redis 命令后，主线程阻塞，直到 IO 线程完成 结果回写到 socket 的工作；&lt;/li&gt;
&lt;li&gt;主线程清空已完成的队列，等待客户端新的请求。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本质上是将主线程 IO 读写的这个操作 独立出来，单独交给一个 I/O 线程组处理。
这样多个 socket 读写可以并行执行，整体效率也就提高了。同时注意 Redis 命令还是主线程串行执行。&lt;/p&gt;
&lt;p&gt;利用多核来分担 I/O 读写负荷。在事件处理线程每次获取到可读事件时，会将所有就绪的读事件分配给 I/O 线程，并进行等待，在所有 I/O 线程完成读操作后，事件处理线程开始执行任务处理，在处理结束后，同样将写事件分配给 I/O 线程，等待所有 I/O 线程完成写操作。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;int handleClientsWithPendingReadsUsingThreads(void) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; /* Distribute the clients across N different lists. */
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; listIter li;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; listNode *ln;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; listRewind(server.clients_pending_read,&amp;amp;li);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; int item_id = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; // 将等待处理的客户端分配给 I/O 线程
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; while((ln = listNext(&amp;amp;li))) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; client *c = listNodeValue(ln);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; int target_id = item_id % server.io_threads_num;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; listAddNodeTail(io_threads_list[target_id],c);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; item_id++;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; /* Wait for all the other threads to end their work. */
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; // 轮训等待所有 I/O 线程处理完
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; while(1) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; unsigned long pending = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; for (int j = 1; j &amp;lt; server.io_threads_num; j++)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; pending += io_threads_pending[j];
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; if (pending == 0) break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt; return processed;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;本质上是利用多核的多线程让多个 IO 的读写加速。&lt;/p&gt;
&lt;h3 id="局限性"&gt;&lt;a href="#%e5%b1%80%e9%99%90%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;局限性
&lt;/h3&gt;&lt;p&gt;6.0 版本的多线程并非彻底的多线程，I/O 线程只能同时执行读或者同时执行写操作，期间事件处理线程一直处于等待状态，并非流水线模型，有很多轮训等待开销。&lt;/p&gt;</description></item><item><title>如何用 30秒和 5 行代码写个 RAG 应用？</title><link>https://xiaobox.github.io/p/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/</link><pubDate>Mon, 30 Sep 2024 16:17:06 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/cover.jpg" alt="Featured image of post 如何用 30秒和 5 行代码写个 RAG 应用？" /&gt;&lt;p&gt;花 30 秒用 5 行代码写个 RAG 应用&lt;/p&gt;
&lt;p&gt;这个点子不是我想出来的，是 llamaindex 想出来的。llamaindex 是啥？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LlamaIndex 是一个框架，用于使用 llm（包括 agents 和 workflows）构建上下文增强的生成式人工智能应用程序。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当然也包括创建 RAG 应用，因为最流行的上下文增强示例就是 RAG（Retrieval-Augmented Generation， RAG），也就是在推理时将上下文与 llm 结合起来的检索增强。&lt;/p&gt;
&lt;p&gt;如果是对 RAG 还不了解的朋友，那么可以参考之前几篇文章中的相关介绍：&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://mp.weixin.qq.com/s?__biz=MzI3Njk5ODg4OQ==&amp;amp;mid=2247489151&amp;amp;idx=1&amp;amp;sn=2f2dc98798b88399322f5be8dd253057&amp;amp;chksm=eb6da9f9dc1a20efe6dc6ae4bf52eeb8c8521c4164f50941881fddf49093a5425810abbcf325&amp;amp;scene=21#wechat_redirect" target="_blank" rel="noopener"
 &gt;RAG 实践-Ollama+AnythingLLM 搭建本地知识库&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="http://mp.weixin.qq.com/s?__biz=MzI3Njk5ODg4OQ==&amp;amp;mid=2247489440&amp;amp;idx=1&amp;amp;sn=5a25f4ee0c5c29de6a6c1b9d4aca19ee&amp;amp;chksm=eb6da826dc1a2130d3549a8e629dca81b45c3733005c2fa173e04d66d8c64560856effeae0c9&amp;amp;scene=21#wechat_redirect" target="_blank" rel="noopener"
 &gt;RAG（检索增强生成）系统的问题及解决思路&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;简单来说：RAG（Retrieval-Augmented Generation）是一种结合检索和生成技术的人工智能方法，通过从外部知识源检索相关信息，增强语言模型的生成能力，提高输出的准确性和相关性。&lt;/p&gt;
&lt;h2 id="llamaindex"&gt;&lt;a href="#llamaindex" class="header-anchor"&gt;&lt;/a&gt;LlamaIndex
&lt;/h2&gt;&lt;p&gt;在进入正题前，关于 LlamaIndex 我还是要再多说几句。&lt;/p&gt;
&lt;p&gt;LlamaIndex 是一个开源框架：https://github.com/run-llama/llama_index&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;它是用 &lt;code&gt;Python&lt;/code&gt; 写的&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/001-3d0fc37b.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最新版本是：&lt;code&gt;0.11.14&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/002-d8af0b28.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;官网地址是：&lt;code&gt;https://www.llamaindex.ai/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/003-1eed1656.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在今年夏天的某个会议上，从 LlamaIndex 团队成员那儿得知，他们是一个规模很小的创业公司，当时团队成员大概 15 人左右。&lt;/p&gt;
&lt;h2 id="30-秒-5-行代码"&gt;&lt;a href="#30-%e7%a7%92-5-%e8%a1%8c%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;30 秒 5 行代码
&lt;/h2&gt;&lt;p&gt;前文说了 30 秒 5 行代码的主意不是我想到的，而是来源于 LlamaIndex ，具体说是 LlamaIndex 的文档中写的：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/004-cca65b59.png"&gt;&lt;/p&gt;
&lt;p&gt;事实也的确如此，但是，这里有一些前提条件。&lt;/p&gt;
&lt;p&gt;首先，从字面上你也能看出来，运行这 5 行代码需要 &lt;code&gt;OpenAI&lt;/code&gt; 的 API key。&lt;/p&gt;
&lt;p&gt;其次，无论你懂不懂编程，我告诉你这 5 行代码是 &lt;code&gt;Python&lt;/code&gt; 语言写的。那么你要有一个 &lt;code&gt;Python&lt;/code&gt; 语言的运行环境，以及你最好懂得如何用 &lt;code&gt;Python&lt;/code&gt; 编程。关于这一点，对于不懂编程的朋友确实不太友好了。不过值得庆幸的是，&lt;code&gt;Python&lt;/code&gt; 语言本身很强大，很好上手，容易学习。门槛并不算太高。虽然我们要开发的应用是跟人工智能（AI）相关的，但也不要被吓到了，以为会多么难。其实有很大一部分所谓的 AI 产品也只是 AI、大模型的应用产品。开发那些产品的工程师甚至也只是能算是大模型应用开发工程师，还用不到多么艰深的技术呢。（&lt;strong&gt;这里并没有拉踩的意思，只是客观表述。能把技术应用的很好，做出满足用户需求的创新性产品也是非常有价值的，做出这样产品的人也当然值得尊重&lt;/strong&gt;）&lt;/p&gt;
&lt;h3 id="安装-python"&gt;&lt;a href="#%e5%ae%89%e8%a3%85-python" class="header-anchor"&gt;&lt;/a&gt;安装 Python
&lt;/h3&gt;&lt;p&gt;我们先解决 &lt;code&gt;Python&lt;/code&gt; 的问题，对于已经熟练掌握 &lt;code&gt;Python&lt;/code&gt; 开发的就可以跳过了。对于编程小白或其他语言开发者（如 Java） 可以看看。&lt;/p&gt;
&lt;p&gt;我们得搭建一个 &lt;code&gt;Python&lt;/code&gt; 的开发和运行环境。关于 &lt;code&gt;Python&lt;/code&gt; 的安装网上教程一大堆，无论你的操作系统是 Windows、Mac 还是 Linux 都很容易。我就不罗嗦了。&lt;/p&gt;
&lt;p&gt;我的操作系统是 MacOS, 后文的具体操作细节都是基于我本地的 Mac 电脑，所以请大家注意，下图是我的的电脑系统情况：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/005-fbb462bd.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; 比较常见的大版本有 &lt;code&gt;Python2&lt;/code&gt; 和 &lt;code&gt;Python3&lt;/code&gt; , 我使用的版本是 &lt;code&gt;Python3&lt;/code&gt;，具体来说是 &lt;code&gt;3.12.4&lt;/code&gt; 算是个比较新的版本了&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/006-548175e5.png"&gt;&lt;/p&gt;
&lt;p&gt;关于 &lt;code&gt;Python&lt;/code&gt; 的安装，我更建议用 &lt;code&gt;Conda&lt;/code&gt; ，它可以创建多个不同 &lt;code&gt;Python&lt;/code&gt; 版本的环境，相当于一个 &lt;code&gt;Python&lt;/code&gt; 环境和版本管理工具。这样你就可以创建多个不同 &lt;code&gt;Python&lt;/code&gt; 版本的环境，相互之间隔离，互不影响。因为有时候不同的项目用到不同的 &lt;code&gt;Python&lt;/code&gt; 版本，混在一起比较麻烦，有了 &lt;code&gt;Conda&lt;/code&gt; 就方便多了。&lt;/p&gt;
&lt;p&gt;Conda 可以到这里下载安装：https://docs.anaconda.com/free/miniconda/&lt;/p&gt;
&lt;p&gt;安装好以后记得设置一下镜像源，不然下载比较慢：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro/ 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;conda config --set show_channel_urls yes
&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" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;//创建虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;conda create -n xinference python=3.11.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;//激活虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;conda activate xinference
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;//退出虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;conda deactivate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;//删除虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;conda remove -n xinference --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;//查看虚拟环境
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;conda env list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; 安装好以后，我们还需要一个开发工具，即 IDE，你可以选择 &lt;code&gt;VSCode&lt;/code&gt;,&lt;code&gt;PyCharm&lt;/code&gt;,&lt;code&gt;Cursor&lt;/code&gt;,&lt;code&gt;Zed&lt;/code&gt; 等等。这里我推荐 &lt;code&gt;Cursor&lt;/code&gt;，因为借用 claude 及 gpt 等大模型的能力，你可以一边快速开发一边快速学习，高效产出的同时高效吸收，简直太爽啦。&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/007-4a4f0c2a.png"&gt;&lt;/p&gt;
&lt;h3 id="学习-python"&gt;&lt;a href="#%e5%ad%a6%e4%b9%a0-python" class="header-anchor"&gt;&lt;/a&gt;学习 Python
&lt;/h3&gt;&lt;p&gt;关于 &lt;code&gt;Python&lt;/code&gt; 的学习，我这里对于特别小白的，尤其是从来没有接触过编程的朋友没有什么具体的建议，因为我从未指导过类似情况的朋友，所以没有经验，不能乱说，怕误人子弟。因为我既不知道用什么样的方式也不知道用什么样的资料指导有用。不过我觉得对于小白，能持续学习下去是最重要的，不要找太难的资料，可以找一些你容易上手，容易看懂的资料来学习，有持续的正反馈，计算机相关的知识很多，有些确实难懂，有持续的正反馈你才不至于半途而废。&lt;/p&gt;
&lt;p&gt;而对于其他语言的开发者，其实已经具备了基础的计算机知识，甚至也已经是某些编程语言的专家了。那么学习 &lt;code&gt;Python&lt;/code&gt; 对于你来说就比较容易了，一理通百理明。都大差不差的。&lt;/p&gt;
&lt;p&gt;我这里把之前收藏的一些学习资料分享一下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/jackfrued/Python-for-Freshmen-2023" target="_blank" rel="noopener"
 &gt;https://github.com/jackfrued/Python-for-Freshmen-2023&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/jackfrued/Python-100-Days" target="_blank" rel="noopener"
 &gt;https://github.com/jackfrued/Python-100-Days&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/walter201230/Python" target="_blank" rel="noopener"
 &gt;https://github.com/walter201230/Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.fullstackpython.com" target="_blank" rel="noopener"
 &gt;https://www.fullstackpython.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;认认真真把其中一个资料看完。&lt;strong&gt;一般来说，用 2 个星期，每天 1-2 个小时左右，快的话甚至一个星期你就能基本掌握这门语言了。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我知道很多朋友不满足只是基本掌握，想更精进，那么就需要再加码了，这里我推荐系统地看一些书，因为书籍会相对系统地讲解知识，这样你对 &lt;code&gt;Python&lt;/code&gt; 以及 &lt;code&gt;Python&lt;/code&gt; 相关的技术就会有一个全面而深入的了解了。&lt;/p&gt;
&lt;p&gt;说实话我看的书并不多，也不好意思过多推荐，这里推荐一本我最喜欢的，豆瓣 9.1 分。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/008-2c47ea4f.png"&gt;&lt;/p&gt;
&lt;p&gt;写得确实很好，很实用，不讲虚的。读起来也很流畅、舒服。是市面上难得的原创 &lt;code&gt;Python&lt;/code&gt; 进阶图书。&lt;/p&gt;
&lt;h3 id="编程"&gt;&lt;a href="#%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;编程
&lt;/h3&gt;&lt;p&gt;现在我们假设你已经有了一个 &lt;code&gt;Python&lt;/code&gt; 的运行环境及开发工具。那么接下来我们就要正式开始编写这 5 行代码了（铺垫这么多终于要写代码了～）&lt;/p&gt;
&lt;p&gt;首先我们要建一个工程，这很简单，不多说。&lt;/p&gt;
&lt;p&gt;然后根据文档所示，我们要安装 &lt;code&gt;llama-index&lt;/code&gt; 的依赖包，在项目根路径下执行&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;pip install llama-index
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;当然，如果你使用的是 &lt;code&gt;Python3&lt;/code&gt; ，可以这样安装：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;pip3 install llama-index
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装好依赖包以后我们创建 main.py 文件，并编写程序：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_query_engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Some question about the data should go here&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&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;
&lt;p&gt;&lt;strong&gt;第一个问题是&lt;/strong&gt;：如果你直接运行 main.py 这个文件会报错，错误总结来说就是你没有 &lt;code&gt;OpenAI&lt;/code&gt; 的 Api Key 。是啊，我们压根就没有设置，其实我也不想设置，因为这个 key 是要花钱的，我不想花钱，那怎么办？&lt;/p&gt;
&lt;p&gt;用 &lt;code&gt;OPENAI_API_KEY&lt;/code&gt; 的目的就是要通过 &lt;code&gt;OpenAI&lt;/code&gt; 的 API 调用 &lt;code&gt;OpenAI&lt;/code&gt; 的大语言模型。我们知道那是收费的，所以我们要用开源免费的模型，将模型安装到本地使用，这样就不用花钱了。所以我们要用 &lt;code&gt;Ollama&lt;/code&gt; 安装开源模型到本地进行调用。关于 &lt;code&gt;Ollama&lt;/code&gt; 以及模型的安装我在之前的文章中有详细说明，这里就不赘述了。大家可以参考。&lt;a class="link" href="http://mp.weixin.qq.com/s?__biz=MzI3Njk5ODg4OQ==&amp;amp;mid=2247489151&amp;amp;idx=1&amp;amp;sn=2f2dc98798b88399322f5be8dd253057&amp;amp;chksm=eb6da9f9dc1a20efe6dc6ae4bf52eeb8c8521c4164f50941881fddf49093a5425810abbcf325&amp;amp;scene=21#wechat_redirect" target="_blank" rel="noopener"
 &gt;RAG 实践-Ollama+AnythingLLM 搭建本地知识库&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;我这里下载使用的是 &lt;code&gt;Qwen2:7b&lt;/code&gt; 的模型&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/009-74fbf1b3.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二个问题是&lt;/strong&gt;：代码中的 &lt;code&gt;data&lt;/code&gt; 在哪里&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;data 是一个文件夹，需要我们在项目的根路径下创建，名字就叫 &lt;code&gt;data&lt;/code&gt;。而在 data 文件夹中我们是要下载测试文本的，通过这个地址下载测试文本：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://raw.githubusercontent.com/run-llama/llama" target="_blank" rel="noopener"
 &gt;https://raw.githubusercontent.com/run-llama/llama&lt;/a&gt;_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;文件类型当然就是 .txt 文件。原文是英文的，但因为我想做中文的测试，所以，我把内容全部翻译成了中文并保存。（如果你看过《黑客与画家》 这本书，你一定会对文本内容感兴趣的！） 这个文件的文件名你可以随意取。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三个问题是&lt;/strong&gt;：用哪个 &lt;code&gt;embedding&lt;/code&gt; 模型？&lt;/p&gt;
&lt;p&gt;前面我们说了，我们不用 &lt;code&gt;OpenAI&lt;/code&gt; 的 API 了，这样的话，其实整个代码结构会发生变化 ，就不是原始的那 5 行代码了，而会变成下面这样（别担心，只多了一行）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt; &lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;huggingface&lt;/span&gt; &lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ollama&lt;/span&gt; &lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bge-base embedding model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embed_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BAAI/bge-base-en-v1.5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ollama&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;llama3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;360.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到代码中写的 &lt;code&gt;embedding&lt;/code&gt; 模型是 &lt;code&gt;BAAI/bge-base-en-v1.5&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;接触过 RAG 的朋友对 &lt;code&gt;embedding&lt;/code&gt; 模型比较熟悉，这里简单地为不了解的朋友解释一下：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Embedding 模型是将离散的输入（如单词或文档）转换为连续向量表示的模型，在 RAG 中用于将查询和检索到的文档片段映射到同一向量空间，以便计算相似度和生成相关响应。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它和 RAG 的关系，可以参考下图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/010-2e3cae67.png"&gt;&lt;/p&gt;
&lt;p&gt;我们这 5 行代码想实现的就是 RAG，所以一定少不了 &lt;code&gt;embedding&lt;/code&gt; 模型。&lt;code&gt;embedding&lt;/code&gt; 模型也分收费的和开源免费的，另外上文中提到的 &lt;code&gt;BAAI/bge-base-en-v1.5&lt;/code&gt; 是一个处理英文的模型，我想处理的是中文，所以不适用。我们要找一个免费开源且支持中文的 &lt;code&gt;embedding&lt;/code&gt; 模型。到哪里找呢？Hugging Face!（Hugging Face 你可以把它理解成大模型领域的 GitHub）&lt;/p&gt;
&lt;p&gt;从 Hugging Face 上可以找到大量的开源免费的 &lt;code&gt;embedding&lt;/code&gt; 模型，数量很多，选哪一个呢？我们可以从 &lt;a class="link" href="https://huggingface.co/spaces/mteb/leaderboard" target="_blank" rel="noopener"
 &gt;https://huggingface.co/spaces/mteb/leaderboard&lt;/a&gt; 这个大规模文本嵌入基准（MTEB）排行榜中，根据你的需求来挑选。&lt;/p&gt;
&lt;p&gt;比如我选择的是支持中文的，模型大小不是特别大的&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/011-d95f597e.png"&gt;&lt;/p&gt;
&lt;p&gt;最终我选择的模型是 ：&lt;code&gt;BAAI/bge-base-zh-v1.5&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;以上三个问题都解决了以后，我们看一下最终的代码成品：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.embeddings.huggingface&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.llms.ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embed_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BAAI/bge-base-zh-v1.5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;qwen2:7b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;360.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_query_engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;作者学习过的编程语言有哪些？&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实话实说，是比 5 行多了 2 行。但也已经很精练了，因为这是 LlamaIndex 做过高级别封装以后的 API，如果想做具体而细致的编程控制，可以使用低级别封装的 API。&lt;/p&gt;
&lt;p&gt;代码我没有写注释，因为是想让读者看看它有多精练。用 LlamaIndex 就这么简单，几行代码就可以实现 RAG 了。&lt;/p&gt;
&lt;p&gt;以下是我加入注释以后的，方便你理解它：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.embeddings.huggingface&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.llms.ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 从指定目录加载文档数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 设置嵌入模型，使用北京智源人工智能研究院的中文嵌入模型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embed_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BAAI/bge-base-zh-v1.5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 设置语言模型，使用 Ollama 提供的 Qwen2 7B 模型，并设置请求超时时间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;qwen2:7b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;360.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使用加载的文档创建向量存储索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 从索引创建查询引擎&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_query_engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使用查询引擎执行特定查询&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;作者学习过的编程语言有哪些？&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 打印查询结果&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行这段代码会自动下载 &lt;code&gt;embedding&lt;/code&gt; 模型，你可能会关心模型下载到哪里了，在我电脑上是这个路径 ：&lt;code&gt;～/Library/Caches/llama_index&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;代码 第一次执行时间比较长，大概有个几十秒。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/012-92563e3b.png"&gt;&lt;/p&gt;
&lt;p&gt;但再次执行应该是有缓存了，就会比较快了，下图就只执行了 10 秒左右。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-30-ru-he-yong-30-miao-he-5-xing-dai-ma-xie-ge-rag-ying-yong/013-e926c405.png"&gt;&lt;/p&gt;
&lt;p&gt;当然，你还可以基于测试文本进行其他查询，看看它分析的是否准确。&lt;/p&gt;
&lt;p&gt;以上图片中的输出每一步都有时间，是因为我对程序做了重构，用装饰器加上了每一步执行时间的打印输出，代码如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wraps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.embeddings.huggingface&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.llms.ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;time_it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@wraps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 耗时：&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.2f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 秒&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IndexBuilder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@time_it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@time_it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_embed_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embed_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HuggingFaceEmbedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BAAI/bge-base-zh-v1.5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@time_it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_llm_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Ollama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;qwen2:7b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;360.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@time_it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@time_it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;37&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_query_engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;38&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;39&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;40&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@time_it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;41&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;42&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IndexBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;43&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;44&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_documents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;45&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_embed_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;46&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_llm_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;47&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;48&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;49&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;50&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;作者跟 Sam 的关系是怎样的？&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;51&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;52&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;查询结果：&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;53&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;54&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;55&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;56&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;由于后续除了 LlamaIndex 又安装了几个依赖库，所以在项目根路径下创建了 requirements.txt 文件，文件内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;llama-index
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;python-dotenv
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;llama-index-llms-ollama
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;llama-index-embeddings-huggingface
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;执行以下命令一次性安装所有依赖：&lt;code&gt;pip3 install -r requirements.txt&lt;/code&gt; 这样方便一些。&lt;/p&gt;
&lt;h2 id="rag-应用创建完成"&gt;&lt;a href="#rag-%e5%ba%94%e7%94%a8%e5%88%9b%e5%bb%ba%e5%ae%8c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;RAG 应用创建完成
&lt;/h2&gt;&lt;p&gt;有了以上的代码基础，其实一个小型的 RAG 应用的核心就完成了，我可以基于本地知识库结合大语言模型进行自然语言的查询了。&lt;/p&gt;
&lt;p&gt;比如我问：“&lt;strong&gt;作者跟 Sam 的关系是怎样的？&lt;/strong&gt;”&lt;/p&gt;
&lt;p&gt;回答是：“&lt;strong&gt;作者与 Sam Altman 的关系是在 2013 年决定让他成为 YC（Y Combinator）的总裁。在那之前，他们可能有某种工作或业务上的联系，因为他们讨论了重组 YC 并让 Sam 接任总裁职位的事情。通过这个决策，可以看出作者认为 Sam 适合领导 YC，并且在 Sam 最初拒绝后，作者坚持不懈地说服他接受这一角色。最终，在 2013 年 10 月，Sam 同意从 2014 年冬季开始接管 YC。这表明两人之间有某种程度的合作和信任关系。&lt;/strong&gt;”&lt;/p&gt;
&lt;p&gt;你看，基于本地知识库的回答比单纯用 LLM 靠谱多了吧。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;然后呢？&lt;/strong&gt; 是的，我们只有一个内核还远远不够，我们还需要漂亮的 UI，更加易用和丰富的功能，程序性能还要强，把它做成一个产品。然后产品还要宣传、推广、积累用户、产品迭代。我们还要赚钱，还要考虑如何盈利。&amp;hellip;..&lt;/p&gt;
&lt;p&gt;差不多了，真的。想到这里，你再看看市面上那些 AI 产品是不是相似的配方？&lt;/p&gt;
&lt;h2 id="最后"&gt;&lt;a href="#%e6%9c%80%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;最后
&lt;/h2&gt;&lt;p&gt;行文至此，关于这 5 行代码的事情我觉得已经说清楚了。最后感慨一下：AI 赛道真是越来越卷了，但无论无何，感谢 &lt;code&gt;Python&lt;/code&gt; , 感谢 &lt;code&gt;LlamaIndex&lt;/code&gt; ，感谢开源和为开源做出贡献的人们。有了他们我们才能够如此享受技术带来的红利。&lt;/p&gt;</description></item><item><title>还在用 top htop? 赶紧换 btop 吧，真香！</title><link>https://xiaobox.github.io/p/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/</link><pubDate>Tue, 17 Sep 2024 03:35:33 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/cover.jpg" alt="Featured image of post 还在用 top htop? 赶紧换 btop 吧，真香！" /&gt;&lt;h2 id="top"&gt;&lt;a href="#top" class="header-anchor"&gt;&lt;/a&gt;top
&lt;/h2&gt;&lt;p&gt;在 Linux 服务器上，或类 Unix 的机器上，一般我们想查看每个进程的 CPU 使用率、内存使用情况以及其他相关信息时会使用 top 命令。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/001-8b55ddd9.png"&gt;&lt;/p&gt;
&lt;p&gt;top 是一个标准的 Linux/Unix 工具，实际上我从一开始接触 Linux 就一直使用 top , 一般是两种场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux 服务器上用&lt;/li&gt;
&lt;li&gt;自己的 Mac 电脑上用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;top 有一些常用的功能，比如可以动态的显示进程的情况，按照 CPU 、内存使用率排序等。说实话，这么多年了，使用最多的还就是 top ，一来是因为习惯了，工具用惯了很多操作都是肌肉记忆。二来是 top 一般系统自带不用安装，省事儿。&lt;/p&gt;
&lt;h2 id="htop"&gt;&lt;a href="#htop" class="header-anchor"&gt;&lt;/a&gt;htop
&lt;/h2&gt;&lt;p&gt;top 挺好的，但 top 对于初学者和小白用户不太友好，尤其是它的用户界面和操作。于是后来有了 htop&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/002-b91d4627.png"&gt;&lt;/p&gt;
&lt;p&gt;htop 是 top 的一个增强替代品，提供了更加友好的用户界面和更多的功能。与 top 相比，htop 默认以颜色区分不同的信息，并且支持水平滚动查看更多的进程信息。htop 还允许用户使用方向键来选择进程，并可以直接发送信号给进程（如 SIGKILL）。htop 支持多种视图和配置选项，使得用户可以根据自己的喜好定制显示的内容。&lt;/p&gt;
&lt;p&gt;htop 我也用了几年，确实舒服一些，但由于需要安装和我对 top 的肌肉记忆 ，htop 在我的使用中并未完全替代 top。直到 btop 的出现&lt;/p&gt;
&lt;h2 id="btop"&gt;&lt;a href="#btop" class="header-anchor"&gt;&lt;/a&gt;btop
&lt;/h2&gt;&lt;p&gt;现在，我本机使用的是 btop，有了 btop，top 和 htop 一点儿都不想用了，哈哈。&lt;/p&gt;
&lt;p&gt;在服务器上有时候因为懒不想安装，一部分时间还是 top，一部分用 btop。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/003-4fc781d1.png"&gt;&lt;/p&gt;
&lt;p&gt;第一印象是真漂亮啊，然而它不止好看，功能也是很实用，操作还很简单，你说能不喜欢它吗？&lt;/p&gt;
&lt;p&gt;说是 btop ，实际上人家真正的名字是 btop++ , 用 C++ 开发的&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/004-e864c170.png"&gt;&lt;/p&gt;
&lt;h3 id="安装"&gt;&lt;a href="#%e5%ae%89%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;安装
&lt;/h3&gt;&lt;p&gt;btop 支持各种类 Unix 系统，你可以在它的文档中找到对应系统的安装方法 &lt;a class="link" href="https://github.com/aristocratos/btop" target="_blank" rel="noopener"
 &gt;https://github.com/aristocratos/btop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/005-e7fdf7ee.png"&gt;&lt;/p&gt;
&lt;p&gt;本文演示，我是用我自己的 Mac 笔记本电脑，用 Mac 安装很简单，用 brew 一行搞定&lt;/p&gt;
&lt;p&gt;&lt;code&gt;brew install btop &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;我的系统情况是这样的：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/006-1cdea30e.png"&gt;&lt;/p&gt;
&lt;p&gt;安装完成后，直接运行 &lt;code&gt;btop&lt;/code&gt; 就可以看到如上图的界面了。&lt;/p&gt;
&lt;h3 id="功能界面"&gt;&lt;a href="#%e5%8a%9f%e8%83%bd%e7%95%8c%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;功能界面
&lt;/h3&gt;&lt;p&gt;打开 btop 后不要被它的界面唬住了，其实非常的简单，我们来介绍一下。&lt;/p&gt;
&lt;p&gt;打开 btop 后，其实显示的是它给你的 “预置” 界面。默认有 4 个预置界面，你可以按 &lt;code&gt;p&lt;/code&gt; 键进行切换。命令行界面上会分别显示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;preset 0&lt;/li&gt;
&lt;li&gt;preset 1&lt;/li&gt;
&lt;li&gt;preset 2&lt;/li&gt;
&lt;li&gt;preset 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/007-f896ac8c.png"&gt;&lt;/p&gt;
&lt;p&gt;你可能注意到了，这 4 个预置界面中有很多内容是重复的，没错，其实 btop 一共就 4 个模块，预置界面只是把不同的模块拼在一起显示罢了。这 4 个模块分别是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPU 模块&lt;/li&gt;
&lt;li&gt;存储 模块&lt;/li&gt;
&lt;li&gt;网络 模块&lt;/li&gt;
&lt;li&gt;进程 模块&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这 4 个模块对应的快捷键分别就是 &lt;code&gt;1&lt;/code&gt;，&lt;code&gt;2&lt;/code&gt;，&lt;code&gt;3&lt;/code&gt;，&lt;code&gt;4&lt;/code&gt; 你按一下模块显示，再按一下模块隐藏。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/008-838380bb.png"&gt;&lt;/p&gt;
&lt;p&gt;所以如果你对预置界面的内容想立刻调整，就可以按快捷键来显示/隐藏 你想要的模块，当然预置界面也是可以通过配置文件调整的，这个我们后面说。&lt;/p&gt;
&lt;h3 id="cpu-模块"&gt;&lt;a href="#cpu-%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;CPU 模块
&lt;/h3&gt;&lt;p&gt;CPU 模块可以显示 CPU 型号、各内核的使用率、温度，CPU 整体的负载，以及一个直观的图象，所有数据都是实时显示的。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/009-ef0561ee.png"&gt;&lt;/p&gt;
&lt;h3 id="存储-模块"&gt;&lt;a href="#%e5%ad%98%e5%82%a8-%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;存储 模块
&lt;/h3&gt;&lt;p&gt;存储模块包括两部分，一个是内存使用情况，一个是磁盘使用情况：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/010-34e5ee3c.png"&gt;&lt;/p&gt;
&lt;p&gt;因为比较直观，具体内容我就不解释了。&lt;/p&gt;
&lt;h3 id="网络模块"&gt;&lt;a href="#%e7%bd%91%e7%bb%9c%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;网络模块
&lt;/h3&gt;&lt;p&gt;网络模块可以看下网络的整体负载和吞吐情况，主要包括上行和下行数据汇总，你可以通过按快捷键 &lt;code&gt;b&lt;/code&gt;和&lt;code&gt;n&lt;/code&gt; 来切换看不同的网卡。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/011-31fca377.png"&gt;&lt;/p&gt;
&lt;h3 id="进程模块"&gt;&lt;a href="#%e8%bf%9b%e7%a8%8b%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;进程模块
&lt;/h3&gt;&lt;p&gt;初始的进程模块可以看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pid&lt;/li&gt;
&lt;li&gt;Program: 进程名称&lt;/li&gt;
&lt;li&gt;Command: 执行命令的路径&lt;/li&gt;
&lt;li&gt;Threads: 进程包含的线程数&lt;/li&gt;
&lt;li&gt;User: 启动进程的用户&lt;/li&gt;
&lt;li&gt;MemB: 进程所占用内存&lt;/li&gt;
&lt;li&gt;Cpu%: 进程所占用 CPU 百分比&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/012-a3cad264.png"&gt;&lt;/p&gt;
&lt;p&gt;你可以按快捷键 &lt;code&gt;e&lt;/code&gt; 显示树状视图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/013-f647b540.png"&gt;&lt;/p&gt;
&lt;p&gt;可以按快捷键 &lt;code&gt;r&lt;/code&gt; 对进行排序，按一下是倒序，再按一下是正序。具体排序列可以按&lt;code&gt;左右箭头&lt;/code&gt;，根据界面显示进行选择，比如我要按照内存使用排序，那么右上角就是这样的：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/014-c54dab64.png"&gt;&lt;/p&gt;
&lt;p&gt;按 &lt;code&gt;f&lt;/code&gt; 键输入你想过滤的内容然后回车，可以过滤一下界面显示的内容，比如我只想看 chrome 的进程情况：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/015-0f03ba62.png"&gt;&lt;/p&gt;
&lt;p&gt;还可以通过 上下箭头选中某一个进程按回车查看进程详情，再次按回车可以隐藏详情：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/016-2eecbd46.png"&gt;&lt;/p&gt;
&lt;p&gt;显示进程详情后可以对进程进行操作，比如 &lt;code&gt;Kill&lt;/code&gt; 只需要按快捷键 &lt;code&gt;k&lt;/code&gt; 就可以了，然后会弹出提示：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/017-87c8e117.png"&gt;&lt;/p&gt;
&lt;h3 id="主题"&gt;&lt;a href="#%e4%b8%bb%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;主题
&lt;/h3&gt;&lt;p&gt;怎么样，是不是很方便，操作简单，上手容易，还好看。关于 btop 的主要操作就这些了，剩下的可以参考 &lt;code&gt;help&lt;/code&gt; 和 &lt;code&gt;menu&lt;/code&gt; 中显示的内容自行操作和设置都很简单。&lt;/p&gt;
&lt;p&gt;btop 的配置文件默认在这里：&lt;code&gt;$HOME/.config/btop&lt;/code&gt; ，你可以直接修改配置文件中的详细参数，如我们前文提到的 “预置” 界面以及预置界面内容都可以在配置文件中设置 ：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/018-cbd33297.png"&gt;&lt;/p&gt;
&lt;p&gt;此外 btop 还有很多好看的主题配色，但默认安装的情况下只带了一个 &lt;code&gt;Default&lt;/code&gt; 的，如果你想切换用其他的主题，需要先下载这些主题，主题文件在这里：https://github.com/aristocratos/btop/tree/main/themes&lt;/p&gt;
&lt;p&gt;下载好以后放到本地对应的文件夹中 &lt;code&gt;~/.config/btop/themes&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;然后你就可以要界面上进行主题的切换了，具体流程是先按快捷键 &lt;code&gt;m&lt;/code&gt; ，然后选 OPTIONS&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/019-9b019758.png"&gt;&lt;/p&gt;
&lt;p&gt;接着在 Color theme 中就能看到你当前拥有的 theme 数据，按方向键就可以切换主题配色了：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/020-f1050548.png"&gt;&lt;/p&gt;
&lt;p&gt;主题有很多，我这里给大家一个完整的预览：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-17-hai-zai-yong-top-htop-gan-jin-huan-btop-ba-zhen-xiang/021-9d21672b.jpg"&gt;&lt;/p&gt;
&lt;p&gt;我目前使用的就是 &lt;code&gt;Default&lt;/code&gt; 我觉得最符合我的审美。&lt;/p&gt;
&lt;h2 id="最后"&gt;&lt;a href="#%e6%9c%80%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;最后
&lt;/h2&gt;&lt;p&gt;用了 btop 后你就再也回不去了，一般情况下再也不会想用 htop 和 top 了，大家没有换的可以直接换了&lt;/p&gt;</description></item><item><title>一文帮你解决 Linux 发行版 “选择困难症”</title><link>https://xiaobox.github.io/p/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/</link><pubDate>Thu, 12 Sep 2024 08:21:56 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/cover.jpg" alt="Featured image of post 一文帮你解决 Linux 发行版 “选择困难症”" /&gt;&lt;p&gt;工作关系，今天要买一批云服务器。打开熟悉的阿里云，到选择操作系统这项的时候我停了下来，因为我发现现在的 linux 发行版是真多呀，阿里云默认显示的公共镜像就这么多：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/001-8404d19d.png"&gt;&lt;/p&gt;
&lt;p&gt;10年前几乎闭眼选择 CentOS 的时代一去不复返了。那么到底应该选择哪个发行版呢？所以干脆写篇文章来盘点一下这些 linux 发行版&lt;/p&gt;
&lt;p&gt;对了，你可能发现我直接忽略了 &lt;code&gt;Windows Server&lt;/code&gt; ，是的，因为 90% 以上的服务器选择安装 linux 操作系统。&lt;/p&gt;
&lt;h3 id="linux-发行版和-linux-内核之间的关系"&gt;&lt;a href="#linux-%e5%8f%91%e8%a1%8c%e7%89%88%e5%92%8c-linux-%e5%86%85%e6%a0%b8%e4%b9%8b%e9%97%b4%e7%9a%84%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;Linux 发行版和 Linux 内核之间的关系
&lt;/h3&gt;&lt;p&gt;先把最基本的概念弄清楚：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux 内核是操作系统的核心部分,由 Linus Torvalds 最初开发并持续维护。它负责管理硬件资源、提供系统调用等最基本的功能。&lt;/li&gt;
&lt;li&gt;Linux 发行版是在 Linux 内核基础上,添加了各种系统软件、应用程序、配置工具等,组成的&lt;strong&gt;完整可用的操作系统&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;发行版的主要工作是 ：1）选择特定版本的 Linux 内核、2）添加各种系统软件和应用程序、 3）开发独特的安装程序和系统管理工具 4）提供技术支持和更新&lt;/p&gt;
&lt;p&gt;常见的发行版有 Ubuntu、Fedora、CentOS、Debian 等。所有 Linux 发行版都使用 Linux 内核作为核心,遵循 GNU 通用公共许可证。&lt;/p&gt;
&lt;h2 id="流行的-linux-发行版"&gt;&lt;a href="#%e6%b5%81%e8%a1%8c%e7%9a%84-linux-%e5%8f%91%e8%a1%8c%e7%89%88" class="header-anchor"&gt;&lt;/a&gt;流行的 Linux 发行版
&lt;/h2&gt;&lt;p&gt;排名不分先后，虽然前文上图中有阿里云的 &lt;code&gt;Alibaba Cloud Linux&lt;/code&gt; 但因为云平台自身利益关系，它的排名和推广不代表流行程度，所以我这里忽略它。&lt;/p&gt;
&lt;h3 id="anolis-os"&gt;&lt;a href="#anolis-os" class="header-anchor"&gt;&lt;/a&gt;Anolis OS
&lt;/h3&gt;&lt;p&gt;Anolis OS 可能没有其他发行版那么知名，它是是由阿里云开发，但 AnolisOS 仍然是开源的，遵循开源许可，所以我这里也要提一下，支持开源社区&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/002-f7bdcd78.png"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;Anolis OS 8 是 OpenAnolis 社区推出的完全开源、中立、开放的发行版，它支持多计算架构，也面向云端场景优化，兼容 CentOS 软件生态&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;简单说，AnolisOS 是基于 CentOS 进行的二次开发，所以如果你更熟悉 CentOS，又讨厌现在 RedHat 对 CentOS 的最新政策，那么可以试一试它。不过选择操作系统还是要谨慎，毕竟基础设施运维起来有坑的话都是大坑，哈哈。&lt;/p&gt;
&lt;h3 id="centos"&gt;&lt;a href="#centos" class="header-anchor"&gt;&lt;/a&gt;CentOS
&lt;/h3&gt;&lt;p&gt;这个我们可得好好说说，可以说是大家最熟悉的 Linux 发行版了。为什么呢？&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/003-3a72632d.png"&gt;&lt;/p&gt;
&lt;p&gt;最初红帽公司开发了企业级付费的 linux 操作系统：Red Hat Enterprise Linux (RHEL)。CentOS 本身是 RHEL 的一个免费开源复制版。这对于广大开发者和系统使用者可是件大好事，因为有企业级付费产品冲在前线做质量保障，CentOS 直接跟在屁股后面复制成果做免费开源，当时的 Red Hat 简直是IT界的赛博菩萨。CentOS 也成为了很多公司服务器操作系统的不二之选 。&lt;/p&gt;
&lt;p&gt;然而：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;CentOS 7已于2024年6月30日停止维护，CentOS官方已停止维护CentOS计划。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;CentOS 没了？倒也不是，Red Hat 更新了产品策略。旧的 CentOS 确实不再维护了，不是不能用，是不再维护了，如果操作系统有bug 可没人管了哈。所以选择老版本的CentOS需要谨慎。&lt;/p&gt;
&lt;p&gt;新版的 CentOS 叫 &lt;code&gt;CentOS Stream&lt;/code&gt; ，别看就多了个 Stream，情况却大不一样。与之前的 RHEL 在前，CentOS 在后相比，这次 Red Hat是这么设计的：CentOS Stream 仍然开源，但它是在第一线的，而 RHEL这次反过来是在 CentOS Stream的后面享受开源的成果。说白了，让社区的开发给 CentOS Stream 提feature 改 bug，RHEL 在后面积累成果卖钱。让大家给 Red Hat 打工。&lt;/p&gt;
&lt;p&gt;总结来说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;原来 Centos 是 RHEL 的下游复制品。CentOS（在转变前）紧跟 RHEL 的发布节奏&lt;/li&gt;
&lt;li&gt;现在 CentOS Stream 是 RHEL的 上游产品。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当然工也不是白打，你不也用人家的操作系统了嘛。&lt;/p&gt;
&lt;p&gt;相比前后两种策略，大家心里跟明镜似的，越来越多的人不再选择 CentOS 了，虽然出了bug 有社区维护，但相比之前有个靠谱商业付费产品做基础，保障少多了，担心多多了。运维也不想加班呀。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;事情发展到这里还没有结束，因为大家不禁要问，CentOS 一直所坚持的开源精神呢？难道这精神没有继续者吗？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;有！！&lt;/p&gt;
&lt;p&gt;Gregory Kurtzer 站了出来。&lt;/p&gt;
&lt;p&gt;CentOS 的原始创始人 Gregory Kurtzer 发起了 &lt;code&gt;Rocky Linux&lt;/code&gt; 项目，目标是创建一个与 RHEL 100% 兼容的下游版本，旨在成为 CentOS 的精神继承者。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/004-2bb83c0c.png"&gt;&lt;/p&gt;
&lt;p&gt;还有！！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;AlmaLinux&lt;/code&gt; 由 CloudLinux 公司发起，同样旨在提供一个与 RHEL 完全兼容的免费替代品。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/005-410d9f2d.png"&gt;&lt;/p&gt;
&lt;p&gt;开源的精神没有覆灭，Rocky Linux 和 AlmaLinux 都是 RHEL 的下源产品，如果你想找到一个 CentOS 的替代品，那么这两个发行版可能会很适合你。&lt;/p&gt;
&lt;h3 id="red-hat-enterprise-linux"&gt;&lt;a href="#red-hat-enterprise-linux" class="header-anchor"&gt;&lt;/a&gt;Red Hat Enterprise Linux
&lt;/h3&gt;&lt;p&gt;红帽公司著名产品：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/006-3f2a7b17.png"&gt;&lt;/p&gt;
&lt;p&gt;前文多次提到它，收费，稳定，天下没有花钱的不是，一分钱一分货。但确实是贵啊（相比开源免费）。。。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/007-fcb58ee4.png"&gt;&lt;/p&gt;
&lt;h3 id="suse-linux"&gt;&lt;a href="#suse-linux" class="header-anchor"&gt;&lt;/a&gt;SUSE Linux
&lt;/h3&gt;&lt;p&gt;又是一个和 RHEL 齐名的付费产品&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/008-c2af8427.png"&gt;&lt;/p&gt;
&lt;p&gt;但它开始的时候也是一个有志青年，是不收费的。&lt;/p&gt;
&lt;p&gt;早期（1992-2003）：SUSE 最初是一个开源项目，提供免费版本。被 Novell 收购后，仍保留了开源版本 openSUSE。从 Novell 分离后，SUSE 成为独立公司，开始更注重商业模式。&lt;/p&gt;
&lt;p&gt;现在 ，SUSE Linux Enterprise（SLE）是付费的企业版本。openSUSE 仍然是免费开源的社区版本。&lt;/p&gt;
&lt;p&gt;SUSE 和 RHEL 在技术和使用上的区别挺多的，但我感觉最大的区别是 SUSE 在欧洲市场较强，特别是在 SAP 环境中。如果欧洲企业中有使用 OpenStack 和 SAP 的，那么愿意为操作系统付费的企业很可能选择的就是 SUSE。&lt;/p&gt;
&lt;h3 id="fedora"&gt;&lt;a href="#fedora" class="header-anchor"&gt;&lt;/a&gt;Fedora
&lt;/h3&gt;&lt;p&gt;在 Fedora 7 之前，Fedora 的名字是“Fedora Core”，之后就简称为 Fedora&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/009-ead6550c.png"&gt;&lt;/p&gt;
&lt;p&gt;Fedora 是一个快速发展的、面向技术爱好者的 Linux 发行版。&lt;/p&gt;
&lt;p&gt;Fedora 是 RHEL 的上游项目之一。RHEL 的开发团队会从 Fedora 社区中吸取一些新的特性和改进，然后根据企业的需要进行调整和完善。因此，可以说 Fedora 在某种程度上影响了 RHEL 的发展方向。看了前文的读者读到这里是不是已经熟悉 RedHat 的套路了？所以你在选择操作系统上也要掌握点儿 “反套路” 才行。&lt;/p&gt;
&lt;h3 id="debian"&gt;&lt;a href="#debian" class="header-anchor"&gt;&lt;/a&gt;Debian
&lt;/h3&gt;&lt;p&gt;与 RHEL 不同，Debian 是纯社区驱动的项目。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/010-ab7ecf9d.png"&gt;&lt;/p&gt;
&lt;p&gt;Debian 有较长的发布周期，注重稳定性，这是它的优势也是劣势。较长的发布周期可能导致软件版本较旧。&lt;/p&gt;
&lt;p&gt;Debian 稳定版通常包含较旧但经过充分测试的软件。但 Debian 对新手来说可能不够友好&lt;/p&gt;
&lt;p&gt;可能最为人熟知的就是包管理系统&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Debian 使用 APT（Advanced Package Tool）和 .deb 包格式。&lt;/li&gt;
&lt;li&gt;CentOS 使用 YUM/DNF 和 .rpm 包格式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ubuntu"&gt;&lt;a href="#ubuntu" class="header-anchor"&gt;&lt;/a&gt;Ubuntu
&lt;/h3&gt;&lt;p&gt;这个发行版大家也很熟悉，你看，一般大家比较熟悉的发行版做的都比较好，不然不会有那么多人喜欢它。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-12-yi-wen-bang-ni-jie-jue-linux-fa-xing-ban-xuan-ze-kun-nan-zhe/011-5dcb222f.png"&gt;&lt;/p&gt;
&lt;p&gt;Ubuntu 是一个基于 Debian 的 Linux 发行版，由 Canonical Ltd. 公司维护和支持。我们上文刚才了 Debian的一些问题，比如发布周期长，对新手不友好等，Ubuntu 就有针对性的解决了这些问题：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;Ubuntu 的目标是提供一个稳定、用户友好的操作系统，并且它特别注重易用性和社区支持。Ubuntu 每六个月发布一个新版本，其中每隔两年会有一个长期支持（LTS）版本，提供长达五年的安全更新和技术支持。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;这里我们不禁要比较一下 Debian和 Ubuntu(&lt;strong&gt;我肯定选后者啦&lt;/strong&gt;) ：Ubuntu 基于 Debian，因此两者共享许多软件包。然而，Debian 更加注重稳定性和安全性，更新周期更长；而 Ubuntu 则更注重易用性和最新技术的应用。&lt;/p&gt;
&lt;p&gt;还是列举一下 Ubuntu的优缺点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;更新频繁，软件包较新&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;强大的社区支持&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;良好的桌面和服务器体验&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;丰富的文档和资源&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;与 RHEL 生态系统不兼容&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在，越来越多的运维同学选择 Ubuntu 作为服务器的操作系统，我觉得可能有这么几点原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ubuntu 对各种硬件的支持非常广泛，这对于新的发行版来说是一个重要优势。&lt;/li&gt;
&lt;li&gt;Ubuntu 在容器技术和云计算方面有很好的支持&lt;/li&gt;
&lt;li&gt;Ubuntu 拥有庞大的用户和开发者社区，这意味着丰富的资源、文档和第三方支持。&lt;/li&gt;
&lt;li&gt;Ubuntu 的六个月发布周期和长期支持版本（LTS）提供了良好的平衡，可以根据需要选择稳定性或新特性。&lt;/li&gt;
&lt;li&gt;Ubuntu 的 APT 包管理系统强大且用户友好，便于管理和定制软件包。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;本文我们讨论了在购买云服务器时面临众多 Linux 发行版选择的问题。随着 CentOS 7 的停止维护以及 CentOS Stream 成为 RHEL 的上游版本，过去直接选择 CentOS 的做法已不再适用。我们提到了几个主要的 Linux 发行版，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anolis OS：阿里云开发的开源发行版，基于 CentOS 进行了二次开发，兼容 CentOS 生态。&lt;/li&gt;
&lt;li&gt;CentOS：曾经作为 RHEL 的下游复制品，现已转变为 RHEL 的上游版本 CentOS Stream，不再作为 RHEL 的直接复制品。&lt;/li&gt;
&lt;li&gt;Rocky Linux 和 AlmaLinux：作为 CentOS 的精神继承者，这两个发行版提供了与 RHEL 完全兼容的免费替代品。&lt;/li&gt;
&lt;li&gt;Red Hat Enterprise Linux (RHEL)：商业化的 Linux 发行版，提供企业级支持和服务。&lt;/li&gt;
&lt;li&gt;SUSE Linux：与 RHEL 类似的商业发行版，在欧洲市场尤其是 SAP 环境中较为流行。&lt;/li&gt;
&lt;li&gt;Fedora：快速发展的发行版，作为 RHEL 的上游项目，为 RHEL 提供技术创新。&lt;/li&gt;
&lt;li&gt;Debian：社区驱动的发行版，注重稳定性和安全性，但软件版本可能较旧。&lt;/li&gt;
&lt;li&gt;Ubuntu：基于 Debian，注重易用性和最新技术的应用，每六个月发布一次新版本，并提供 LTS 版本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后我说一下我个人 对 linux 发行版的选择排序：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rocky Linux &amp;gt; Ubuntu &amp;gt; AlmaLinux &amp;gt; CentOS Stream&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>IP地址的多种书写方式</title><link>https://xiaobox.github.io/p/2024-08-30-ip-di-zhi-de-duo-zhong-shu-xie-fang-shi/</link><pubDate>Fri, 30 Aug 2024 02:36:04 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-08-30-ip-di-zhi-de-duo-zhong-shu-xie-fang-shi/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-30-ip-di-zhi-de-duo-zhong-shu-xie-fang-shi/cover.jpg" alt="Featured image of post IP地址的多种书写方式" /&gt;&lt;p&gt;当我们提及 IP 地址，大多数人首先想到的是那种我们习以为常的形式：如 127.0.0.1、10.0.2.1 等。这些由数字和点组成的串，在日复一日的使用中，或许已经变得有些单调乏味。但你是否知道，IP 地址并非只能以这种方式呈现？事实上，它拥有多种书写方式，这些不同的形式不仅可以为我们带来乐趣，更能在某些特定场合发挥出意想不到的作用。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-30-ip-di-zhi-de-duo-zhong-shu-xie-fang-shi/001-a87f4f9b.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、IP 地址的常规书写与潜在变化&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在大多数情况下，我们使用的 IP 地址都是点分十进制格式，即由四个 0-255 之间的数字组成，数字之间用点号分隔。这种格式简单明了，易于理解和记忆。然而，这种常规的书写方式背后，其实隐藏着一些不为人知的秘密。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二、零的可选性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先，让我们来看一个有趣的例子。&lt;/p&gt;
&lt;p&gt;在 Linux 系统中，输入&lt;code&gt;ping 0&lt;/code&gt;，你会发现它实际上被解析为&lt;code&gt;127.0.0.1&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; 56&lt;span class="o"&gt;(&lt;/span&gt;84&lt;span class="o"&gt;)&lt;/span&gt; bytes of data.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 127.0.0.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.053 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 127.0.0.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.037 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但在 Mac 系统中，同样的命令却会返回一个错误，提示无法找到目标主机。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.0.0.0&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;ping: sendto: No route to host
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是因为，在不同的操作系统中，对于 IP 地址中零的处理方式可能存在差异。&lt;/p&gt;
&lt;p&gt;再来看另一个例子：&lt;code&gt;ping 127.1&lt;/code&gt;。这个命令在大多数系统中会被解析为&lt;code&gt;127.0.0.1&lt;/code&gt;，系统会自动在数字前补零。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping 127.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING 127.1 &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 127.0.0.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.033 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 127.0.0.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.085 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但请注意，这并不意味着计算机可以随意猜测并填充零。例如，&lt;code&gt;ping 10.50.1&lt;/code&gt;会被解析为&lt;code&gt;10.50.0.1&lt;/code&gt;，而不是&lt;code&gt;10.50.1.0&lt;/code&gt;或其他形式。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping 10.50.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING 10.50.1 &lt;span class="o"&gt;(&lt;/span&gt;10.50.0.1&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;Request timeout &lt;span class="k"&gt;for&lt;/span&gt; icmp_seq &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是因为 IP 地址的结构是固定的，每个部分都有其特定的含义和范围。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三、IP 地址的“溢出”技巧&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;除了零的可选性外，我们还可以利用 IP 地址的“溢出”特性来玩一些小把戏。例如，&lt;code&gt;ping 10.0.513&lt;/code&gt;这个命令，在大多数系统中会被解析为&lt;code&gt;10.0.2.1&lt;/code&gt;。这是因为 IP 地址的每个部分都是一个 8 位的二进制数，最大值为 255。当超过这个值时，它会自动“溢出”并从零开始重新计数。在这个例子中，513 被解析为 2x256+1，即 257，但由于 IP 地址每部分的取值范围是 0-255，所以它实际上被解析为 2，再加上前面的 10.0.0，就得到了 10.0.2.1。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping 10.0.513
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING 10.0.513 &lt;span class="o"&gt;(&lt;/span&gt;10.0.2.1&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 10.0.2.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.189 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 10.0.2.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;58.119 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种“溢出”技巧不仅可以用于娱乐和恶作剧，还可以在某些特定场合发挥出实际作用。例如，在网络安全领域，攻击者可能会利用这种技巧来绕过一些基于 IP 地址的过滤和限制。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;四、十进制、十六进制与八进制的 IP 表示&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;除了我们常见的点分十进制格式外，IP 地址还可以用其他进制来表示。例如，我们可以使用十进制数来表示一个 IP 地址。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping &lt;span class="m"&gt;167772673&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING &lt;span class="m"&gt;167772673&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;10.0.2.1&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 10.0.2.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15.441 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 10.0.2.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4.627 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如上文提到的&lt;code&gt;ping 167772673&lt;/code&gt;，这个十进制数实际上就是&lt;code&gt;10.0.2.1&lt;/code&gt;的另一种表现形式。这种表示方法在某些编程和网络调试场景中可能会更加方便。&lt;/p&gt;
&lt;p&gt;具体来说：167772673 在十进制下转换为二进制是 &lt;code&gt;00001010000000000000001000000001&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这个二进制数可以按照每 8 位一组分割为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;00001010&lt;/li&gt;
&lt;li&gt;00000000&lt;/li&gt;
&lt;li&gt;00000010&lt;/li&gt;
&lt;li&gt;00000001&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;分别转换为十进制数为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10&lt;/li&gt;
&lt;li&gt;0&lt;/li&gt;
&lt;li&gt;2&lt;/li&gt;
&lt;li&gt;1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同样地，十六进制也是 IP 地址的一种常见表示方式。例如，&lt;code&gt;ping 0xA000201&lt;/code&gt;这个命令中的&lt;code&gt;0xA000201&lt;/code&gt;就是一个十六进制数，它同样表示的是&lt;code&gt;10.0.2.1&lt;/code&gt;。在计算机科学中，十六进制是一种常用的表示方式，因为它可以更紧凑地表示较大的数字，并且与二进制之间的转换相对简单。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping 0xA000201
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING 0xA000201 &lt;span class="o"&gt;(&lt;/span&gt;10.0.2.1&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 10.0.2.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7.329 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;64&lt;/span&gt; bytes from 10.0.2.1: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;18.350 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;此外，我们还可以使用八进制来表示 IP 地址。虽然这种方式在实际应用中相对较少见，但它同样具有一定的理论和实际意义。例如，&lt;code&gt;ping 10.0.2.010&lt;/code&gt;这个命令中的&lt;code&gt;.010&lt;/code&gt;实际上就是八进制数 8，所以这个命令最终会被解析为&lt;code&gt;10.0.2.8&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ ping 10.0.2.010
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;PING 10.0.2.010 &lt;span class="o"&gt;(&lt;/span&gt;10.0.2.8&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="m"&gt;56&lt;/span&gt; data bytes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;五、使用 Sipcalc 工具进行 IP 地址转换&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对于需要进行大量 IP 地址转换的场景，我们可以借助一些工具来简化操作。其中，&lt;code&gt;sipcalc&lt;/code&gt; （https://github.com/sii/sipcalc）就是一个非常实用的命令行 IP 地址计算器。它可以方便地进行十进制、十六进制等不同进制之间的转换，并且提供了丰富的输出格式和选项。&lt;/p&gt;
&lt;p&gt;使用&lt;code&gt;sipcalc&lt;/code&gt;工具，我们可以轻松地将一个 IP 地址从一种格式转换为另一种格式。例如，要将十进制数&lt;code&gt;167772673&lt;/code&gt;转换为点分十进制格式，我们可以输入相应的命令并得到结果&lt;code&gt;10.0.2.1&lt;/code&gt;。同样地，我们也可以将一个点分十进制格式的 IP 地址转换为其他进制表示形式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;六、IP 地址书写方式的多样性与应用场景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;除了上述提到的几种 IP 地址书写方式外，还有一些其他不太常见但同样有趣的表示方法。这些方法或许在日常使用中并不常见，但在某些特定场合却能发挥出意想不到的作用。&lt;/p&gt;
&lt;p&gt;例如，在网络安全领域，攻击者可能会利用 IP 地址的不同书写方式来绕过一些基于规则的过滤和检测系统。他们可能会使用一些特殊格式的 IP 地址来隐藏真实的攻击目标或规避安全策略。&lt;/p&gt;
&lt;p&gt;此外，在网络编程和调试过程中，灵活运用 IP 地址的不同书写方式也可以为我们带来便利。例如，在编写网络应用程序时，我们可能需要根据不同的需求和环境选择最合适的 IP 地址表示形式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;七、如何防范 IP 地址欺骗与攻击&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;虽然 IP 地址的不同书写方式为我们带来了乐趣和便利，但与此同时也带来了一定的安全风险。特别是当攻击者利用这些技巧进行 IP 地址欺骗和攻击时，后果将不堪设想。&lt;/p&gt;
&lt;p&gt;为了防范这些潜在的安全威胁，我们可以采取以下措施：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;使用防火墙和安全策略&lt;/strong&gt;：配置防火墙和安全策略来限制对特定 IP 地址或 IP 地址范围的访问。这样可以有效防止未经授权的访问和攻击。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;验证 IP 地址来源&lt;/strong&gt;：在进行网络通信和数据交换时，务必验证对方的 IP 地址来源和真实性。不要轻易相信来自未知或可疑来源的 IP 地址信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;定期更新系统和软件&lt;/strong&gt;：及时更新操作系统、应用程序和安全补丁以修复可能存在的安全漏洞。这样可以降低被攻击的风险并提高系统的安全性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;加强网络安全培训&lt;/strong&gt;：提高员工和用户的网络安全意识培训，让他们了解常见的网络攻击手段和防范措施。这样可以形成一道坚实的网络安全防线。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;八、结语&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过本文的介绍和分析，我们可以看到 IP 地址并非只能以常规的点分十进制格式呈现。除了这种常见形式外，它还可以用其他多种方式来表示和书写。这些不同的书写方式不仅为我们带来了乐趣和便利，更在某些特定场合发挥出意想不到的作用。&lt;/p&gt;
&lt;p&gt;然而，与此同时我们也需要注意防范这些不同书写方式可能带来的安全风险。通过采取适当的安全措施和策略，我们可以有效降低潜在的安全威胁并保障网络安全。&lt;/p&gt;
&lt;p&gt;最后，希望这篇文章能为你带来一些新的启示和思考。如果你对 IP 地址或其他网络安全话题感兴趣，欢迎继续关注和探索更多有趣的内容！&lt;/p&gt;</description></item><item><title>容器编排工具的演进：从 Docker 到 Kubernetes</title><link>https://xiaobox.github.io/p/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/</link><pubDate>Sat, 10 Aug 2024 05:18:45 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/cover.jpg" alt="Featured image of post 容器编排工具的演进：从 Docker 到 Kubernetes" /&gt;&lt;p&gt;在现代应用部署中，Docker 和其他容器引擎为服务器端应用程序的部署提供了极大的便利。然而，随着应用和服务数量的增加，管理这些容器变得越来越困难。这催生了一类被称为容器编排器的工具，其中最为知名的莫过于 Kubernetes。容器编排的历史可以分为 Kubernetes 出现之前和之后两个阶段。&lt;/p&gt;
&lt;h4 id="容器的便利与妥协"&gt;&lt;a href="#%e5%ae%b9%e5%99%a8%e7%9a%84%e4%be%bf%e5%88%a9%e4%b8%8e%e5%a6%a5%e5%8d%8f" class="header-anchor"&gt;&lt;/a&gt;容器的便利与妥协
&lt;/h4&gt;&lt;p&gt;容器的使用虽然便利，但也带来了一些妥协。严格遵循 Docker 的理念，每个服务都应有其独立的容器，这将导致运行大量的容器。即使是一个简单的数据库网页界面，也可能需要分别运行数据库服务器、应用程序，以及可能包括用于处理静态文件的 Web 服务器、用于终止 SSL/TLS 连接的代理服务器、用作缓存的键值存储，甚至用于处理后台作业和计划任务的第二个应用程序容器。&lt;/p&gt;
&lt;p&gt;负责多个此类应用程序的管理员很快就会意识到，需要一个工具来简化管理任务，这时容器编排工具应运而生。容器编排器可以将多个容器作为一个单元来管理，并将多个服务器结合成一个集群，自动分配容器工作负载到集群节点中。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/001-b1b8ce49.png"&gt;&lt;/p&gt;
&lt;h4 id="docker-compose-与-swarm"&gt;&lt;a href="#docker-compose-%e4%b8%8e-swarm" class="header-anchor"&gt;&lt;/a&gt;Docker Compose 与 Swarm
&lt;/h4&gt;&lt;p&gt;Docker Compose 虽然不完全是一个编排器，但它是 Docker 首次尝试创建的工具，用于更轻松地管理由多个容器组成的应用程序。它使用 YAML 格式的文件，通常命名为&lt;code&gt;docker-compose.yml&lt;/code&gt;。Compose 读取该文件，并使用 Docker API 创建所需的资源，同时为所有资源添加标签，以便在创建后作为一组进行管理。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/002-eea10afc.png"&gt;&lt;/p&gt;
&lt;p&gt;Compose 文件中可以定义三种资源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;服务（services）：&lt;/strong&gt; 包含要启动的容器声明。每个条目相当于一个&lt;code&gt;docker run&lt;/code&gt;命令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网络（networks）：&lt;/strong&gt; 声明可以附加到容器的网络。每个条目相当于一个&lt;code&gt;docker network create&lt;/code&gt;命令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;卷（volumes）：&lt;/strong&gt; 定义可以附加到容器的命名卷。每个条目相当于一个&lt;code&gt;docker volume create&lt;/code&gt;命令。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compose 提供了一种更方便的方式来管理由多个容器组成的应用程序，但在其最初版本中，它仅支持单个主机；所有创建的容器都在同一台机器上运行。为了扩展到多个主机，Docker 在 2016 年引入了 Swarm 模式。这是 Docker 的第二个名为“Swarm”的产品，前一个产品于 2014 年推出，采用了完全不同的方法在多个主机上运行容器，但现在已不再维护。&lt;/p&gt;
&lt;p&gt;Swarm 模式包含在 Docker 中，无需额外的软件即可使用。创建集群只需在初始节点上运行&lt;code&gt;docker swarm init&lt;/code&gt;，然后在每个其他节点上运行&lt;code&gt;docker swarm join&lt;/code&gt;。Swarm 集群包含两种类型的节点：管理节点和工作节点。管理节点提供 API 以在集群上启动容器，并使用基于 Raft 一致性算法的协议进行通信，以在所有管理节点之间同步集群状态。工作节点则负责运行容器。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/003-62b1f381.png"&gt;&lt;/p&gt;
&lt;p&gt;通过 Compose 文件在 Swarm 上部署服务。Swarm 通过为每个服务添加一个&lt;code&gt;deploy&lt;/code&gt;键扩展了 Compose 格式，该键指定服务应该运行的实例数量及其运行的节点。然而，这导致 Compose 和 Swarm 之间出现了一些分歧，某些选项如 CPU 和内存配额需要根据使用的工具以不同的方式指定。在此分歧期间，为 Swarm 准备的文件被称为“堆栈文件”而非 Compose 文件，幸好这些差异在当前版本的 Swarm 和 Compose 中已被平滑处理，Compose 格式现在有一个开放规范及其 GitHub 组织提供的参考实现。&lt;/p&gt;
&lt;p&gt;关于 Swarm 的未来存在一些不确定性。它曾经是名为 Docker Cloud 的服务的骨干，但该服务在 2018 年突然关闭。它还被宣传为 Docker 企业版的关键特性，但该产品已售予另一家公司，现以 Mirantis Kubernetes Engine 的名义进行市场推广。同时，最新版本的 Compose 已经获得了将容器部署到 Amazon 和 Microsoft 托管服务的能力。虽然没有宣布弃用，但最近也没有任何其他类型的公告；在 Docker 网站上搜索“Swarm”一词，仅能找到一些提及。&lt;/p&gt;
&lt;h4 id="kubernetes"&gt;&lt;a href="#kubernetes" class="header-anchor"&gt;&lt;/a&gt;Kubernetes
&lt;/h4&gt;&lt;p&gt;Kubernetes（有时称为 k8s）是受 Google 内部工具 Borg 启发的项目。Kubernetes 管理资源并协调在多达数千个节点的集群上运行工作负载；它在容器编排领域的统治地位如同 Google 在搜索领域的统治地位。Google 曾在 2014 年希望与 Docker 在 Kubernetes 开发上合作，但 Docker 决定走自己的路，发展 Swarm。相反，Kubernetes 在云原生计算基金会（CNCF）的支持下成长。到 2017 年，Kubernetes 的流行度已高到 Docker 宣布将其集成到 Docker 产品中。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/004-3033a01c.png"&gt;&lt;/p&gt;
&lt;p&gt;Kubernetes 以其复杂性而闻名。手动设置一个新集群是一项繁杂的任务，除了 Kubernetes 本身外，管理员还需选择和配置若干第三方组件。就像 Linux 内核需要结合其他软件以构成完整的操作系统一样，Kubernetes 仅是一个编排器，需结合其他软件以构成完整的集群。它需要容器引擎来运行其容器，还需要网络和持久化卷的插件。&lt;/p&gt;
&lt;p&gt;Kubernetes 发行版存在以填补这一空白。像 Linux 发行版一样，Kubernetes 发行版将 Kubernetes 与安装程序和精选的第三方组件捆绑在一起。不同的发行版存在以满足不同的需求；几乎每家规模一定的科技公司都有其自己的发行版和/或托管产品，以迎合企业需求。minikube 项目为开发者提供了一个更简便的本地实验环境。&lt;/p&gt;
&lt;h3 id="kubernetes-的组成结构"&gt;&lt;a href="#kubernetes-%e7%9a%84%e7%bb%84%e6%88%90%e7%bb%93%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;Kubernetes 的组成结构
&lt;/h3&gt;&lt;p&gt;一个 Kubernetes 集群包含多个软件组件。集群中的每个节点都会运行一个称为 kubelet 的代理，以保持集群成员资格并接受来自集群的工作，容器引擎，以及用于启用与其他节点上运行的容器进行网络通信的 kube-proxy。&lt;/p&gt;
&lt;p&gt;保持集群状态并对资源分配做出决策的组件被统称为控制平面，这包括一个分布式键值存储（etcd），一个将工作分配给集群节点的调度器，以及一个或多个控制器进程，这些进程对集群状态的变化做出反应，并触发任何必要的操作以使实际状态与所需状态相匹配。用户和集群节点通过 Kubernetes API 服务器与控制平面进行交互。为了实现变更，用户通过 API 服务器设置集群的期望状态，而 kubelet 将每个集群节点的实际状态报告给控制器进程。&lt;/p&gt;
&lt;p&gt;Kubernetes 在一个称为 Pod 的抽象中运行容器，Pod 可以包含一个或多个容器，尽管不建议在一个 Pod 中运行多个服务的容器。相反，通常一个 Pod 会有一个提供服务的主容器，可能还有一个或多个“sidecar”容器，用于从主容器中运行的服务收集指标或日志。Pod 中的所有容器都会一起调度在同一台机器上，并共享一个网络命名空间——在同一个 Pod 中运行的容器可以通过回环接口互相通信。每个 Pod 在集群内都会收到一个唯一的 IP 地址。在不同 Pod 中运行的容器可以使用它们的集群 IP 地址相互通信。&lt;/p&gt;
&lt;p&gt;一个 Pod 指定了一组要运行的容器，但 Pod 的定义并没有说明要在哪些地方运行这些容器，或运行多久——在没有这些信息的情况下，Kubernetes 会在集群中某处启动容器，但不会在它们退出时重新启动它们，并可能在控制平面决定其他工作负载需要它们使用的资源时突然终止它们。因此，Pod 很少单独使用；相反，Pod 的定义通常被封装在一个 Deployment 对象中，用于定义一个持久化服务。像 Compose 和 Swarm 一样，Kubernetes 管理的对象是在 YAML 中声明的；对于 Kubernetes，这些 YAML 声明通过 kubectl 工具提交到集群。&lt;/p&gt;
&lt;p&gt;除了 Pod 和 Deployment，Kubernetes 还可以管理许多其他类型的对象，例如负载均衡器和授权策略。支持的 API 列表在不断演变，且会因运行的 Kubernetes 版本和集群运行的发行版而有所不同。自定义资源可以用来向集群添加 API 以管理其他类型的对象。例如，KubeVirt 增加了 API 以使 Kubernetes 能够运行虚拟机。可以使用 kubectl api-versions 命令发现特定集群支持的 API 的完整列表。&lt;/p&gt;
&lt;p&gt;与 Compose 不同的是，每个对象是在一个单独的 YAML 文档中声明的，尽管可以通过在同一文件中用“&amp;mdash;”分隔它们内联多个 YAML 文档，如 Kubernetes 文档中所示。一个复杂的应用程序可能由多个对象组成，其定义分布在多个文件中；在维护此类应用程序时保持所有这些定义同步可能相当繁琐。为了使这项工作更容易，一些 Kubernetes 管理员转向了模板工具如 Jsonnet。&lt;/p&gt;
&lt;h4 id="helm-与应用部署"&gt;&lt;a href="#helm-%e4%b8%8e%e5%ba%94%e7%94%a8%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;&lt;/a&gt;Helm 与应用部署
&lt;/h4&gt;&lt;p&gt;Helm 进一步推进了模板化的方法。与 Kubernetes 一样，Helm 的开发在 CNCF 的支持下进行；它被誉为“Kubernetes 的包管理器”。Helm 从一组称为 chart 的模板和变量声明集合中生成 Kubernetes 的 YAML 配置。其模板语言与 Ansible 的 Jinja 模板不同，但看起来非常相似；熟悉 Ansible 角色的人可能会对 Helm 图表感到得心应手。&lt;/p&gt;
&lt;p&gt;Helm 图表的集合可以在 Helm 存储库中发布；Artifact Hub 提供了一个公共 Helm 存储库的大型目录。管理员可以将这些存储库添加到他们的 Helm 配置中，并使用现成的 Helm 图表将预打包的流行应用程序版本部署到他们的集群。最近版本的 Helm 还支持将图表推送和拉取到容器注册表中，从而为管理员提供了将图表存储在与容器镜像相同位置的选项。&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/005-c4704500.png"&gt;&lt;/p&gt;
&lt;p&gt;Kubernetes 在短期内没有失去势头的迹象。它被设计为可以管理任何类型的资源；这种灵活性，如通过 KubeVirt 虚拟机控制器所示，即使容器化工作负载最终失宠，它也有可能保持相关性。开发进展迅速，定期发布新版本。版本支持为期一年；似乎没有长期支持版本。支持集群升级，但一些人更愿意建立一个新集群并迁移他们的服务。&lt;/p&gt;
&lt;h4 id="nomad-的简单替代方案"&gt;&lt;a href="#nomad-%e7%9a%84%e7%ae%80%e5%8d%95%e6%9b%bf%e4%bb%a3%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;Nomad 的简单替代方案
&lt;/h4&gt;&lt;p&gt;Nomad 是 HashiCorp 推出的编排器，作为 Kubernetes 的简单替代方案进行营销。Nomad 是一个开源项目，像 Docker 和 Kubernetes 一样。它由一个名为 nomad 的二进制文件组成，可用于启动一个称为代理的守护程序，并作为 CLI 与代理进行通信。根据其配置方式，代理进程可以以两种模式之一运行。在服务器模式下运行的代理接受作业并为它们分配集群资源。在客户端模式下运行的代理与服务器联系以接收作业、运行它们，并向服务器报告其状态。代理还可以在开发模式下运行，在这种模式下，它同时承担客户端和服务器的角色，形成一个可用于测试目的的单节点集群。&lt;/p&gt;
&lt;p&gt;创建一个 Nomad 集群可能相当简单。在 Nomad 的最基本操作模式下，必须启动初始服务器代理，然后可以使用 nomad server join 命令将其他节点添加到集群中。HashiCorp 还提供了 Consul，这是一种通用服务网格和发现工具。虽然可以单独使用，但 Nomad 与 Consul 结合使用时可能表现最佳。Nomad 代理可以使用 Consul 自动发现和加入集群，并且可以执行健康检查、提供 DNS 记录以及为集群上运行的服务提供 HTTPS 代理。&lt;/p&gt;
&lt;p&gt;Nomad 支持复杂的集群拓扑。每个集群分为一个或多个“数据中心”。与 Swarm 类似，单个数据中心内的服务器代理使用一种基于 Raft 的协议进行通信；该协议具有严格的延迟要求，但多个数据中心可以使用一种允许信息在集群中传播的流言协议链接在一起，而无需每个服务器都与每个其他服务器保持直接连接。从用户的角度来看，以这种方式链接在一起的数据中心可以作为一个集群运作。这种架构在扩展到巨大的集群时为 Nomad 带来优势。Kubernetes 官方支持最多 5000 个节点和 300000 个容器，而 Nomad 的文档引用了包含超过 10000 个节点和 200 万个容器的集群示例。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/006-4f3abd38.png"&gt;&lt;/p&gt;
&lt;p&gt;与 Kubernetes 类似，Nomad 不包括容器引擎或运行时。它使用任务驱动程序来运行作业。使用 Docker 和 Podman 运行容器的任务驱动程序已包含在内；社区支持的驱动程序可用于其他容器引擎。同样与 Kubernetes 类似，Nomad 的野心不限于容器；还有其他类型工作负载的任务驱动程序，包括一个简单地在主机上运行命令的 fork/exec 驱动程序、用于运行虚拟机的 QEMU 驱动程序和用于启动 Java 应用程序的 Java 驱动程序。社区支持的任务驱动程序将 Nomad 连接到其他类型的工作负载。&lt;/p&gt;
&lt;p&gt;与 Docker 或 Kubernetes 不同，Nomad 避开了 YAML，而是采用 HashiCorp 配置语言（HCL），该语言最初是为另一个 HashiCorp 项目 Terraform 创建的，用于云资源的配置。HCL 在 HashiCorp 产品线中使用广泛，尽管在其他地方采用有限。用 HCL 编写的文档可以轻松转换为 JSON，但其目标是提供比 JSON 更便于手指输入且比 YAML 更不易出错的语法。&lt;/p&gt;
&lt;p&gt;HashiCorp 的 Helm 等效工具称为 Nomad Pack。像 Helm 一样，Nomad Pack 处理包含模板和变量声明的目录以生成作业配置。Nomad 还具有一个社区注册表，用于预打包应用程序，但可用选择远少于 Artifact Hub 的 Helm。&lt;/p&gt;
&lt;p&gt;Nomad 没有 Kubernetes 那样的受欢迎程度。像 Swarm 一样，其开发似乎主要由其创建者推动；虽然它已被许多大公司部署，但 HashiCorp 仍然是 Nomad 社区的中心。此时，项目似乎不太可能获得足够的动力以独立于其企业母公司存在。用户或许可以从 HashiCorp 更明确地致力于 Nomad 的开发和推广中找到一些保证，这与 Docker 对 Swarm 的承诺形成鲜明对比。&lt;/p&gt;
&lt;h4 id="结论"&gt;&lt;a href="#%e7%bb%93%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;结论
&lt;/h4&gt;&lt;p&gt;Swarm、Kubernetes 和 Nomad 并不是唯一的容器编排器，但它们是三个最具生命力的工具。Apache Mesos 也可以用于运行容器，但在 2021 年几乎被搁置；基于 Mesos 的 DC/OS 也面临类似的情况，支持其发展的社区和商业实体正在寻找新的方向。尽管如此，Swarm、Kubernetes 和 Nomad 仍然是当前市场上最受欢迎和最活跃的容器编排解决方案，它们各自提供了不同的功能和优势，以满足不同规模和需求的企业。随着技术的不断进步和市场的变化，这些工具将继续演化，以适应未来的挑战和机遇。&lt;/p&gt;</description></item></channel></rss>