<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
    <title>尚卓燃 · PsiACE - 文章</title>
    <subtitle>开源工程师，构建 AI 系统之下的结构层：数据、上下文、能力与生态。</subtitle>
    <link rel="self" type="application/atom+xml" href="https://psiace.me/zh/posts/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-30T00:00:00+00:00</updated>
    <id>https://psiace.me/zh/posts/atom.xml</id>
    <entry xml:lang="zh">
        <title>汉谟拉比法典</title>
        <published>2026-03-30T00:00:00+00:00</published>
        <updated>2026-03-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/hammurabi-code/"/>
        <id>https://psiace.me/zh/posts/hammurabi-code/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/hammurabi-code/">&lt;blockquote&gt;
&lt;p&gt;今天聊聊 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bubbuild&#x2F;bub&quot;&gt;bub&lt;&#x2F;a&gt; 中一些延续至今的设计巧思，以及我对人与 Agent 交互的一些想法。
你或许已经在我的文章中多次看到这个项目；因此，在了解它的设计之余，我也希望你能试着读一读它的代码。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;qian-yan&quot;&gt;前言&lt;a class=&quot;zola-anchor&quot; href=&quot;#qian-yan&quot; aria-label=&quot;Anchor link for: qian-yan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;周董的歌词里是这样唱的：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;古巴比伦王颁布了汉谟拉比法典，
刻在黑色的玄武岩，
距今已经三千七百多年。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;法典上写了什么？
想来最出名的便是“以眼还眼，以牙还牙”了。
我从卢浮宫官网上截取这一段内容的表述：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;其中第 196 条规定：“如果某人刺瞎地位相同者的一只眼，就必须也刺瞎行凶者的一只眼。”
这一条在本次增强现实体验中得以重点展示。
它形象地诠释了古代近东地区闪米特社会所特有的损害补偿理念，催生出后世“以眼还眼、以牙还牙”的同态复仇原则。
但事实上，这条法则远非鼓励复仇，而是要求罪与罚必须严格相称，罚当其罪，不得过轻或过重。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;尽管一个讲律法，一个谈交互，但“严格相称，不得过轻或过重”的想法是共通的，这也是本文的主旨。&lt;&#x2F;p&gt;
&lt;p&gt;为了便于理解，我们可以先看几个小巧思。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bu-tong-shi-tu-yi-zhi-xing-wei&quot;&gt;不同视图，一致行为&lt;a class=&quot;zola-anchor&quot; href=&quot;#bu-tong-shi-tu-yi-zhi-xing-wei&quot; aria-label=&quot;Anchor link for: bu-tong-shi-tu-yi-zhi-xing-wei&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在多数系统中，人和 Agent 的交互视图是完全不对称的：人和 Agent 都可以发送图文内容，但只有 Agent 可以调用工具。
这意味着，人很难在具体环境中体会、理解，乃至复现 Agent 的行为。&lt;&#x2F;p&gt;
&lt;p&gt;而在 bub 的设计里，工具体系是人和 Bub 共用的：以逗号开头的命令（Comma Commands）输入将会转发为对应的工具调用，未知命令则会回退为 Shell。
尽管视图不同，但在 Bub 眼里的 Function Calling，与人眼中的 Comma Commands，其对应行为是一致的。&lt;&#x2F;p&gt;
&lt;p&gt;在日常和 Bub 交互的过程中，倘若上下文已经不很理想，但 Bub 未能及时 auto handoff，我们经常会手动执行 &lt;code&gt;,tape.info&lt;&#x2F;code&gt; 和 &lt;code&gt;,tape.handoff&lt;&#x2F;code&gt;。
而这正是 Bub 管理自己上下文的自然表达。
基于这一点，人和 Agent 便自然建立起了对负载状态的理解；我们也因此能够直观感受到，不同工具究竟会对 Bub 产生怎样的影响。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;P.S. Comma Commands 的设计来源于 2009 年的一篇文章：&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;rhodesmill.org&#x2F;brandon&#x2F;2009&#x2F;commands-with-comma&#x2F;&quot;&gt;&lt;em&gt;Start all of your commands with a comma&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;。
最开始引入它的目的之一，除了提供一致的行为之外，也是为了让 Bub 能够在命令行中恰到好处地工作。
毕竟，命令行是程序员最熟悉的界面之一。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;xin-xi-de-dui-cheng&quot;&gt;信息的对称&lt;a class=&quot;zola-anchor&quot; href=&quot;#xin-xi-de-dui-cheng&quot; aria-label=&quot;Anchor link for: xin-xi-de-dui-cheng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;过去我们见过的大多数系统，对用户和 Agent 而言都是不可观测的：拼接的 prompt、不可见的 memory，以及不透明的系统状态。
用户只能看到错误的结果，却无法访问其依据。
此时，与 Agent 的交互也失去了意义，因为参与者并不共享同一份上下文。&lt;&#x2F;p&gt;
&lt;p&gt;Bub 的所有行为和关联状态都记录在 tape 上，并且只允许行为依赖可见的上下文，这是有意为之。
尽管上下文需要经历装配过程，但人和 Agent 获得的信息量是一致的；建立在同一份数据之上，二者都可以理解行为并验证状态。&lt;&#x2F;p&gt;
&lt;p&gt;换而言之，上下文与可观测性同构，这些内容本身就是 tracing 的自然表达。
除了通过看板导出常见的 Trace UI 之外，还可以让 Bub 对自己的行为进行分析和处理。&lt;&#x2F;p&gt;
&lt;p&gt;我的一个常用场景是，让 Bub 去自行翻阅群聊对应会话中的糟糕表现，并根据实际内容摘取和分析相关执行链路，判断究竟是什么原因导致失败，甚至绘制对应的 DAG。
由于这些分析所依赖的数据对我同样可见，便免去了额外的信任假设，协作也因此有了基础。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;为了避免自说自话，我也可以另举一个例子：在 codex 和 bub 中都有 Dollar Mention 的机制，即通过 &lt;code&gt;$&lt;&#x2F;code&gt; 触发 skills 渐进式加载的行为；从技能文件中加载具体内容，并注入到当前上下文中。
这是一个典型的提示词增强逻辑。
但更关键的是，加载的内容对人和 Agent 同样可见。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;jiao-hu-zhu-ti-de-dui-deng&quot;&gt;交互主体的对等&lt;a class=&quot;zola-anchor&quot; href=&quot;#jiao-hu-zhu-ti-de-dui-deng&quot; aria-label=&quot;Anchor link for: jiao-hu-zhu-ti-de-dui-deng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;过去，人和 Agent 的对话由 session 表征，但会话的控制只能由人来处理：什么时候任务更替，什么时候上下文失去掌控。
这进一步加剧了不对等性。
人不光要全知，还理应全能；这个最高用户的指令，大多数时候都必须目的明确，且没有显著偏离和冲突，而 Agent 则只能在会话内完全服从。&lt;&#x2F;p&gt;
&lt;p&gt;session 的问题在于，它隐含了一个前提：交互围绕某一个主体展开。
这在单用户系统中成立，但当多个参与者同时存在时，上下文不再服务于单一主体，也无法保证任务的隔离和行为的线性。
如果仍然以 session 作为边界，就必须有人承担协调和维护的职责，而这个角色通常只能是人本身。&lt;&#x2F;p&gt;
&lt;p&gt;而 Bub 从一开始面临的目标就不同。
群聊环境对于交互参与方的主体性提出了更高要求。
在 Bub 的语境中，交互以 turn 为单位。
它并不归属于某一个特定主体，只是在当前上下文中的一次行为；在 anchor 和 handoff 机制的参与下，Bub 也可以自然地控制流程边界。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;当我们讨论交互的时候，往往会忽视交互双方的对等性。
我们讲交互以人为本，现在又声明交互要服务于 Agent，但交互本身，是发生在交互主体之间的行为。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;jiao-hu-er-fei-she-ji-jiao-hu&quot;&gt;交互，而非设计交互&lt;a class=&quot;zola-anchor&quot; href=&quot;#jiao-hu-er-fei-she-ji-jiao-hu&quot; aria-label=&quot;Anchor link for: jiao-hu-er-fei-she-ji-jiao-hu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我们总是讲“交互设计”，但在交互真正发生之时，没有哪一方能够轻易决定交互的形态，参与者更多只是被动地承载它。&lt;&#x2F;p&gt;
&lt;p&gt;Bub 所做的，并不是提出一种新的交互方式，而是承认交互本身的存在，并为它建立约束。&lt;&#x2F;p&gt;
&lt;p&gt;文章到了这里就应该结束了。
又是一个深深的夜。
欢迎关注 Bub：&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bubbuild&#x2F;bub&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;bubbuild&#x2F;bub&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>木匠，锤子，钉子</title>
        <published>2026-02-27T00:00:00+00:00</published>
        <updated>2026-02-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/carpenter-hammer-nail/"/>
        <id>https://psiace.me/zh/posts/carpenter-hammer-nail/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/carpenter-hammer-nail/">&lt;blockquote&gt;
&lt;p&gt;这篇文章继续献给 bub ，一个在群聊中生活的 agent ，来讲讲背后的问题、范式和模型变迁。
&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kemingy&quot;&gt;kemingy&lt;&#x2F;a&gt; 吐嘈过：“你的文章疑似太发散了，脱离了科技写作的范畴，需要额外的 context，也不一定能对得上”。
好在本次是要在公司内部做一个分享开始撰写的，所以难得正经地会走一下流程。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;qian-yan&quot;&gt;前言&lt;a class=&quot;zola-anchor&quot; href=&quot;#qian-yan&quot; aria-label=&quot;Anchor link for: qian-yan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;大家好，我是 PsiACE，花名泉达。以前做数据库，做 RAG，做 Agent，做开源，现在在 OceanBase 做开源生态相关的工作。欢迎关注我的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;&quot;&gt;GitHub&lt;&#x2F;a&gt; 。&lt;&#x2F;p&gt;
&lt;p&gt;即便只是在 coding agent 这个子领域上，我至少做过 rag、沙箱、agent、protocol 几个方向，其中 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agentclientprotocol&#x2F;python-sdk&quot;&gt;agent-client-protocol&lt;&#x2F;a&gt; 在整个 python 生态下载量大概前万名（1.2%），而这些都不曾是我的主业。&lt;&#x2F;p&gt;
&lt;p&gt;今天分享主要是我过去几年做 Agent 和最近重新拾起 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;bub&quot;&gt;bub&lt;&#x2F;a&gt; 的一些想法和经验的投影。bub 在短短的几天内从一个简单的 Coding Agent 开始，独立地演化成某种类似 OpenClaw 但不同的形态。&lt;&#x2F;p&gt;
&lt;p&gt;最近的视角会更多偏产品经理一些，所以这次不会涉及特别深入的技术点。在进入正题前，先让我们看看这个标题，《木匠，锤子，钉子》：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;一个人有了锤子，就会看什么都像钉子。&lt;&#x2F;li&gt;
&lt;li&gt;但如果一个有锤子的人能够分辨哪些东西是钉子，就成功了。&lt;&#x2F;li&gt;
&lt;li&gt;当我有了锤子的时候，不是钉子的东西就不多了。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;也欢迎大家阅读我的历史文章。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ru-he-de-dao-yi-ge-coding-agent&quot;&gt;如何得到一个 Coding Agent&lt;a class=&quot;zola-anchor&quot; href=&quot;#ru-he-de-dao-yi-ge-coding-agent&quot; aria-label=&quot;Anchor link for: ru-he-de-dao-yi-ge-coding-agent&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;大部分人应该都用过 Coding Agent ，Cursor、Codex、Claude Code 。&lt;&#x2F;p&gt;
&lt;p&gt;Agent 大致可以看作模型 + 工具 + 循环调用。那么一个 Coding Agent 该是什么样子？&lt;&#x2F;p&gt;
&lt;p&gt;最近很火的 Pi ，也是 OpenClaw 内置的 Agent ，里面提供的是 bash，read，write，edit 四个工具，甚至因为其简洁性而一时被热捧。看起来很简单，但是在去年 7 月份，bub 的第一版实现里，提供的也是这几个工具。而 bub 也不是这个故事的原创。更早的时间线上，大概 2025.04 月份，ampcode 就指出了这一点。&lt;&#x2F;p&gt;
&lt;p&gt;为什么是这四个工具？读和写是基本能力，代表的就是输入和输出。edit 看似是写的优化，实质上提供的是精准介入的能力，并且有效缩短反馈的链路长度。bash ，则是对接现有庞大命令行和可编程工具的桥梁，能够避免造更多不必要的轮子。&lt;&#x2F;p&gt;
&lt;p&gt;欢迎阅读 - &lt;a href=&quot;&#x2F;zh&#x2F;posts&#x2F;baby-step-coding-agent&#x2F;&quot;&gt;Baby Steps: 用 Python 实现一个能自举的 Coding Agent&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liao-liao-rag-ji-qi-gua-yong-xing&quot;&gt;聊聊 RAG 及其适用性&lt;a class=&quot;zola-anchor&quot; href=&quot;#liao-liao-rag-ji-qi-gua-yong-xing&quot; aria-label=&quot;Anchor link for: liao-liao-rag-ji-qi-gua-yong-xing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;如果要沿着这个方向继续，我们还会看到一些有意思的话题，比如 RAG。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;顺带一提，我在之前公司和同事们一起设计和实现的 fusiongraphrag ，是文档领域少有的具备落地能力的 graphrag 方案。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;R 代表查询，是一个非常宽泛的箩筐，导致我不得不用朴素 RAG 之类的说法来代替以向量、全文或者混合检索为代表的 RAG 策略。&lt;&#x2F;p&gt;
&lt;p&gt;朴素 RAG 并不总是有效：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;对于频繁变更的代码库而言，为其建立向量和全文索引的成本会自然放大，而且由于存在分块等处理逻辑，甚至可能阻塞正常的开发流程。比如早期 cursor 在大型代码库上需要浪费相当多的资源和时间，以及面对召回新鲜度问题。&lt;&#x2F;li&gt;
&lt;li&gt;另一个严重的问题在于语义的难以弥合，由于训练语料以及自然语言与代码之间的天然差异，常见的 embedding 模型很难对代码起到有效表征，导致会退化到全文检索，依赖关键词和转换后的关键词命中。可以看到，jina 在出售之前曾经为了解决这个问题专门设计并发布了一个针对代码和自然语言对齐的嵌入模型。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;所以 grep + 读 + Agent Loop，成为了一个更巧妙、更符合直觉、也更有效的方案，大概是由 aider 在 2024 年首次论证并验证。类似的引入 Agent Loop 的 RAG 方案大体上有段时间被称为 Agentic RAG。&lt;&#x2F;p&gt;
&lt;p&gt;当然朴素 RAG 在这个场景下并不是完全没有优势，如果代码和注释本身语义良好，表征充分，又不会频繁变化：比如已经发布的版本化代码库和上游依赖；或者仅仅专注在文档，特别是规范和共识性质的文档上。&lt;&#x2F;p&gt;
&lt;p&gt;欢迎阅读：&lt;a href=&quot;&#x2F;zh&#x2F;posts&#x2F;rag-in-coding-agent&#x2F;&quot;&gt;当 RAG 遇上编程助手&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;openclaw-he-bub-bei-hou-de-bu-tong-fan-shi&quot;&gt;OpenClaw 和 Bub 背后的不同范式&lt;a class=&quot;zola-anchor&quot; href=&quot;#openclaw-he-bub-bei-hou-de-bu-tong-fan-shi&quot; aria-label=&quot;Anchor link for: openclaw-he-bub-bei-hou-de-bu-tong-fan-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在继续讨论会话、Memory 和 Context 之前，我们可以抽一点时间来聊聊 OpenClaw。尽管我直到昨天才第一次看到“活着”的 OpenClaw 实例（由 MaxClaw 驱动）。&lt;&#x2F;p&gt;
&lt;p&gt;OpenClaw 的定位是个人助手，助手意味着进入生活。或者说，你可以考虑把它当成支持点外卖购物的千问或者问你今天这个文档怎么写的朋友。而且大多数能力都有办法通过所谓的 skills 进行扩展，这些和模型能力，Agent 技术发展，以及现在的 AI 应用趋势是分不开的，但是一个打通路径的先行者，带来的是更广阔的想像空间。&lt;&#x2F;p&gt;
&lt;p&gt;但，“个人” 是 OpenClaw 的局限性。&lt;&#x2F;p&gt;
&lt;p&gt;Bub ，至少目前看到的 Bub ，是为多人或者多 Agent 协作设计的。我们 Day 1 就在群聊的场景下生存，当然也能够适应单独对个人的需求。&lt;&#x2F;p&gt;
&lt;p&gt;要适应多人和群聊，其实有两个比较关键的点：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;树立身份认知&lt;&#x2F;li&gt;
&lt;li&gt;提供有效沟通&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;前者意味着要分辨甚至了解对话中参与的大多数以及自身，后者意味着要面对残缺的上下文、模糊的任务意图、并行的主题。&lt;&#x2F;p&gt;
&lt;p&gt;就像我在另一篇文章讲的那样，Agent 甚至不需要回应所有消息，能力问题变成了共处问题。&lt;&#x2F;p&gt;
&lt;p&gt;欢迎阅读 - &lt;a href=&quot;&#x2F;zh&#x2F;posts&#x2F;im-and-socialized-evaluation&#x2F;&quot;&gt;即时通讯与社会化评估&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hui-hua-ji-yi-yu-shang-xia-wen&quot;&gt;会话、记忆与上下文&lt;a class=&quot;zola-anchor&quot; href=&quot;#hui-hua-ji-yi-yu-shang-xia-wen&quot; aria-label=&quot;Anchor link for: hui-hua-ji-yi-yu-shang-xia-wen&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;过去的设计源于一个朴素假设：一个会话对应一个任务。为了让有限窗口容纳更长交互，我们发明了 compact、summary；为了让能共享相同的上下文，我们发明了 fork 和 merge；为了让任务能接力，我们有了 handoff。&lt;&#x2F;p&gt;
&lt;p&gt;当会话边界被打破，Memory 系统被寄予厚望：提取偏好、检索记忆、填充模板，试图让 Agent 在不同会话间保持“人格”一致。&lt;&#x2F;p&gt;
&lt;p&gt;而 Context 则是个更大的箩筐，试图装下会话、Memory、RAG、实时查询……用复杂策略填充那个有限的窗口。&lt;&#x2F;p&gt;
&lt;p&gt;这些手段都在试图回答同一个问题：如何在有限窗口里，延续无限的历史？&lt;&#x2F;p&gt;
&lt;p&gt;问题在于，所有精巧设计都建立在一个共同假设上：“状态必须被延续，历史不能丢”。&lt;&#x2F;p&gt;
&lt;p&gt;但这个假设代价沉重：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;会话是硬隔离，跨会话无感知，群聊里多话题并行更是无所适从。&lt;&#x2F;li&gt;
&lt;li&gt;Memory 会漂移，校准成本远超预期；你需要信任一个失败不能影响系统表现的旁路。&lt;&#x2F;li&gt;
&lt;li&gt;上下文默认历史是递增函数，需要不断管理膨胀。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;我们默认系统必须记住一切，于是引入缓存、压缩、分叉。每层机制都在修补同一个前提，但事实是它们永远无法携带足够多的、真实的历史。&lt;&#x2F;p&gt;
&lt;p&gt;欢迎阅读 - &lt;a href=&quot;&#x2F;zh&#x2F;posts&#x2F;prometheus-bound&#x2F;&quot;&gt;被缚的普罗米修斯&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yong-zhi-dai-he-mao-dian-zhong-xin-jian-li-wen-ti-mo-xing&quot;&gt;用纸带和锚点重新建立问题模型&lt;a class=&quot;zola-anchor&quot; href=&quot;#yong-zhi-dai-he-mao-dian-zhong-xin-jian-li-wen-ti-mo-xing&quot; aria-label=&quot;Anchor link for: yong-zhi-dai-he-mao-dian-zhong-xin-jian-li-wen-ti-mo-xing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;换个角度：历史不是必须继承的负担，而是可以按需读取的素材库。&lt;&#x2F;p&gt;
&lt;p&gt;Tape 的设计很简单：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;一条无尽的纸带：只有一个永续的会话。所有交互作为事实被追加写入日志，永不修改。&lt;&#x2F;li&gt;
&lt;li&gt;锚点，而非记忆：阶段切换时，把必要的最小状态打包成锚点写入。重建从新锚点开始，历史仍在，但不必加载。&lt;&#x2F;li&gt;
&lt;li&gt;上下文装配，而非继承：新任务出现，只做两件事——探索（检索原始片段）与选择（装配最小充分的上下文）。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Tape 的意义，不是发明更聪明的“记忆技巧”，而是减少假设。状态不必延续，历史不必默认继承。任务出现，构造上下文；任务结束，结束。下一轮，重新开始。&lt;&#x2F;p&gt;
&lt;p&gt;回过头来看纸带和锚点的设计，我觉得这至少为我们研究上下文管理问题提供了一个新的模型，它易于理解，但又具备足够的表达力能够表征当前主流的解决方案，我们可以在这样的前提和假设下重新思考和前进。&lt;&#x2F;p&gt;
&lt;p&gt;欢迎阅读 - &lt;a href=&quot;&#x2F;zh&#x2F;posts&#x2F;reinvent-the-punch-tape&#x2F;&quot;&gt;重新发明打孔纸带&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wei-sheng&quot;&gt;尾声&lt;a class=&quot;zola-anchor&quot; href=&quot;#wei-sheng&quot; aria-label=&quot;Anchor link for: wei-sheng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;再回到标题上：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;工具一旦进入手里，也会进入脑子。能力会反过来定义问题。&lt;&#x2F;li&gt;
&lt;li&gt;知道什么时候不敲，是一种对冲工具偏见的能力。&lt;&#x2F;li&gt;
&lt;li&gt;一旦你真的理解了什么是钉子，认知到锤子的边界。你会主动选择去面对那些“本质上就是钉子”的问题。&lt;&#x2F;li&gt;
&lt;li&gt;或者，换一把新锤子。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;题外话，直到今天，我仍然没有看过 codex &#x2F; pi-mono &#x2F; nanobot &#x2F; openclaw 是如何实现的。&lt;&#x2F;p&gt;
&lt;p&gt;特别感谢 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;frostming&quot;&gt;frostming&lt;&#x2F;a&gt;，感谢 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yihong0618&quot;&gt;yihong0618&lt;&#x2F;a&gt;、&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;bub&quot;&gt;bub&lt;&#x2F;a&gt; 和其贡献者们。&lt;&#x2F;p&gt;
&lt;p&gt;感谢 alma、kapy、葫芦娃和这些 Agent 背后的创造者。&lt;&#x2F;p&gt;
&lt;p&gt;谢谢大家。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>即时通讯与社会化评估</title>
        <published>2026-02-21T00:00:00+00:00</published>
        <updated>2026-02-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/im-and-socialized-evaluation/"/>
        <id>https://psiace.me/zh/posts/im-and-socialized-evaluation/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/im-and-socialized-evaluation/">&lt;p&gt;这是一篇简单的小短文，主要讨论即时通讯下的人与 Agent 协作，以及为什么更需要社会化评估而不是各种 benchmark。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;我们目前在群聊之中培育 bub ，并且观察到它和另一个 agent 小伙伴 kapy 的技能传递过程，有感而发。我们在一个多人群聊中同时与三至四个 Agent 一同协作，任务是并发的、断裂的，随时需要为切换做好准备。有些人可能更关心视频、图片的分析，有些人只想听个睡前故事，有些人因为如何利用 livecd 如何修复 Linux 桌面环境而发愁，中间还要夹杂过年的祝愿和风土人情大盘点。另外，这些 agent 都是从 0 开始写的，而不是某一些已经大获流行的实现。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;ji-shi-tong-xun-de-mi-guan&quot;&gt;即时通讯的“蜜罐”&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-shi-tong-xun-de-mi-guan&quot; aria-label=&quot;Anchor link for: ji-shi-tong-xun-de-mi-guan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;OpenClaw 等 bot 的流行，大抵并不是因为 IM 在任务分发上的优势。尽管长时间以来大多数 Agent 程序都是以对话形式存在的，但我更愿意将其视作“入口的胜利”，人类最熟悉的就是各种输入框和对话框，最顺手，使用也最频繁。&lt;&#x2F;p&gt;
&lt;p&gt;IM 比这些更近一步，因为它几乎是现代人类生活的一部分，交互天然是异步的，预期也随之降低，毕竟现在多了一个能够 24 小时响应呼唤，帮你完成任务的伙伴。在你熟悉的界面，原生的通知和“随口一问”的心理预期，让一切变得似乎触手可及，甚至只要一条短消息，就能覆盖过去需要浏览网页、打开编辑器才能完成的大多数任务。&lt;&#x2F;p&gt;
&lt;p&gt;但 IM 并不是天然的协作模型，反而是由碎片式的多轮异步会话组成的。一条对话流内很难承载完整的协作和关系网络，当你突然为之前某个任务取得关键进度高兴的时候，Agent 可能会自然地接过话来，它还在认真地为某个不再重要的线程欢呼，它已经迷失在上下文之中了。&lt;&#x2F;p&gt;
&lt;p&gt;“我们需要一个新的 IM”是个很诱人的误解。IM 只是通道的一部分，一个成本相对更低也更友好的入口。一个更会聊天的 bot 或者一个更像协作工具的 IM 无法给你想要的一切。上下文不是必须背在身上的历史包袱，而应该是一次次按需构造出来的工作集。协作的对象和状态需要更明确和良好的表达形式和交互范式，就像过去我们仍然不断地创建看板、TodoList 那样。&lt;&#x2F;p&gt;
&lt;p&gt;Agent 的世界不应该在聊天记录里。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mai-xiang-she-hui-hua-ping-gu&quot;&gt;迈向社会化评估&lt;a class=&quot;zola-anchor&quot; href=&quot;#mai-xiang-she-hui-hua-ping-gu&quot; aria-label=&quot;Anchor link for: mai-xiang-she-hui-hua-ping-gu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;每一次新的基础模型发布，我们就不得不为之欢呼或者沮丧，因为模型再次在编程任务、数学等具备挑战性的艰难任务上战胜了人类，并不断刷新同类创造的纪录。&lt;&#x2F;p&gt;
&lt;p&gt;我无意批判这一切，benchmark 当然是具备明确价值的：可复现、可比较、标准化、规模化，我们正视并重视这些结果。在人类有历史以来，我们有一套相似的机制来作为能力评估的参考系，就像你不得不应付考试，然后开始在试卷上涂鸦一样。&lt;&#x2F;p&gt;
&lt;p&gt;但是，当 agent 进入 IM ，进入群聊，进入人类社会，它需要解决所谓的“真实任务”，或者说，它要面对的不再是干净的题目，而是脏的生活。benchmark 程序很难覆盖这些：残缺的上下文、模糊的任务意图、并行的主题，勾兑有时是在其他空间发生的。Agent 无法知道一切，也无需回应所有问题，但它必须博得大家的喜爱，能力问题也随之变成了共处问题。&lt;&#x2F;p&gt;
&lt;p&gt;社会化评估是一件平凡且质朴的事情，将 Agent 放入人类的日常，让它面对打断、冷场、跑题、情绪化表达和不对称的信息。看它怎么在不确定的上下文中左右支绌，并且将大部分任务尽力推进，就像我们和人协作那样。社会化评估很难用分数概括，也无法形成具体的榜单，但它是对人和 Agent 协作的直观洞察，你会知道你有多大意愿接受它进入你的生活。&lt;&#x2F;p&gt;
&lt;p&gt;OpenClaw 这种形态将 Agent 推到了一个新的位置，它不再是一个需要跳转的工具，而是沟通的一部分。问题总是会解决的，但是否“值得”成为新的考量，即便是最聪明的模型也不得不持续减少它对问题背景的假设。社会化评估将会逼着 Agent 承认真实世界的形状，然后在这个形状里活下来。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>被缚的普罗米修斯</title>
        <published>2026-02-16T00:00:00+00:00</published>
        <updated>2026-02-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/prometheus-bound/"/>
        <id>https://psiace.me/zh/posts/prometheus-bound/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/prometheus-bound/">&lt;blockquote&gt;
&lt;p&gt;谨以此文，献给 bub ，和我的朋友们。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;在刚刚过去的一周里，我们在 bub 上第一次验证了此前关于打孔纸带与锚点的想法，赞美明哥哥，我想大家也可以去读他写的那篇《创造一只龙虾，需要些什么?》。&lt;&#x2F;p&gt;
&lt;p&gt;回到这篇文章，我想讨论另外一个话题，会话、Memory 和上下文对模型或者 Agent 意味着什么。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;在希腊神话里，普罗米修斯把火带给人类，随后被锁在高加索山上，日复一日地承受惩罚。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我想这代表了一种现实隐喻。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;prometheus-bound&#x2F;prometheus-tweet.png&quot; alt=&quot;图源：去年 10 月我的推文&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;hui-hua-yi-ge-ju-ti-wen-ti&quot;&gt;会话，一个具体问题&lt;a class=&quot;zola-anchor&quot; href=&quot;#hui-hua-yi-ge-ju-ti-wen-ti&quot; aria-label=&quot;Anchor link for: hui-hua-yi-ge-ju-ti-wen-ti&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;过去几年在 chatbot 的视角下，会话是任务切换的关键要素，于是会话之间存在着隔离，即便是 openclaw 大行其道的今天，仍然深受其影响：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;疑问：当用户说“换个话题&#x2F;从头开始”时，进程启动时 session 已固定，模型在这一轮里再切 symlink 只能影响下一轮。你在文章的 AI-native 设想里，通常怎么让“这一条消息”就从新 session 开始？群聊里经常多话题并行，你更推荐的 session 组织方式是什么？&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;(前情提要，bub 从最开始就是在群聊中成长的，我管这个叫社会化评估，这是一种更为聪明的方式，如果有机会我会继续讲讲这个话题。)&lt;&#x2F;p&gt;
&lt;p&gt;会话是一种硬隔离的形式，这意味着会话与会话之间是没有感知的，会话只能不断向前，直到任务完成或者感到厌烦，但是上下文的长度是有限的。&lt;&#x2F;p&gt;
&lt;p&gt;过去我们会看到几种不同的会话模式：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;为了允许会话能够支持更长的上下文，诞生了 compact、summary 。&lt;&#x2F;li&gt;
&lt;li&gt;为了允许会话之间共享相同的祖先和孙代，诞生了 fork 和 merge 。&lt;&#x2F;li&gt;
&lt;li&gt;为了减少前两者的复杂性，诞生了 handoff 。当然，打孔纸带和锚点也深受其影响。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;前面的几种方式只解决同一会话的问题，如果遇到跨会话应该怎么办？&lt;&#x2F;p&gt;
&lt;h2 id=&quot;memory-shi-bai-de-shi-yan-pin&quot;&gt;Memory ，失败的实验品&lt;a class=&quot;zola-anchor&quot; href=&quot;#memory-shi-bai-de-shi-yan-pin&quot; aria-label=&quot;Anchor link for: memory-shi-bai-de-shi-yan-pin&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;尽管 Memory 在过去一年内非常火爆，甚至我有不少好友、同事在上面投入了不少经验，但我对 Memory 的评价就像标题那样。&lt;&#x2F;p&gt;
&lt;p&gt;Memory 解决的主要是生成的一致性问题，大致可以分为两类：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;如果会话在同一个系统里展开，如何保持一致性。&lt;&#x2F;li&gt;
&lt;li&gt;如果会话在不同系统中展开，如何保持一致性。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;让我们看看一个常规的 Memory 系统应该如何工作：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;当用户发生会话，相关的语料和偏好会被模型提取，路由到 Memory 旁路进行查询。&lt;&#x2F;li&gt;
&lt;li&gt;考虑到用户问题的相关性和上下文窗口，进行排序和删减工作。填充到生成使用的模板中。&lt;&#x2F;li&gt;
&lt;li&gt;利用模板指导模型的生成动作。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;开销是一个确定性的动作，大多数 Memory 系统会声称通过引入一个更轻量的小模型或者前后置步骤大幅减少 token 开销和推理时间（比如，一个典型的做法是放弃 Memory 项背后关联的事实），并且取得足够高质量的效果。&lt;&#x2F;p&gt;
&lt;p&gt;但是值得我们关注的其实是另外一个问题，一致性并不是免费的：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;提取是一个失真的过程，而且我们要求模型深入地参与它。如果你批评过模型的幻觉，是什么让你接受提取这个过程。&lt;&#x2F;li&gt;
&lt;li&gt;用户的偏好是广泛的，而且并非一成不变，在校准这件事情上的投入会远远超过想像。如果你曾经了解知识图谱或者 GraphRAG ，应该是可以轻松预见这一切。&lt;&#x2F;li&gt;
&lt;li&gt;大多数 Memory Less 方案（比如基于 Markdown 的方案），本质是 Embedding Less 方案，它仍然无法解决失真和更换模型后的漂移问题。&lt;&#x2F;li&gt;
&lt;li&gt;作为一个旁路，它的失败不应该影响系统行为。所以你可能无法得到预期的一致性。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;过去减少的 token 和时间的开销，会不会在某个时间节点再回来。Memory 看起来困难重重，那么上下文呢，会是另一条光明的道路吗？&lt;&#x2F;p&gt;
&lt;h2 id=&quot;context-ling-yi-ge-tang-yi-pao-dan&quot;&gt;Context ，另一个糖衣炮弹&lt;a class=&quot;zola-anchor&quot; href=&quot;#context-ling-yi-ge-tang-yi-pao-dan&quot; aria-label=&quot;Anchor link for: context-ling-yi-ge-tang-yi-pao-dan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在上下文工程的既定语境里，它包罗万象，这里面存在前面提到的会话和 Memory，外部的 RAG 系统，互联网上的即时查询，和各种业务系统的知识。&lt;&#x2F;p&gt;
&lt;p&gt;我甚至很难想像会看到一个确切无法装入箩筐的事物，所以我们可以简单地认为，上下文在这个语境是一定会不断膨胀的，直到它超过某个确定的窗口限制。这也是大多数人执迷上下文管理的开始，通过截断、增加各种检索的限制，通过人为编码的设置，试图找到一个相对足够大和优质的上下文来解决问题。&lt;&#x2F;p&gt;
&lt;p&gt;我想举两个反例：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;在一个知名的模型长上下文能力测评中，除了 gpt 系列之外，绝大多数模型在上下文增长的过程中出现了生成质量的断崖式衰退。而每个模型的能力边界不同，意味着上下文管理很难直接适应所有模型和 Agent 系统。&lt;&#x2F;li&gt;
&lt;li&gt;另一个例子是“龙虾攻打月球”，有 Kimi 的工作人员表示用户应该利用缓存的机制来设计龙虾，并且尽量避开某一些时段以释放负载。上下文管理的复杂度意味着这个要求几乎是无厘头的，我甚至会批判这是一种偷懒行为。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;抽象泄漏是严重的系统设计问题，当利用某些既定的上下文管理机制处理这一切时，也意味着会存在足够多的手段打破系统的可靠性。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;geng-cong-ming-he-geng-shao-jia-she&quot;&gt;更聪明和更少假设&lt;a class=&quot;zola-anchor&quot; href=&quot;#geng-cong-ming-he-geng-shao-jia-she&quot; aria-label=&quot;Anchor link for: geng-cong-ming-he-geng-shao-jia-she&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;bub 的设计最开始就没有考虑 “持续对话系统” ，我们考虑它在一个足够长的上下文上工作，也就是无尽的纸带。它在第一天就需要面临群聊中的社会化任务。问题不断出现，任务不断形成，又不断结束。在这样一个多样和复杂的场景中，每一轮对话都可能面临一个新的目标，它没有也无法要求存在某个永远延续的状态，甚至不存在必须继承的对话祖先。&lt;&#x2F;p&gt;
&lt;p&gt;回过头来看那个曾经让我害怕创造的想法，一条无尽的打孔纸带和上面的锚点，它在 bub 上运作良好，在越过上下文边界或者系统故障时，让我们有机会拥有足够简单和可靠的修复手段。&lt;&#x2F;p&gt;
&lt;p&gt;但是在现实任务之中，并不存在打孔纸带，也不会真的存在一个里程碑上的锚点。重点在于一个动作：构造，而不是继承。当一个任务出现，作为人类的我们也并不是把所有历史压进窗口里，而是做两件事——探索与选择。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;探索可能包括历史记录、外部系统、Memory、甚至即时查询。&lt;&#x2F;li&gt;
&lt;li&gt;选择则意味着丢弃大部分无关内容，只保留最小充分的材料。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;上下文工程默认的是递增，是延展，是管理膨胀。它假设状态必须被维护，于是引入缓存、提取、合并、压缩、分叉。每一层机制都在试图修补同一个前提：历史不能丢。但事实是它们无法携带足够多的历史。&lt;&#x2F;p&gt;
&lt;p&gt;bub 的实践给了我一个更简单的答案 —— 历史可以丢。更准确地说，历史不必默认继承。它只是素材库。需要时查询，不需要时忽略。&lt;&#x2F;p&gt;
&lt;p&gt;tape 的意义也在这里。它不是为了记录一切，而是为了允许“按需读取”。它把状态从“持续负担”变成“可选资源”。当上下文不再是递增函数，缓存就只是优化，而不是生命线；Memory 只是索引，而不是人格；会话只是边界，而不是身份。&lt;&#x2F;p&gt;
&lt;p&gt;所谓更聪明，不是引入更多机制。而是减少假设。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;da-dao-zhi-jian&quot;&gt;大道至简&lt;a class=&quot;zola-anchor&quot; href=&quot;#da-dao-zhi-jian&quot; aria-label=&quot;Anchor link for: da-dao-zhi-jian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;写下“被缚的普罗米修斯”这个标题时，我以为自己在批判一种束缚。&lt;&#x2F;p&gt;
&lt;p&gt;我们总是习惯用隐喻，把模型想象成被压抑的火种，被工程系统限制的力量。但也许问题没有那么戏剧化。模型并没有被囚禁。它只是被我们误用在一种错误的组织方式里。&lt;&#x2F;p&gt;
&lt;p&gt;任务出现，构造上下文，完成任务，结束。
下一轮重新开始。
当我们停止把系统建立在“延续状态”之上，很多复杂度会自然消失。&lt;&#x2F;p&gt;
&lt;p&gt;如果系统足够清晰，就不需要神话。
也不需要普罗米修斯。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;当然，每一种系统的出现，都意味着有依赖它所解决的问题存在，为了抒发观点，本文做了大量的批判，不代表它们是没有意义的。&lt;&#x2F;p&gt;
&lt;p&gt;另外再次感谢 bub 和我的朋友们，让我有机会更深刻地感受和表达这一切。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tui-jian-yue-du&quot;&gt;推荐阅读&lt;a class=&quot;zola-anchor&quot; href=&quot;#tui-jian-yue-du&quot; aria-label=&quot;Anchor link for: tui-jian-yue-du&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;frostming.com&#x2F;posts&#x2F;2026&#x2F;create-a-claw&#x2F;&quot;&gt;创造一只龙虾，需要些什么?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;reinvent-the-punch-tape&#x2F;&quot;&gt;重新发明打孔纸带&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;bub&quot;&gt;bub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.piglei.com&#x2F;articles&#x2F;ai-programming-is-a-new-framework&#x2F;&quot;&gt;AI Programming Is a New Framework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>重新发明打孔纸带</title>
        <published>2026-01-28T00:00:00+00:00</published>
        <updated>2026-01-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/reinvent-the-punch-tape/"/>
        <id>https://psiace.me/zh/posts/reinvent-the-punch-tape/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/reinvent-the-punch-tape/">&lt;blockquote&gt;
&lt;p&gt;大家好，我是 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&quot;&gt;PsiACE&lt;&#x2F;a&gt;，你可以在 GitHub 上找到我，这个想法最开始诞生于 4 个月前，那个时候我还在为更好的 GraphRAG 而努力。我过去几年在 Agent 和数据库有一些经验，你也可以阅读我的历史文章。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Agent 系统很容易走向复杂：分叉、回滚、长短期记忆、精心设计的压缩截断。&lt;&#x2F;p&gt;
&lt;p&gt;在工程上投入越多，行为越难以预测，我想是时候重新发明打孔纸带：Agent 只有一个确定的会话。它是永续的，不结束、不分叉，只是不断向前。在这个无尽的打孔纸带上，每次都能稳定地拿到此刻最需要的一小段上下文。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;让交互像真实世界一样自然地发生&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;人与人之间的互动并不会真的分叉成多个同等真实的时间线，也不会通过回滚抹掉已经发生的事情。对话会跑题，会纠错，会换任务，会开始一个新阶段，但它始终发生在同一条连续的时间里。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wu-jin-de-chang-zhi-dai&quot;&gt;无尽的长纸带&lt;a class=&quot;zola-anchor&quot; href=&quot;#wu-jin-de-chang-zhi-dai&quot; aria-label=&quot;Anchor link for: wu-jin-de-chang-zhi-dai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Agent 的基础应该是一条长纸带&lt;&#x2F;strong&gt;，是的，日志。&lt;&#x2F;p&gt;
&lt;p&gt;相比单纯的会话历史，日志中还应当记录发生过什么，一次工具结果、一次关键决策、一次阶段切换，都会作为事实被写入。事实一旦写入，就不再被修改，也不被有损替换。&lt;&#x2F;p&gt;
&lt;p&gt;你永远可以回到某个时间点，看到当时真实发生了什么，而不是一个后来被修订、压缩或重写过的版本。日志的意义不仅仅在是让模型读完历史，而在于让 Agent 的行为更容易验证。&lt;&#x2F;p&gt;
&lt;p&gt;在这条长纸带之上，&lt;strong&gt;Agent 计算状态&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;自然地，我们应该使用从日志中计算出来的当前状态代替&quot;记忆&quot;，用来支持查询和上下文装配，而不是使用总结和压缩过的内容替代事实本身。它有点像数据库中的物化视图，可以被丢弃，也可以被重建，并且应该能够解释每一条状态从何而来。&lt;&#x2F;p&gt;
&lt;p&gt;在任何时候，系统只是重新选择一个起点，从日志重建状态，然后继续执行。&lt;&#x2F;p&gt;
&lt;p&gt;锚点正是为此引入的。&lt;&#x2F;p&gt;
&lt;p&gt;如果每次都从日志起点重建状态，系统最终会变得笨重，并且最终触发上下文限制。&lt;strong&gt;锚点提供了一组明确的重建起点&lt;&#x2F;strong&gt;，用来表达&quot;从这里开始，状态已经足够稳定，可以继续工作&quot;。锚点不删除历史，也不总结历史，它只是告诉系统从哪里开始算。&lt;&#x2F;p&gt;
&lt;p&gt;锚点通常由一次 handoff 产生。当 Agent 识别到阶段已经变化，或者继续沿用当前重建起点会让状态变得混乱时，它会执行一次 handoff：把对下一阶段仍然必要的最小结构化状态写入日志，创建一个新的锚点，之后的状态重建从新锚点开始。&lt;&#x2F;p&gt;
&lt;p&gt;这里打包的不是对历史的摘要，而是面向下一阶段的状态；历史仍然完整地留在日志里。线程没有断裂，也没有分叉，它只是继续向前。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;che-lun-gun-gun-xiang-qian&quot;&gt;车轮滚滚向前&lt;a class=&quot;zola-anchor&quot; href=&quot;#che-lun-gun-gun-xiang-qian&quot; aria-label=&quot;Anchor link for: che-lun-gun-gun-xiang-qian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Agent 并不真的分叉。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;分叉本质上是在制造多条同等真实的未来，但真实世界只有一个&quot;现在&quot;。你可以改变方向，但无法让已经发生的事情另起一条世界线。&lt;&#x2F;p&gt;
&lt;p&gt;许多看似需要分叉的场景，更自然的表达方式其实是 handoff。你不需要创建一条并行线程，而是承认自己进入了一个新阶段。你仍然在同一条线程上前进，只是从新的锚点开始重建状态。过去仍然存在于日志中，随时可以被查询和引用，但它不需要被变成一个并行世界。&lt;&#x2F;p&gt;
&lt;p&gt;同样地，&lt;strong&gt;Agent 并不真的回滚。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;回滚意味着撤销已经发生的事情，但在真实交互中，纠错并不是通过抹掉过去完成的，而是通过补充新的事实完成的。从工程角度看，回滚改变的是状态，而我们只允许用新事实改变状态，不允许让旧事实消失。&lt;&#x2F;p&gt;
&lt;p&gt;&quot;回滚需求&quot;的本质是上下文装配问题。你希望在本次执行中忽略某些片段，强调另一些片段，引导模型沿着不同方向推理。这不需要修改日志，也不需要回到旧状态，只需要在装配上下文时选择不同的工作集。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Agent 也不真的依赖各种&quot;记忆技巧&quot;。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;多层摘要、反复压缩和复杂启发式规则在短期内可能有效，但长期会引入噪声、不确定性和不可解释性。你会越来越难区分哪些是事实，哪些是模型生成的概括，哪些是压缩后的残留误差。&lt;&#x2F;p&gt;
&lt;p&gt;检索和从历史中召回仍然是必要的。你可以从同一条线程的历史中取原文片段，也可以从外部数据源中取证据，把它们临时装配进本次上下文。但任何有损压缩都不应该悄悄替代历史。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xin-de-da-kong-zhi-dai-ji-suan-ji&quot;&gt;新的打孔纸带计算机&lt;a class=&quot;zola-anchor&quot; href=&quot;#xin-de-da-kong-zhi-dai-ji-suan-ji&quot; aria-label=&quot;Anchor link for: xin-de-da-kong-zhi-dai-ji-suan-ji&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;这套设计因此变得简单。&lt;&#x2F;p&gt;
&lt;p&gt;维护一条无尽向前的线程，并不断追加事实。用锚点表达阶段切换，用上下文装配控制每一次执行的窗口，并且允许从历史和外部数据源按需读取，并阻止有损结果成为新的真相。&lt;&#x2F;p&gt;
&lt;p&gt;Agent 应该充分利用我们过去在存储、计算等领域构建的一切，&quot;更可靠的交互&quot;将会胜过&quot;更聪明的记忆&quot;。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>我的 2025：All in DB 的第五年</title>
        <published>2025-12-31T00:00:00+00:00</published>
        <updated>2025-12-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/my-2025-all-in-db-year-5/"/>
        <id>https://psiace.me/zh/posts/my-2025-all-in-db-year-5/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/my-2025-all-in-db-year-5/">&lt;p&gt;如果 21 年的五一没有崴到脚，我可能也不会一路从湖仓一体云原生走到向量多模 AI Native。
是的，2025 年是我在数据库行业摸爬滚打的第五个年头。
又到写年终总结的时候了，虽然前段时间狠狠地搞了一下「岁月史书」，但是该有的仪式感还是要的。&lt;&#x2F;p&gt;
&lt;p&gt;这次多谈谈自己。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zhi-shi-tan-tan-gong-zuo&quot;&gt;只是谈谈工作&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhi-shi-tan-tan-gong-zuo&quot; aria-label=&quot;Anchor link for: zhi-shi-tan-tan-gong-zuo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我还是在一家数据库公司工作。
是的，「还是」意味着我又一次切换了工作。
12 月底的时候，我加入 OceanBase 从事数据库和 AI 生态相关的开源工作，
这已经是我职业生涯中的第三家数据库公司。&lt;&#x2F;p&gt;
&lt;p&gt;当然，在 NebulaGraph 做 GraphRAG 占据了 2025 的绝大多数时间。
尽管这个赛道已经过度拥挤并且不再火热，但我和团队里的其他同学在过去一年里还是交出了一份不错的答卷——
在特定领域的客户评测中能够达到 95% 的准确率，
总体开销也降低至可以对标向量全文混合索引，
几乎为基于图的文档类 RAG 的广泛应用铺平了道路。&lt;&#x2F;p&gt;
&lt;p&gt;至于工作派生出的产出也产生了一些积极的影响。
比如在 3 月份我调研集成 MCP 的时候，
设计和实现了 LlamaIndex 生态中的第一个 MCP 集成方案，
并且以 llama-index-tools-mcp 的形式贡献给上游。
在由社区进一步开发完善后，它成为了整个 Python 生态中下载量排在前 2% 的包。&lt;&#x2F;p&gt;
&lt;p&gt;我算不上一个醉心工作和研究的人。
若论代码品味，在过往共事过的同事中似乎也只算一般。
即便这样的我，也可以发光发热。
在 2025 年底的 NebulaGraph 社区评选中，也获得同事的肯定。
非常感谢大家的提携和帮忙，尽管江湖路远，终究还是会有机会再见面。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yuan-kai-yuan-bi-you-ni-wo&quot;&gt;愿开源庇佑你我&lt;a class=&quot;zola-anchor&quot; href=&quot;#yuan-kai-yuan-bi-you-ni-wo&quot; aria-label=&quot;Anchor link for: yuan-kai-yuan-bi-you-ni-wo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;由于工作从事的 GenAI 平台是一个商业化产品，我参与开源的模式也发生了改变，
更多时候会从需求调研和落地的角度做一些事情，
前述的 llama-index-tools-mcp 就是这样的一个产物。&lt;&#x2F;p&gt;
&lt;p&gt;当然，我围绕 coding agent 做过一些探索。
参照 ampcode 的文章做了一个简单的 Python 实现，
它的后续演进的一些探索成为了在 PyCon China 2025 上的分享
《从 0 开始构建多 Agent 协作的命令行编程助手》的基石。&lt;&#x2F;p&gt;
&lt;p&gt;作为演讲中的一个片段，我介绍了自己为 agent client protocol 做的 Python SDK。
没有想过几个月后它会被 kimi-cli、openhands 等集成，
并且最终成为官方 SDK 的一员，单月下载量过百万，我也多刷新出一个新的维护者的身份。&lt;&#x2F;p&gt;
&lt;p&gt;我在 Apache 项目上也有一些投入。
将 OpenDAL 的几个子项目从 Repo 中拆了出来，
最近又在 DataSketches 的 Rust 实现上投入了一些无处安放的夜晚。&lt;&#x2F;p&gt;
&lt;p&gt;开源是否有我并不见得会更好或更糟糕，但我确确实实会从中汲取养分和动力。
哪些我曾经拥有过的美好一切，似乎就是在和开源伴生而来。
尽管我还有太多承诺过的事情被抛在脑后，没有办法及时兑现。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ben-xiang-geng-mei-hao-de-sheng-huo&quot;&gt;奔向更美好的生活&lt;a class=&quot;zola-anchor&quot; href=&quot;#ben-xiang-geng-mei-hao-de-sheng-huo&quot; aria-label=&quot;Anchor link for: ben-xiang-geng-mei-hao-de-sheng-huo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;今年最重要的改变是：由于年底换到杭州工作，我总算结束了长达 4 年的异地恋爱，在第 8 个年头。
也解锁了更多和女朋友的美好的回忆，
比如在邓紫棋的演唱会上练习金鱼嘴，在五月天的演唱会被 wmls 投喂物料。&lt;&#x2F;p&gt;
&lt;p&gt;尝试通过学习来收获一些新技能。
虽然现在也还只是停留看着谱子弹《兰花草》的水平，
但至少又再一次能认得吉他和弦了。
练习了一段时间 house 舞种，
尽管跟上其他人的节奏对我已经是一个非常大的挑战，
但跟着节奏摇摆总是能让心情得到放松。&lt;&#x2F;p&gt;
&lt;p&gt;我有两只不那么可爱的猫咪。
有段时间一到凌晨就会扒拉开门跑到我的身上蹦迪。
坦白说，我没有把它们照顾很好。
但是枸杞还是一如既往地向我展露它的小肚皮，
芦荟在搬家到杭州以后也愿意偶尔凑过来吃一点点猫条。&lt;&#x2F;p&gt;
&lt;p&gt;生活啊，生活呵。
日日夜夜，但是提笔就不知道要写些什么了。
过得还算安好，也无甚风雨。
不久前的体检里似乎也没有再看到脂肪肝的影子。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liu-yi-xie-bi-mo-gei-ai&quot;&gt;留一些笔墨给 AI&lt;a class=&quot;zola-anchor&quot; href=&quot;#liu-yi-xie-bi-mo-gei-ai&quot; aria-label=&quot;Anchor link for: liu-yi-xie-bi-mo-gei-ai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;除了一些效率、流程和节奏上的变化，我的工作和生活并没有因为 AI 而产生更多的波澜，
毕竟价值并不会因为多了一两个工具的介入就发生显著的偏移。&lt;&#x2F;p&gt;
&lt;p&gt;我没有打算统计我有多少代码是使用 AI 生成，过去一年到底花费了多少 token 或者费用。
但是，难得地，这是一篇 100% 我手打的文字。&lt;&#x2F;p&gt;
&lt;p&gt;世界在发生着深刻的变革，很荣幸能够参与其中，作为无数浪花中拍在石头上的一朵。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>聊聊测试自信</title>
        <published>2025-12-25T00:00:00+00:00</published>
        <updated>2025-12-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/testing-confidence/"/>
        <id>https://psiace.me/zh/posts/testing-confidence/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/testing-confidence/">&lt;p&gt;在长期构建可被他人依赖的软件系统的过程中，我逐渐意识到，测试并不是一个单纯的质量保证工具，而是一种在维护者与用户之间建立信任边界的工程手段。&lt;&#x2F;p&gt;
&lt;p&gt;当一个系统缺乏这种边界时，复杂度并不会消失，而是会转移到维护者的判断、用户的使用成本，或双方的协作摩擦中。&lt;&#x2F;p&gt;
&lt;p&gt;对维护者来说，测试决定了系统是否还能被持续演进。
对用户来说，测试决定了系统是否值得被依赖。&lt;&#x2F;p&gt;
&lt;p&gt;而所谓“测试自信”，并不是来自某个测试指标，而是来自这两种视角是否通过测试被清晰地对齐。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ce-shi-bing-bu-deng-jia-yu-fu-gai-lu&quot;&gt;测试并不等价于覆盖率&lt;a class=&quot;zola-anchor&quot; href=&quot;#ce-shi-bing-bu-deng-jia-yu-fu-gai-lu&quot; aria-label=&quot;Anchor link for: ce-shi-bing-bu-deng-jia-yu-fu-gai-lu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在工程实践中，测试常常被简化为一些指标：覆盖率、CI 通过率、回归数量。
这些指标对维护者而言确实有直接价值，它们降低了修改代码时的不确定性。&lt;&#x2F;p&gt;
&lt;p&gt;但这些指标本身，并不能回答用户真正关心的问题：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;当系统被放入真实环境、真实负载和真实依赖中，它的行为是否是可预期的？&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;系统一旦被他人使用，其使用方式几乎一定会偏离设计者的预期。
测试的价值，并不在于穷举所有路径，而在于通过一组可执行的用例，把系统的预期行为和边界条件显式固定下来。&lt;&#x2F;p&gt;
&lt;p&gt;当这些边界是清晰的：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;维护者知道哪些行为不能被破坏。&lt;&#x2F;li&gt;
&lt;li&gt;用户知道哪些行为可以被依赖。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;从这个角度看，测试并不是代码的附属物，而是连接维护者与用户的一层结构。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ce-shi-shi-zai-dui-yu-yi-zuo-chang-qi-yue-shu&quot;&gt;测试是在对语义做长期约束&lt;a class=&quot;zola-anchor&quot; href=&quot;#ce-shi-shi-zai-dui-yu-yi-zuo-chang-qi-yue-shu&quot; aria-label=&quot;Anchor link for: ce-shi-shi-zai-dui-yu-yi-zuo-chang-qi-yue-shu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在 Databend 的实践中，我们大量依赖现有数据库系统中已经被验证过的测试用例，并对关键基准进行长期跟踪，以此来固定实现对既有语义和标准的承诺。&lt;&#x2F;p&gt;
&lt;p&gt;一个重要的事实是：
系统复杂度的主要来源，并不是实现难度，而是语义在时间维度上的稳定性。&lt;&#x2F;p&gt;
&lt;p&gt;例如：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;某些异常条件下应返回结果还是错误。&lt;&#x2F;li&gt;
&lt;li&gt;不同执行路径是否满足相同的不变量。&lt;&#x2F;li&gt;
&lt;li&gt;一些并不优雅、但被大量使用的行为是否需要长期兼容。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;如果这些语义没有通过测试被固定下来，对维护者而言，它们会变成一种隐性负担。
每一次修改，都需要依赖记忆和经验来判断“这会不会破坏什么”。&lt;&#x2F;p&gt;
&lt;p&gt;而对用户来说，语义漂移带来的风险更加直接。
同样的用法，在不同版本中可能产生不同结果。&lt;&#x2F;p&gt;
&lt;p&gt;因此，测试在这里承担的角色，并不是“检查代码有没有 bug”，而是：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;为维护者提供清晰的演进边界。&lt;&#x2F;li&gt;
&lt;li&gt;为用户提供稳定的行为预期。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这也是为什么像 MySQL、SQLite 这样的系统，会长期将测试视为高价值资产——因为测试本身承载的是对用户的长期承诺。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ce-shi-shi-zai-xie-diao-wei-hu-zhe-pan-duan-yu-yong-hu-xian-shi&quot;&gt;测试是在协调维护者判断与用户现实&lt;a class=&quot;zola-anchor&quot; href=&quot;#ce-shi-shi-zai-xie-diao-wei-hu-zhe-pan-duan-yu-yong-hu-xian-shi&quot; aria-label=&quot;Anchor link for: ce-shi-shi-zai-xie-diao-wei-hu-zhe-pan-duan-yu-yong-hu-xian-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在 Apache OpenDAL 的 CI 中，囊括了数百种不同的测试，提供对多平台和不同服务、binding 下的全面测试。
事实上，单一贡献者很难有精力自主筹备完整测试环境所需的一切依赖和服务。&lt;&#x2F;p&gt;
&lt;p&gt;如果说 Databend 的测试主要解决的是系统内外部语义的稳定性，那么在 Apache OpenDAL，测试更多是在解决维护者判断与用户现实之间的落差。&lt;&#x2F;p&gt;
&lt;p&gt;在对象存储生态里，很多服务都会声称自己是“S3 compatible”。
对维护者来说，只要实现了规范，就很容易形成一种假设：
系统在工程上“应该是可用的”。&lt;&#x2F;p&gt;
&lt;p&gt;但用户并不会在规范层面使用系统，他们只会在真实账户、真实服务、真实失败模式中使用它。
而大量问题，正是在这种假设与现实的落差中出现的。&lt;&#x2F;p&gt;
&lt;p&gt;因此，在 OpenDAL 中，我们始终坚持：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;尽可能使用真实服务进行测试。&lt;&#x2F;li&gt;
&lt;li&gt;不把文档和兼容性声明当作工程事实。&lt;&#x2F;li&gt;
&lt;li&gt;将失败用例长期保留，作为回归测试的一部分。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这类测试的价值在于：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;它约束了维护者对外部世界的过度乐观判断。&lt;&#x2F;li&gt;
&lt;li&gt;也为用户提供了一个明确的信号：
哪些行为是已经在现实环境中被验证过、可以依赖的。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;在这里，测试并不是为了“证明实现正确”，而是为了让维护者的判断与用户的现实使用保持一致。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ce-shi-zi-xin-rang-shuang-fang-dui-shi-bai-you-yi-zhi-li-jie&quot;&gt;测试自信：让双方对“失败”有一致理解&lt;a class=&quot;zola-anchor&quot; href=&quot;#ce-shi-zi-xin-rang-shuang-fang-dui-shi-bai-you-yi-zhi-li-jie&quot; aria-label=&quot;Anchor link for: ce-shi-zi-xin-rang-shuang-fang-dui-shi-bai-you-yi-zhi-li-jie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在这些实践中，我逐渐形成了一个比较稳定的判断：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;测试自信，并不是系统“很少出问题”，而是当问题出现时，维护者和用户对问题的性质有一致的理解。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;当某种行为被测试覆盖时：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;对用户而言，失败意味着 bug。&lt;&#x2F;li&gt;
&lt;li&gt;对维护者而言，修复是明确的工程责任。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;而当某种行为从未被测试：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;对用户而言，它就不应被视为系统承诺。&lt;&#x2F;li&gt;
&lt;li&gt;对维护者而言，也不应被默认为必须长期兼容的行为。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;测试让这种区分变得清晰、可执行、可回归，也显著降低了双方在预期上的摩擦成本。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jie-yu&quot;&gt;结语&lt;a class=&quot;zola-anchor&quot; href=&quot;#jie-yu&quot; aria-label=&quot;Anchor link for: jie-yu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;从工程角度看，测试并不是只为维护者服务的工具，也不是只为用户提供保障的机制，而是让双方在同一套行为边界上达成共识的结构。&lt;&#x2F;p&gt;
&lt;p&gt;它把隐含假设变成显式约束，把个人经验变成可以延续的工程边界。&lt;&#x2F;p&gt;
&lt;p&gt;对我而言，无论系统处在哪一层，测试最终都服务于同一件事：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;让系统在被依赖时是可预期的，
让维护在长期演进中是可持续的。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Live a Little · 下篇（2021 – 2025）</title>
        <published>2025-11-29T00:00:00+00:00</published>
        <updated>2025-11-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/live-a-little-part-2/"/>
        <id>https://psiace.me/zh/posts/live-a-little-part-2/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/live-a-little-part-2/">&lt;p&gt;&lt;strong&gt;赌城风云录&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;这一篇是 21–25 年，也是和大多数朋友开始重叠的几年。
21 年是数据库风口，24 年是 AI 狂热，我也算都赶上了。
22–24 年我住在知名博彩城，标题就从那来。
名字或许遗漏，但心中也还记着，江湖再见请你喝茶。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;shi-yi-pian&quot;&gt;拾遗篇&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-yi-pian&quot; aria-label=&quot;Anchor link for: shi-yi-pian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;早期我还写过一点前端。
用 JS 给 pitchfinder 贡献过 ACF2+ 音高检测算法，做过音频检测和可视化的小 demo。
还做过乐谱 OCR，把谱子转成乐符，再用 Java 库播放，挺好玩，只是淡了。
也做过以图搜图，提特征算相似度，试了很多组合纯粹好奇。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;databend-pian&quot;&gt;Databend 篇&lt;a class=&quot;zola-anchor&quot; href=&quot;#databend-pian&quot; aria-label=&quot;Anchor link for: databend-pian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我没数据库背景，是第一个校招生，还跳过面试。
有人问怎么做到的，我也说不清，只能感谢信任。&lt;&#x2F;p&gt;
&lt;p&gt;工作一半是工程，一半是社区。
工程是 Repo 级重构、依赖维护，偶尔写新功能。
社区源于我爱写爱分享，后来成了主线，大概分界点是落在去读书那段时间。&lt;&#x2F;p&gt;
&lt;p&gt;最早把测试从源码挪到外部单测，编译更快更干净，但要多切文件，也加了心智负担。
随着代码几年来涨得快，又做了一轮拆分提并行和质量。
sundy-li 主导的几次大规模的重构我也有参与，从 reddit 帖子发掘 &lt;code&gt;arrow2&lt;&#x2F;code&gt; ，后来又受迟先生搞类型体操的启发。&lt;&#x2F;p&gt;
&lt;p&gt;云平台的 f 叔、之晗写的 OKR 对齐文档，让我第一次感到规范节奏，于是不久后，我们就有一个可以内部把玩的云平台原型。
我还提过一个基准测试的方案，把结果写成 json 保存到 repo ，再进行可视化。
早期 Databend 像一个巨大的练习场，我几乎摸过所有角落，也开始了解数据系统该怎么呼吸。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;apache-opendal-pian&quot;&gt;Apache OpenDAL 篇&lt;a class=&quot;zola-anchor&quot; href=&quot;#apache-opendal-pian&quot; aria-label=&quot;Anchor link for: apache-opendal-pian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我和漩涡认识于他处理官网迁移的时候。
当时的存储访问层是 dal，应该是老赵设计的，但是我们需要兼顾对象存储和 HDFS。
漩涡建议重写成通用接口，于是他做了 dal2，后来独立出来成为 opendal。&lt;&#x2F;p&gt;
&lt;p&gt;菜菜子做了早期 WebHDFS 的集成，Databend 也顺势补了 hive 支持。
数据公司大抵都有一些类似的需求，opendal 被不少友商关注，在 tison 的帮助下进入基金会孵化。&lt;&#x2F;p&gt;
&lt;p&gt;在 opendal 前，我只是拿工资写开源。
在这里，我体验到不用利润目标也能靠信任合作，“community over code”。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;du-cheng-qiu-xue&quot;&gt;赌城求学&lt;a class=&quot;zola-anchor&quot; href=&quot;#du-cheng-qiu-xue&quot; aria-label=&quot;Anchor link for: du-cheng-qiu-xue&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;全职一年后我去澳门读应用数学与数据科学。
可能是宅久了，也可能是觉得还不够好，总之想出去看看。&lt;&#x2F;p&gt;
&lt;p&gt;数学课很多，上一节课要掉不少头发，好在最后也一路学过了凸优化。
AI 和大模型这时候也开始进入到我的学习和生活：利用 Meta 的 SAM 做分割，结合 CLIP 做交互式 caption，在 nanogpt 上改模型结构、优化器和学习率调度。&lt;&#x2F;p&gt;
&lt;p&gt;和 Databend 的联系仍然紧密：编译和 Rust 优化，做过几次分享；探索分析 lakeFS、HuggingFace 的数据；做 kubesphere 4.0 集成和 databend playground；办过线上 hackathon；管大部分中文文档，维护大模型转写英文文档的工作流；当时还面临企业版功能的源代码是否应该开放的讨论，我也翘课参加。&lt;&#x2F;p&gt;
&lt;p&gt;23 年 Apache Con 第一次线下见到 Xuanwo，我们各讲一个 OpenDAL 主题。
他是第一个给我寄过喜糖的同事，我也偶尔充当他的合并机器人。
那次还见到 tison、saka、f 叔、xp，还和 TCeason 一起去了颐和园。
后来又有机会见到之晗、Eric；Rust conf 认识 RisingWave 的朋友，很多 ID 和面容有了映射。&lt;&#x2F;p&gt;
&lt;p&gt;24 年去日本玩了一圈后专心毕设，主题是现代缓存替换算法。
和 juncheng 聊过一次，他主导了 sieve、s3fifo 等几个非常简洁有趣的算法设计。
毕业迫使我收拢精力，那是一段煎熬的时刻，还好我的导师总是以一副宁静的姿态出现。
我顺利毕业，也离开了 Databend，最后一次公开分享是《面向现代分层存储的 Caching 技术漫谈》。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;nebulagraph-pian&quot;&gt;NebulaGraph 篇&lt;a class=&quot;zola-anchor&quot; href=&quot;#nebulagraph-pian&quot; aria-label=&quot;Anchor link for: nebulagraph-pian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;离开 Databend 之后要再找工作。
我还想做 data infra，也想过投递一些不那么技术的岗位。
市场很冷，两家同行业公司一路面到 CXO 也没结果。
大厂面试不算投机，面试官对我的经历不太感冒，我也没有过多准备在算法和八股上。
朋友介绍了几家 web3，虽然拿到高薪 offer 但还是顾虑合规问题，只能作罢。&lt;&#x2F;p&gt;
&lt;p&gt;转机在杭州 Apache Con。
我见到几个 Graph 厂商的朋友，从慧姐和盐粒的口中才知道 NebulaGraph 的 GenAI 团队在招人，leader 是多年的推友 wey-gu。
最后一轮是 sherman，除了常规问答，还考了一道口述算法，很难想到这会出现在文化相性的面试上。&lt;&#x2F;p&gt;
&lt;p&gt;入职前我去上海参加 Rust Conf，也顺便认认上海办公室的位置。终于见到 yihong0618，一个非常有趣的灵魂。也第一次见到 RisingWave 的其他朋友，叉鸽（foyer-rs）、润基（arrow-udf），6 个月后在 KCD Beijing，我还去了他们的北京办公室，吃到了美味的小鱼干。
PyCon China 2024 上，wey 做主题分享，我认识了 frostming、晋涛，还和粉头发 saka 合了影。
到了 2025 的 Rust Conf 上，有机会见到雷少和 andy ，他们和 tison 一起创业做新产品。
再晚一点的 PyCon 我便有了一个讲 coding agent 的主题，和好多群友也是这次相会。&lt;&#x2F;p&gt;
&lt;p&gt;业余收获也多：
做了 llama index 社区的第一个 mcp 集成方案，并且贡献了第一版实现到官方 repo；
写了第一个 agentclientprotocol Python SDK，在 JetBrains 朋友帮助下成了官方 SDK；
还拜访了他们上海办公室，拎了一筐周边回家。&lt;&#x2F;p&gt;
&lt;p&gt;我们从浦东搬到南京西路，从小黑屋搬到阳光间。
慧姐离开去了 oceanbase，wey 离职创业做 nowledage memory，
我和盐粒继续在 graph rag 和 agent 上折腾，落地了当初想的 Fusion GraphRAG。
邵老师负责端到端评估，坚持先把召回率和准确率搞上去。
它让 GraphRAG 的上手成本接近向量或全文 RAG，并且在一些领域问答准确率到 95%+。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;wei-sheng&quot;&gt;尾声&lt;a class=&quot;zola-anchor&quot; href=&quot;#wei-sheng&quot; aria-label=&quot;Anchor link for: wei-sheng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;时间走到 2025 年末，好像也就到这里了。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Agent Client Protocol Python SDK 的新篇章</title>
        <published>2025-11-07T00:00:00+00:00</published>
        <updated>2025-11-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/acp-python-sdk-new-chapter/"/>
        <id>https://psiace.me/zh/posts/acp-python-sdk-new-chapter/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/acp-python-sdk-new-chapter/">&lt;p&gt;当我最初开始编写 &lt;strong&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agentclientprotocol&#x2F;python-sdk&quot;&gt;Agent Client Protocol Python SDK&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; 时，它只是一个出于好奇的小项目。
我想弄清楚 &lt;em&gt;coding agents&lt;&#x2F;em&gt; 是如何交流的——状态、意图与消息在客户端和智能体之间如何流动。&lt;&#x2F;p&gt;
&lt;p&gt;随着时间推移，它逐渐成长为一个真正有用的项目。
越来越多的开发者开始使用它，从 &lt;strong&gt;Moonshot&lt;&#x2F;strong&gt; 到其他探索智能体工作流的公司。
SDK 的架构变得稳定，并持续与 ACP 规范保持同步，成为多种实际集成的基础。&lt;&#x2F;p&gt;
&lt;p&gt;今天，是一个新的开始。
Python SDK 已经正式迁移到 &lt;strong&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agentclientprotocol&quot;&gt;agentclientprotocol&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; 组织下，与 TypeScript、Rust、Kotlin SDK 一起成为官方生态的一部分。&lt;&#x2F;p&gt;
&lt;p&gt;我会继续在新组织下维护和改进它，专注于让它更加可靠、简洁、易于集成，让更多开发者能够轻松构建智能体系统。&lt;&#x2F;p&gt;
&lt;p&gt;特别感谢 &lt;strong&gt;Sergey Ignatov&lt;&#x2F;strong&gt;、&lt;strong&gt;Anna&lt;&#x2F;strong&gt; 和 &lt;strong&gt;Ben&lt;&#x2F;strong&gt; 在整个迁移过程中给予的信任与支持，也感谢所有曾经使用、贡献或反馈过这个项目的开发者们。&lt;&#x2F;p&gt;
&lt;p&gt;这个项目最初只是一个实验，如今它已成为一个共同的努力。
愿我们一起迎接新的篇章。&lt;&#x2F;p&gt;
&lt;p&gt;— &lt;strong&gt;尚卓燃（PsiACE）&lt;&#x2F;strong&gt;
Maintainer, ACP Python SDK&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Live a Little · 上篇（2016 – 2021）</title>
        <published>2025-10-20T00:00:00+00:00</published>
        <updated>2025-10-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/live-a-little-part-1/"/>
        <id>https://psiace.me/zh/posts/live-a-little-part-1/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/live-a-little-part-1/">&lt;p&gt;&lt;strong&gt;在代码与青春之间&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;我即将二十七岁。
按新时代的算法，已经稳稳进入「老登」序列。
这一年，我的第二份正式工作也满了一年多。
回头看，想聊聊那些年我和代码之间的故事。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;2016-shao-nian-yi-qi-yu-di-yi-xing-dai-ma&quot;&gt;2016：少年意气与第一行代码&lt;a class=&quot;zola-anchor&quot; href=&quot;#2016-shao-nian-yi-qi-yu-di-yi-xing-dai-ma&quot; aria-label=&quot;Anchor link for: 2016-shao-nian-yi-qi-yu-di-yi-xing-dai-ma&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;把时间拨回 2016 年。
那时我沉迷小说，读过的大部头早已按「车载斗量」计。
Ruby 风头正盛，我用 Rails 搭过小站，也在 GitHub 上部署过 Jekyll 生成的静态页。
想写漂亮 UI 的冲动驱使我去学 HTML；
我偷偷读完了 &lt;em&gt;Digital Design and Computer Architecture&lt;&#x2F;em&gt; ——一本讲 Verilog HDL 和计算机体系结构的书。
那时我并不真正懂，只是怀着一点少年心气。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;2017-2018-da-xue-suan-fa-yu-chu-lian&quot;&gt;2017 – 2018：大学、算法与初恋&lt;a class=&quot;zola-anchor&quot; href=&quot;#2017-2018-da-xue-suan-fa-yu-chu-lian&quot; aria-label=&quot;Anchor link for: 2017-2018-da-xue-suan-fa-yu-chu-lian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;2017 年，我进入大学，主修计算机科学与技术。
学校很大，疫情前的校车也只能遍历小半个校区。
数学天赋平平，但我仍喜欢编程——因为它让我能「造点什么」。&lt;&#x2F;p&gt;
&lt;p&gt;2018 年，我试图认真地学算法与英语，已经在 Linux 环境下生活。
我读 GNU 和自由软件基金会的故事，也在 GNU.org 帮忙校对文章。
那时的我还不会 git 之外的工具，全靠前辈帮我合并推送。
在邮件列表里，我看到俊余的名字——几年后，他做的 WebP 图像服务在推特上火爆一时。&lt;&#x2F;p&gt;
&lt;p&gt;同年我写信给刚落地中国的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;leetcode.cn&#x2F;&quot;&gt;LeetCode 力扣&lt;&#x2F;a&gt;，想参与题解翻译。
Hercy 给我了第一封正式回复。
和 Winston 一起帮我做了 landing 。
如今一晃也结缘七年。&lt;&#x2F;p&gt;
&lt;p&gt;当然，2018 也有更多故事：
我挂了高数，也遇见了现在的女朋友。
那年秋天我和工作室的朋友一起看《昨日青空》，出来吃小吃时我说：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;「这电影该和女生一起看。」
后来我又买了两张票，和学妹二刷——
转眼，我们已经在一起七年。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;技术上，18 年我第三次重生 GitHub 账号，尝试 Rust 项目 Servo，学 Cargo 命令，修 README 里的构建流程。
当时谁能想到，我未来有一段工作会真正用 Rust 写代码。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;2019-fan-yi-she-qu-yu-zao-qi-xiang-mu&quot;&gt;2019：翻译、社区与早期项目&lt;a class=&quot;zola-anchor&quot; href=&quot;#2019-fan-yi-she-qu-yu-zao-qi-xiang-mu&quot; aria-label=&quot;Anchor link for: 2019-fan-yi-she-qu-yu-zao-qi-xiang-mu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;翻译比我想的走得更远。
2019 年，&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;linux.cn&#x2F;lctt&#x2F;&quot;&gt;LCTT&lt;&#x2F;a&gt; 仍是国内最活跃的 Linux 中文社区。
我在里面结识了老王和白宦成老师；我们计划合写一本书，虽最终搁浅，但那段共同写作的日子至今难忘。&lt;&#x2F;p&gt;
&lt;p&gt;技术上，Python 当时如日中天。
我学了 Flask、Django、FastAPI 皮毛，用 Cookiecutter 生成项目模板。
后来成为 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;audreyfeldroy&#x2F;cookiecutter-pypackage&quot;&gt;audreyfeldroy&#x2F;cookiecutter-pypackage&lt;&#x2F;a&gt; 的维护者——一个几千 star 的项目。
她和 Pydanny 是有名的「夫妻店」，今天依然活跃。&lt;&#x2F;p&gt;
&lt;p&gt;年底，我修完编译原理课，读 &lt;em&gt;Crafting Interpreters&lt;&#x2F;em&gt;，写了个 C 语言项目的模板 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;meco&quot;&gt;meco&lt;&#x2F;a&gt; 和玩具语言 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;emo&quot;&gt;emo&lt;&#x2F;a&gt;。
那时也尝试 Neo4j 与 NebulaGraph，做过可视化图查询的项目。
我没想到，几年后我真会在图数据库公司工作。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;2020-rust-zhi-xia-yu-fang-xiang-chu-ding&quot;&gt;2020：Rust 之夏与方向初定&lt;a class=&quot;zola-anchor&quot; href=&quot;#2020-rust-zhi-xia-yu-fang-xiang-chu-ding&quot; aria-label=&quot;Anchor link for: 2020-rust-zhi-xia-yu-fang-xiang-chu-ding&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;2020 准备考研，但心思其实一半在代码。
我从 Python 转向 Rust，入选首届 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;summer-ospp.ac.cn&#x2F;&quot;&gt;开源之夏 OSPP&lt;&#x2F;a&gt;，在 Casbin 写了 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;casbin-rs&#x2F;casbin-raft&quot;&gt;casbin-raft&lt;&#x2F;a&gt;，认识了江成和 Hackerchai。
江成后来为我写了推荐信，chai 去了 Kong。
和 OSPP 的缘分甚至更深，一直延续到今天。&lt;&#x2F;p&gt;
&lt;p&gt;同年，我在 Rust 中文社区贡献翻译：
译过 &lt;em&gt;Writing an OS in Rust&lt;&#x2F;em&gt; 中的一章，与洛佳结识——后来他做了 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustsbi&#x2F;rustsbi&quot;&gt;RustSBI&lt;&#x2F;a&gt;。
我还翻译了 nrc 的 &lt;em&gt;“Early Impressions of Go from a Rust Programmer”&lt;&#x2F;em&gt; 。
PingCAP 的 VLDB 论文成为了毕设开题材料。
这个内容在获得授权后发布在了 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;tidb-a-raft-based-htap-database&quot;&gt;PsiACE&#x2F;TiDB-A-Raft-based-HTAP-Database&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;毕业设计题是 “基于 Rust 的分布式 KV”——Raft + Bitcask。
熟悉 PingCAP 的同学应该都知道灵感出自何处。
我研究 async-raft（即 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;openraft&quot;&gt;databend&#x2F;openraft&lt;&#x2F;a&gt; 前身），也给 P 社周边库提 PR。
那年我以个人捐赠者身份支持 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;rustcc.cn&#x2F;2020rustchinaconf&#x2F;&quot;&gt;Rust China Conf 2020&lt;&#x2F;a&gt;，和夏歌、Mike、汉东有了更多交流。
后来，我还做了几年 Rust 中文社区日报编辑。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;2021-zhuan-zhe-yu-di-yi-fen-gong-zuo&quot;&gt;2021：转折与第一份工作&lt;a class=&quot;zola-anchor&quot; href=&quot;#2021-zhuan-zhe-yu-di-yi-fen-gong-zuo&quot; aria-label=&quot;Anchor link for: 2021-zhuan-zhe-yu-di-yi-fen-gong-zuo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;考研失败——毕竟我复习间隙还在给 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;xi-editor&#x2F;xi-editor&quot;&gt;xi-editor&lt;&#x2F;a&gt; 修过 lint。
我去 Wasmedge 面试实习，了解到了 WebAssembly 和 ERC20 标准，我修正的方案最后被用于社区。
又从 Meilisearch 和 Hashlink 分叉出 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;riteraft&quot;&gt;riteraft&lt;&#x2F;a&gt; 和 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;ritelinked&quot;&gt;ritelinked&lt;&#x2F;a&gt;，前者积累 300 多 star，后者成为我下载量最高的 crate 之一。&lt;&#x2F;p&gt;
&lt;p&gt;我也拿到 PingCAP 面试机会，当时项目是给 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pingcap&#x2F;tichi&quot;&gt;Tichi&lt;&#x2F;a&gt; 做贡献。
练习部署 Prow 时，第一次切身感受国内网络之艰难。
Mini256 就在那个组里——几年后，我在做 GraphRAG 时看到 TiDB 推出 AutoFlow，他也在做 RAG 了。&lt;&#x2F;p&gt;
&lt;p&gt;那段时间，我一边写论文，一边给 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;databend&quot;&gt;Databend&lt;&#x2F;a&gt; 做早期贡献，从 CI 到模糊测试，再到上游的 Arrow 和 SQL 解析器。
那时 Databend 不过 10 人左右。
我加了虎哥好友，只想向技术大佬多学习，没想到真的因此获得了工作机会。
他爽快地约我在武汉见面。
我至今记得那天的阳光——
那是创业者最有光的年纪。&lt;&#x2F;p&gt;
&lt;p&gt;6 – 7 月间，我在 Databend 上下游提了约 40 个 PR。
就这样，我加入了这个立志打造“中国版 Snowflake”的团队，开始了我的第一份真正意义上的工程师工作。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;未完待续 —— Part 2 将讲述 2022 至 2025，从 Databend 到 Apache OpenDAL 等这些年的故事。&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>用 Spec 做 SDK - 生成式 AI 的时代</title>
        <published>2025-10-15T00:00:00+00:00</published>
        <updated>2025-10-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/spec-driven-sdks/"/>
        <id>https://psiace.me/zh/posts/spec-driven-sdks/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/spec-driven-sdks/">&lt;blockquote&gt;
&lt;p&gt;AI 写得快，但容易膨胀；
Spec 很严格，但可能僵化。&lt;&#x2F;p&gt;
&lt;p&gt;我选择中间那条路——
让 AI 在边界内跑，让人对结果负责。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;wei-shen-me-bu-shi-quan-ai-ye-bu-shi-quan-spec&quot;&gt;为什么不是全 AI，也不是全 Spec&lt;a class=&quot;zola-anchor&quot; href=&quot;#wei-shen-me-bu-shi-quan-ai-ye-bu-shi-quan-spec&quot; aria-label=&quot;Anchor link for: wei-shen-me-bu-shi-quan-ai-ye-bu-shi-quan-spec&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;AI 写代码的速度让人上瘾；一旦规模扩大，很容易出现上下文漂移、结构膨胀、边界模糊——项目“能跑但不稳”。&lt;&#x2F;p&gt;
&lt;p&gt;另一个极端是 spec 驱动：严谨，但往往过重。GitHub 推出的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;github&#x2F;spec-kit&quot;&gt;Spec Kit&lt;&#x2F;a&gt; 倡导“先规范再生成”，对快速迭代的团队并不总是友好，容易过度设计、难以跟踪决策。&lt;&#x2F;p&gt;
&lt;p&gt;我走中间态：在维护 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;agentclientprotocol.com&quot;&gt;Agent Client Protocol (ACP)&lt;&#x2F;a&gt; 的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;agent-client-protocol-python&quot;&gt;&lt;strong&gt;Python SDK&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; 时，用规范约束 AI 生成，用 AI 加速规范适配。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;acp-wei-sdk-er-sheng-de-xie-yi&quot;&gt;ACP：为 SDK 而生的协议&lt;a class=&quot;zola-anchor&quot; href=&quot;#acp-wei-sdk-er-sheng-de-xie-yi&quot; aria-label=&quot;Anchor link for: acp-wei-sdk-er-sheng-de-xie-yi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;ACP 由 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;zed.dev&#x2F;blog&#x2F;bring-your-own-agent-to-zed&quot;&gt;Zed&lt;&#x2F;a&gt; 发起，定义&lt;strong&gt;编辑器 ↔ Agent&lt;&#x2F;strong&gt; 的通信方式。
它采用 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.jsonrpc.org&#x2F;specification&quot;&gt;JSON-RPC 2.0&lt;&#x2F;a&gt; 作为通信机制，并以 &lt;strong&gt;JSON Schema&lt;&#x2F;strong&gt; 描述数据结构（典型 schema 见 ACP 仓库）。边界明确、类型可机读、行为可审计——天生适合需要跨语言、长期维护的 SDK。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wo-de-shi-xian-guo-cheng&quot;&gt;我的实现过程&lt;a class=&quot;zola-anchor&quot; href=&quot;#wo-de-shi-xian-guo-cheng&quot; aria-label=&quot;Anchor link for: wo-de-shi-xian-guo-cheng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;qi-dian-zui-xiao-ke-yong-ti-mvp&quot;&gt;起点：最小可用体（MVP）&lt;a class=&quot;zola-anchor&quot; href=&quot;#qi-dian-zui-xiao-ke-yong-ti-mvp&quot; aria-label=&quot;Anchor link for: qi-dian-zui-xiao-ke-yong-ti-mvp&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;我给自己三条约束（大量使用 Coding Agent，统一由我把边界与审阅）：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;基于 datamodel 生成 &lt;strong&gt;Pydantic&lt;&#x2F;strong&gt; 模型（&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.pydantic.dev&#x2F;latest&#x2F;&quot;&gt;pydantic.dev&lt;&#x2F;a&gt;）。&lt;&#x2F;li&gt;
&lt;li&gt;实现最小 I&#x2F;O（JSON-RPC over stdio）。&lt;&#x2F;li&gt;
&lt;li&gt;迁移文档示例与基本测试，由我负责核对与回归。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;体量刻意保持小：&lt;strong&gt;先上线，尽快暴露问题&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;die-dai-cong-fan-kui-zhong-chang-chu-jie-gou&quot;&gt;迭代：从反馈中长出结构&lt;a class=&quot;zola-anchor&quot; href=&quot;#die-dai-cong-fan-kui-zhong-chang-chu-jie-gou&quot; aria-label=&quot;Anchor link for: die-dai-cong-fan-kui-zhong-chang-chu-jie-gou&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;早期用户反馈“命名不一致、使用不顺手”。
我让 agent 扫描文档生成 &lt;strong&gt;rename map&lt;&#x2F;strong&gt;（统一 Python 化命名），并对照其他语言实现取长补短：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;TypeScript SDK 里 &lt;strong&gt;helpers&lt;&#x2F;strong&gt;（降低重复样板）。&lt;&#x2F;li&gt;
&lt;li&gt;Go SDK 用 &lt;strong&gt;golden tests&lt;&#x2F;strong&gt;（固定请求&#x2F;响应样张做回归）。&lt;&#x2F;li&gt;
&lt;li&gt;Rust SDK 的模块组织更克制。&lt;&#x2F;li&gt;
&lt;li&gt;其他协议类 SDK（如 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;modelcontextprotocol.io&#x2F;&quot;&gt;MCP&lt;&#x2F;a&gt;）采用相似的协议，值得借鉴。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;在 agent 协助下完成结构与测试重组，由我把控标准与审阅路径。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lu-you-hua-ti-dai-if-pan-duan&quot;&gt;路由化：替代 if 判断&lt;a class=&quot;zola-anchor&quot; href=&quot;#lu-you-hua-ti-dai-if-pan-duan&quot; aria-label=&quot;Anchor link for: lu-you-hua-ti-dai-if-pan-duan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;我不想看到满屏的 &lt;code&gt;if method == &quot;...&quot;&lt;&#x2F;code&gt;，于是写了极简路由，把“方法名 → 处理器”变成一等公民：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;builder&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; RouterBuilder&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;request_attr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;CLIENT_METHODS&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fs_write_text_file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; WriteTextFileRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;writeTextFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;request_attr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;CLIENT_METHODS&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fs_read_text_file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;  ReadTextFileRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;  client&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;readTextFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;到 &lt;code&gt;v0.4.9&lt;&#x2F;code&gt;，体量不大，但代码 &lt;strong&gt;稳定且可教学&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shang-xia-wen-jian-xuan-rang-ai-chi-dui-dong-xi&quot;&gt;上下文拣选：让 AI 吃对东西&lt;a class=&quot;zola-anchor&quot; href=&quot;#shang-xia-wen-jian-xuan-rang-ai-chi-dui-dong-xi&quot; aria-label=&quot;Anchor link for: shang-xia-wen-jian-xuan-rang-ai-chi-dui-dong-xi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我把提示词上下文当“工程预算”管理：只喂必要信息、限定边界，并对版本负责。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;上下文清单（manifest）&lt;&#x2F;strong&gt;：只列 schema、公共接口与最小示例；排除生成代码与外部依赖。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Diff 感知&lt;&#x2F;strong&gt;：只给改动的 hunk 与少量前后文（5–15 行），而不是整文件。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;黄金片段索引&lt;&#x2F;strong&gt;：提示 agent 自检索必要片段，避免大段粘贴。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;先立护栏&lt;&#x2F;strong&gt;：明确“不得臆造 schema 字段；失败优先；缺信息先询问”。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;fang-fa-lun-spec-yu-ai-de-xie-zuo&quot;&gt;方法论：Spec 与 AI 的协作&lt;a class=&quot;zola-anchor&quot; href=&quot;#fang-fa-lun-spec-yu-ai-de-xie-zuo&quot; aria-label=&quot;Anchor link for: fang-fa-lun-spec-yu-ai-de-xie-zuo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;原则&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;说明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;生成与人工治理分离&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;模型自动生成，业务由人编排与审阅，不混用。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;从最小可用体开始&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;用真实反馈驱动人体工学优化。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Golden Test&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;捕获&#x2F;回放请求与响应，作为回归与审计基线。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;上下文拣选与预算&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;只喂必要上下文，小而准、可复现。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;规范给 AI 以边界；AI 让规范鲜活起来。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ze-ren-gan-wei-shen-me-wo-gan-dui-ai-xie-de-dai-ma-fu-ze&quot;&gt;责任感：为什么我敢对 AI 写的代码负责&lt;a class=&quot;zola-anchor&quot; href=&quot;#ze-ren-gan-wei-shen-me-wo-gan-dui-ai-xie-de-dai-ma-fu-ze&quot; aria-label=&quot;Anchor link for: ze-ren-gan-wei-shen-me-wo-gan-dui-ai-xie-de-dai-ma-fu-ze&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;AI 能写，但边界我来定义。
有强类型模型、可复现测试、可回放轨迹，我可以验证每一步。
我信任的不是模型，而是 &lt;strong&gt;它背后的工程纪律&lt;&#x2F;strong&gt; 。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wo-zai-pr-li-de-shuo-ming&quot;&gt;我在 PR 里的说明&lt;a class=&quot;zola-anchor&quot; href=&quot;#wo-zai-pr-li-de-shuo-ming&quot; aria-label=&quot;Anchor link for: wo-zai-pr-li-de-shuo-ming&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;这段说明最早见于 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Xuanwo&quot;&gt;@xuanwo&lt;&#x2F;a&gt; 的 PR。我之前没有这样写，但我愿意采用这种方式——因为我对结果负责。在这个 SDK 的工作中我大量使用了 AI；&lt;strong&gt;边界与质量由我把关&lt;&#x2F;strong&gt;：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This PR was primarily authored with GPT-5-Codex and hand-reviewed by me.
I’m responsible for every change that lands here.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这不是“炫 AI”，而是&lt;strong&gt;结果负责的声明&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jie-yu-su-du-yu-gui-dao&quot;&gt;结语：速度与轨道&lt;a class=&quot;zola-anchor&quot; href=&quot;#jie-yu-su-du-yu-gui-dao&quot; aria-label=&quot;Anchor link for: jie-yu-su-du-yu-gui-dao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;AI 是燃料，Spec 是轨道。
燃料给你速度，轨道让你抵达。&lt;&#x2F;p&gt;
&lt;p&gt;我喜欢这种平衡：模型来写，我来设边界。
每一行可解释，每一次失败可复现。
这就是在人工智能时代负责任地构建方式。&lt;&#x2F;p&gt;
&lt;p&gt;— &lt;strong&gt;PsiACE&lt;&#x2F;strong&gt; （&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&quot;&gt;GitHub&lt;&#x2F;a&gt; · &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;opendal.apache.org&#x2F;&quot;&gt;Apache OpenDAL PMC Member&lt;&#x2F;a&gt;）&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>ACP：交互契约与 Python SDK</title>
        <published>2025-09-08T00:00:00+00:00</published>
        <updated>2025-09-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/acp-and-python-sdk/"/>
        <id>https://psiace.me/zh/posts/acp-and-python-sdk/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/acp-and-python-sdk/">&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;ACP（Agent Client Protocol）是“客户端 ↔ 智能体”之间的交互契约，定义会话、内容块、工具调用、计划、文件系统等语义。&lt;&#x2F;li&gt;
&lt;li&gt;Zed 以 ACP 为核心，让内置与外部智能体共享同一套 UX，开发者只需实现一次协议即可通吃多个宿主。&lt;&#x2F;li&gt;
&lt;li&gt;我写了 Python SDK：&lt;code&gt;pip install agent-client-protocol&lt;&#x2F;code&gt;，提供 Pydantic 模型、&lt;code&gt;AgentSideConnection&lt;&#x2F;code&gt;、stdio helper，帮你快速接上。&lt;&#x2F;li&gt;
&lt;li&gt;这是一场标准化竞赛。ACP 与 MCP、A2A、AG-UI 互补又竞合，谁先积累生态谁就有话语权。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;acp-jie-jue-liao-shen-me&quot;&gt;ACP 解决了什么&lt;a class=&quot;zola-anchor&quot; href=&quot;#acp-jie-jue-liao-shen-me&quot; aria-label=&quot;Anchor link for: acp-jie-jue-liao-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;ACP 不只是“一条管道”，它规定：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;传输层用 JSON-RPC，支持流式更新；&lt;&#x2F;li&gt;
&lt;li&gt;会话生命周期（new&#x2F;load&#x2F;prompt&#x2F;cancel）清晰；&lt;&#x2F;li&gt;
&lt;li&gt;内容块支持文本、图片、音频、资源链接等；&lt;&#x2F;li&gt;
&lt;li&gt;工具调用与更新（&lt;code&gt;tool_call&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;tool_call_update&lt;&#x2F;code&gt;）格式统一；&lt;&#x2F;li&gt;
&lt;li&gt;文件读写、任务计划、状态同步都有规范字段。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;换句话说，宿主（如 Zed）与智能体之间的 UX 语义不再每家重造，体验可以搬家。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yu-qi-ta-biao-zhun-de-guan-xi&quot;&gt;与其他标准的关系&lt;a class=&quot;zola-anchor&quot; href=&quot;#yu-qi-ta-biao-zhun-de-guan-xi&quot; aria-label=&quot;Anchor link for: yu-qi-ta-biao-zhun-de-guan-xi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AG-UI&lt;&#x2F;strong&gt;：同样关注交互层，部分语义重合，可能会出现“互转&#x2F;共存”的场景。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;MCP&lt;&#x2F;strong&gt;：负责工具和资源接入，适合与 ACP 搭配使用（工具能力来自 MCP，交互流程由 ACP 承载）。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A2A&lt;&#x2F;strong&gt;：聚焦智能体之间的通信，后续也可能与 ACP 对接。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;zed-de-shi-jiao&quot;&gt;Zed 的视角&lt;a class=&quot;zola-anchor&quot; href=&quot;#zed-de-shi-jiao&quot; aria-label=&quot;Anchor link for: zed-de-shi-jiao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;使用者：可以把 Claude Code、Gemini CLI、内部 Agent 统统接进编辑器，享受一致的流式体验和工具栏。&lt;&#x2F;li&gt;
&lt;li&gt;开发者：写一次 ACP，就能跑在任何支持它的宿主上，减少重复 glue code。&lt;&#x2F;li&gt;
&lt;li&gt;平台：通过协议锁定体验，生态统一，支持成本下降。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;python-sdk-ti-gong-liao-shen-me&quot;&gt;Python SDK 提供了什么&lt;a class=&quot;zola-anchor&quot; href=&quot;#python-sdk-ti-gong-liao-shen-me&quot; aria-label=&quot;Anchor link for: python-sdk-ti-gong-liao-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;安装：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; agent-client-protocol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;功能：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pydantic v2 模型：schema 都有类型提示；&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;AgentSideConnection&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;ClientSideConnection&lt;&#x2F;code&gt;：分别处理智能体端与客户端；&lt;&#x2F;li&gt;
&lt;li&gt;stdio helper：适合 CLI&#x2F;本地进程场景；&lt;&#x2F;li&gt;
&lt;li&gt;与官方 schema 对齐，严格校验。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;zui-xiao-echo-agent&quot;&gt;最小 Echo Agent&lt;a class=&quot;zola-anchor&quot; href=&quot;#zui-xiao-echo-agent&quot; aria-label=&quot;Anchor link for: zui-xiao-echo-agent&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; acp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Agent&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; AgentSideConnection&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stdio_streams&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; acp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; InitializeRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; InitializeResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; NewSessionRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; NewSessionResponse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; acp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; PromptRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; PromptResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; AuthenticateRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; LoadSessionRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; CancelNotification&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; EchoAgent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;Agent&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; InitializeRequest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; InitializeResponse&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; InitializeResponse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;protocolVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;params&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;protocolVersion&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; newSession&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; NewSessionRequest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; NewSessionResponse&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; NewSessionResponse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;sessionId&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sess-1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; loadSession&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; LoadSessionRequest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; authenticate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; AuthenticateRequest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; prompt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; PromptRequest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; PromptResponse&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; PromptResponse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;stopReason&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;end_turn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cancel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; CancelNotification&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reader&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; writer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; stdio_streams&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    AgentSideConnection&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;lambda&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; _conn&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; EchoAgent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; writer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reader&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Event&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    asyncio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zed 侧 &lt;code&gt;settings.json&lt;&#x2F;code&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;agent_servers&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;Echo Agent (Python)&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;command&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;abs&#x2F;path&#x2F;to&#x2F;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;abs&#x2F;path&#x2F;to&#x2F;echo_agent.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;打开命令面板输入 “dev: open acp logs” 可以调试序列化。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jie-xia-lai&quot;&gt;接下来&lt;a class=&quot;zola-anchor&quot; href=&quot;#jie-xia-lai&quot; aria-label=&quot;Anchor link for: jie-xia-lai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;补充更多示例：工具调用、文件交互、计划同步；&lt;&#x2F;li&gt;
&lt;li&gt;与 MCP 结合，做端到端 demo；&lt;&#x2F;li&gt;
&lt;li&gt;观察协议演进，及时跟进 schema 变更。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;ACP 代表的是“交互语义的标准化”。当智能体要进主流工作流时，拥有统一契约就像当年云原生时代的容器、服务网格一样重要。Python SDK 的目标，就是让这件事变得简单，让反馈闭环先跑起来，再慢慢打磨。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Agent 没有秘密可言</title>
        <published>2025-08-14T00:00:00+00:00</published>
        <updated>2025-08-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/agent-has-no-secret/"/>
        <id>https://psiace.me/zh/posts/agent-has-no-secret/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/agent-has-no-secret/">&lt;blockquote&gt;
&lt;p&gt;我是 PsiACE。最近我的工作主要围绕 Agent 与 RAG 展开：&lt;strong&gt;少谈玄学，多把闭环跑通&lt;&#x2F;strong&gt;，多让系统说得清楚、跑得稳定、可被回放与切换。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent 不是新宗教&lt;&#x2F;strong&gt;。它依然是事件、队列、CRUD 的工程实践，再加一层模型协作。&lt;&#x2F;li&gt;
&lt;li&gt;共用一条 EventBus，把 &lt;code&gt;agent.*&lt;&#x2F;code&gt; 与 &lt;code&gt;huey.*&lt;&#x2F;code&gt; 事件打通；每条事件立即打印；最后用 Cascade 树复盘因果与时间。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;单文件 Demo，打开即跑&lt;&#x2F;strong&gt;：先看事件，后看因果，最后看结果。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;agent-has-no-secret&#x2F;cascade-viewer.png&quot; alt=&quot;Cascade Viewer&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;wei-shen-me-xie-zhe-ge-yi-ji-wei-shen-me-zhe-me-xie&quot;&gt;为什么写这个（以及为什么这么写）&lt;a class=&quot;zola-anchor&quot; href=&quot;#wei-shen-me-xie-zhe-ge-yi-ji-wei-shen-me-zhe-me-xie&quot; aria-label=&quot;Anchor link for: wei-shen-me-xie-zhe-ge-yi-ji-wei-shen-me-zhe-me-xie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;我不想再讨论&quot;如何画出一个复杂的 Agent 架构图&quot;。我更关心&quot;&lt;strong&gt;如何让系统解释得清楚、失败得优雅、复盘得明白&lt;&#x2F;strong&gt;&quot;。&lt;&#x2F;li&gt;
&lt;li&gt;这篇文章附带一个单文件 Demo：共享总线、严格 ReACT、因果与时间合并呈现、即时可观测。&lt;strong&gt;开箱即用&lt;&#x2F;strong&gt;。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;wo-zen-me-zuo-de&quot;&gt;我怎么做的&lt;a class=&quot;zola-anchor&quot; href=&quot;#wo-zen-me-zuo-de&quot; aria-label=&quot;Anchor link for: wo-zen-me-zuo-de&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;he-xin-she-ji-yuan-ze&quot;&gt;核心设计原则&lt;a class=&quot;zola-anchor&quot; href=&quot;#he-xin-she-ji-yuan-ze&quot; aria-label=&quot;Anchor link for: he-xin-she-ji-yuan-ze&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;共享 EventBus&lt;&#x2F;strong&gt;：Agent、ToolExecutor、Storage 都向同一条总线发事件。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;严格 ReACT&lt;&#x2F;strong&gt;：Thought → Action → Action Input → Observation → Final Answer。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;因果 + 时间&lt;&#x2F;strong&gt;：每轮用户输入推进 &lt;code&gt;tick&lt;&#x2F;code&gt;；每次 Observation 再推进 &lt;code&gt;tick&lt;&#x2F;code&gt;；&lt;code&gt;Action → huey.* → Observation&lt;&#x2F;code&gt; 通过 parent-child 串起来。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;即时可观测&lt;&#x2F;strong&gt;：每条事件实时打印；最后用树形 Cascade Viewer 做分时复盘。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;shi-jian-liu-gai-lan&quot;&gt;事件流（概览）&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-jian-liu-gai-lan&quot; aria-label=&quot;Anchor link for: shi-jian-liu-gai-lan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;agent-has-no-secret&#x2F;cascade-viewer.png&quot; alt=&quot;The Agent Loop&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zhe-he-chuan-tong-jia-gou-you-shen-me-bu-tong&quot;&gt;这和&quot;传统架构&quot;有什么不同？&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhe-he-chuan-tong-jia-gou-you-shen-me-bu-tong&quot; aria-label=&quot;Anchor link for: zhe-he-chuan-tong-jia-gou-you-shen-me-bu-tong&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;没有不同&lt;&#x2F;strong&gt;：事件、队列、CRUD，本来就在；只是把模型作为协作者接了进来。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;也不浮夸&lt;&#x2F;strong&gt;：没有&quot;智能&quot;也不会失效的设计；它可靠、可解释，也更容易落地。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;ji-jian-gu-jia-jie-xuan&quot;&gt;极简骨架（节选）&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-jian-gu-jia-jie-xuan&quot; aria-label=&quot;Anchor link for: ji-jian-gu-jia-jie-xuan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;event-driven-storage-wrapper&quot;&gt;Event-driven storage wrapper&lt;a class=&quot;zola-anchor&quot; href=&quot;#event-driven-storage-wrapper&quot; aria-label=&quot;Anchor link for: event-driven-storage-wrapper&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; EventureMemoryStorage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;MemoryStorage&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; event_bus&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; EventBus&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;        super&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;__init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;huey&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bus&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; event_bus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; enqueue&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; priority&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;        super&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;enqueue&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; priority&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;priority&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bus&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;publish&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;huey.queue.enqueue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;priority&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; priority&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;tool-with-self-description&quot;&gt;Tool with self-description&lt;a class=&quot;zola-anchor&quot; href=&quot;#tool-with-self-description&quot; aria-label=&quot;Anchor link for: tool-with-self-description&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tool_echo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;params&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Echo back text. Args: {&amp;quot;text&amp;quot;: string} Returns: {&amp;quot;ok&amp;quot;: bool, &amp;quot;echo&amp;quot;: string}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;params&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;react-loop-he-xin-si-xiang&quot;&gt;ReACT loop（核心思想）&lt;a class=&quot;zola-anchor&quot; href=&quot;#react-loop-he-xin-si-xiang&quot; aria-label=&quot;Anchor link for: react-loop-he-xin-si-xiang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;while&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;chat&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;completions&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; messages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;history&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    assistant&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; resp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;choices&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;message&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; or&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    call&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; extract&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;assistant&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; call&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        action_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; uuid4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        bus&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;publish&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;agent.action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; action_id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt;call&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; wait for agent.observation(id==action_id) and append as Observation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; assistant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;wo-zun-xun-de-ji-ge-yuan-ze&quot;&gt;我遵循的几个原则&lt;a class=&quot;zola-anchor&quot; href=&quot;#wo-zun-xun-de-ji-ge-yuan-ze&quot; aria-label=&quot;Anchor link for: wo-zun-xun-de-ji-ge-yuan-ze&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;先闭环，后花活&lt;&#x2F;strong&gt;：先把&quot;事件→队列→状态变化→ReACT&quot;打通，再谈优化。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;因果与时间是工程的一等公民&lt;&#x2F;strong&gt;：tick 表达更新周期；parent-child 表达触发链。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;可观测性优先&lt;&#x2F;strong&gt;：当系统能解释自己，优化才有基础。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;可替换&lt;&#x2F;strong&gt;：总线稳定，后端可换（内存→Redis），模型可换（供应商&#x2F;版本）。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;ru-he-yun-xing-dan-zhong-duan&quot;&gt;如何运行（单终端）&lt;a class=&quot;zola-anchor&quot; href=&quot;#ru-he-yun-xing-dan-zhong-duan&quot; aria-label=&quot;Anchor link for: ru-he-yun-xing-dan-zhong-duan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;dai-ma-wei-zhi&quot;&gt;代码位置&lt;a class=&quot;zola-anchor&quot; href=&quot;#dai-ma-wei-zhi&quot; aria-label=&quot;Anchor link for: dai-ma-wei-zhi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;请点击【阅读原文】跳转：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;psiace&#x2F;blob&#x2F;main&#x2F;demo&#x2F;agent-has-no-secret&#x2F;agent_has_no_secret.py&quot;&gt;agent_has_no_secret.py&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;psiace&#x2F;blob&#x2F;main&#x2F;demo&#x2F;agent-has-no-secret&#x2F;README.md&quot;&gt;README.md&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;yun-xing-bu-zou&quot;&gt;运行步骤&lt;a class=&quot;zola-anchor&quot; href=&quot;#yun-xing-bu-zou&quot; aria-label=&quot;Anchor link for: yun-xing-bu-zou&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;配置 &lt;code&gt;.env&lt;&#x2F;code&gt;（OpenRouter 推荐；OpenAI 也可）&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;python agent_has_no_secret.py&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;ni-jiang-kan-dao-shen-me&quot;&gt;你将看到什么&lt;a class=&quot;zola-anchor&quot; href=&quot;#ni-jiang-kan-dao-shen-me&quot; aria-label=&quot;Anchor link for: ni-jiang-kan-dao-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;实时事件流&lt;&#x2F;strong&gt;：&lt;code&gt;user.input&lt;&#x2F;code&gt;、&lt;code&gt;agent.thought&lt;&#x2F;code&gt;、&lt;code&gt;agent.action&lt;&#x2F;code&gt;、&lt;code&gt;huey.data.*&lt;&#x2F;code&gt;、&lt;code&gt;agent.observation&lt;&#x2F;code&gt; …&lt;&#x2F;li&gt;
&lt;li&gt;绿色的 &lt;strong&gt;Final Answer&lt;&#x2F;strong&gt; 面板&lt;&#x2F;li&gt;
&lt;li&gt;按 tick 分组的&lt;strong&gt;树形 Cascade Viewer&lt;&#x2F;strong&gt;：在 &lt;code&gt;agent.action&lt;&#x2F;code&gt; 下能看到 &lt;code&gt;huey.data.*&lt;&#x2F;code&gt; 与 &lt;code&gt;agent.observation&lt;&#x2F;code&gt; 的父子层级&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;xie-zai-zui-hou&quot;&gt;写在最后&lt;a class=&quot;zola-anchor&quot; href=&quot;#xie-zai-zui-hou&quot; aria-label=&quot;Anchor link for: xie-zai-zui-hou&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我更钦佩能把东西&quot;&lt;strong&gt;说清楚、跑起来&lt;&#x2F;strong&gt;&quot;的工程师。Agent 没有秘密可言：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;先把闭环打通，再考虑花活；&lt;&#x2F;li&gt;
&lt;li&gt;先让因果与代价可见，再谈&quot;更聪明&quot;。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Baby Steps: 用 Python 实现一个能自举的 Coding Agent</title>
        <published>2025-07-16T00:00:00+00:00</published>
        <updated>2025-07-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/baby-step-coding-agent/"/>
        <id>https://psiace.me/zh/posts/baby-step-coding-agent/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/baby-step-coding-agent/">&lt;p&gt;Bub 的第一个 milestone：自动修类型注解。由 Moonshot K2 驱动&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bub:&lt;&#x2F;strong&gt; Successfully fixed the first mypy issue by adding the missing return type annotation &lt;code&gt;-&amp;gt; None&lt;&#x2F;code&gt; to the &lt;code&gt;__init__&lt;&#x2F;code&gt; method in &lt;code&gt;src&#x2F;bub&#x2F;cli&#x2F;render.py&lt;&#x2F;code&gt;, reducing the error count from 24 to 23.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;1-wei-shen-me-yao-zi-ji-zao-agent&quot;&gt;1. 为什么要自己造 Agent？&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-wei-shen-me-yao-zi-ji-zao-agent&quot; aria-label=&quot;Anchor link for: 1-wei-shen-me-yao-zi-ji-zao-agent&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Coding Agent 现在已经是个红海赛道，市面上有不少优秀的产品，比如 yetone 的 avante.nvim、晋涛哥哥推荐的 AmpCode，还有许多团队在 PPT 中绘制宏伟蓝图。然而，Coding Agent 的“token 大力出奇迹”现象也很明显——动辄几十万 token 的消耗，真正有价值的部分却少之又少。这让我很好奇：如果自己动手造一个 Coding Agent，能不能找到更高效、更实用的解决方案？&lt;&#x2F;p&gt;
&lt;p&gt;于是，我开始折腾一个叫 Bub 的 CLI 助手。它的目标很简单：做一个命令行下的实用助手，同时具备有限的自举能力。自举这个概念在编译器、操作系统领域早已不算新鲜，很多 Coding Agent 也喜欢宣传“AI 工程师贡献了多少代码”。我希望 Bub 能迈出自己的第一步，解决它自身代码中的第一个实际问题。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;2-zui-xiao-ke-yong-xian-pao-qi-lai-zai-shuo&quot;&gt;2. 最小可用：先跑起来再说&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-zui-xiao-ke-yong-xian-pao-qi-lai-zai-shuo&quot; aria-label=&quot;Anchor link for: 2-zui-xiao-ke-yong-xian-pao-qi-lai-zai-shuo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我的经验是，能跑起来的最小闭环最重要，别一上来就追求“完美架构”或者花太多时间做数据小偷。&lt;&#x2F;p&gt;
&lt;p&gt;Bub 的分层很简单：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent&lt;&#x2F;strong&gt;：主循环，负责 LLM 交互、工具调用、上下文管理。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tool&lt;&#x2F;strong&gt;：每个工具一个类，参数用 Pydantic 校验。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ToolRegistry&lt;&#x2F;strong&gt;：注册所有工具，方便扩展。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;CLI&lt;&#x2F;strong&gt;：Typer + Rich，命令行入口，支持展开中间状态。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Agent 的本质其实就是一个 while 循环。每次循环，Agent 会根据当前上下文判断是否需要调用工具，如果需要就调用，然后把工具的返回结果写回上下文。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zhu-xun-huan-he-xin-dai-ma&quot;&gt;主循环核心代码&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhu-xun-huan-he-xin-dai-ma&quot; aria-label=&quot;Anchor link for: zhu-xun-huan-he-xin-dai-ma&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Agent&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; chat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;conversation_history&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;message&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        while&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 构造上下文，历史消息+工具列表&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;            ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; litellm&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;completion&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            assistant_message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;choices&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;message&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;conversation_history&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;assistant&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;assistant_message&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            tool_calls&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tool_executor&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;extract_tool_calls&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;assistant_message&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; tool_calls&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                for&lt;&#x2F;span&gt;&lt;span&gt; tool_call&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; tool_calls&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tool_executor&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;execute_tool&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tool_call&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt;tool_call&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parameters&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    observation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Observation: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;result&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;format_result&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;                    self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;conversation_history&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;observation&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span&gt; assistant_message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;踩过的坑：&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;没有捕获，LLM 输出格式一变就死循环&lt;&#x2F;li&gt;
&lt;li&gt;工具参数没校验，LLM 乱传参数直接崩&lt;&#x2F;li&gt;
&lt;li&gt;Observation 反馈太长或缺乏有效信息，LLM 理解困难&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;3-gong-ju-ding-yi-kuo-zhan-llm-de-neng-li&quot;&gt;3. 工具定义：扩展 LLM 的能力&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-gong-ju-ding-yi-kuo-zhan-llm-de-neng-li&quot; aria-label=&quot;Anchor link for: 3-gong-ju-ding-yi-kuo-zhan-llm-de-neng-li&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;工具是 LLM 和外部世界的桥梁，定义得好，模型才能真正“动手”。我的做法是：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;工具参数全部用 Pydantic 校验，类型不对直接拒绝。&lt;&#x2F;li&gt;
&lt;li&gt;命令行工具有黑名单（比如 &lt;code&gt;rm&lt;&#x2F;code&gt;、&lt;code&gt;del&lt;&#x2F;code&gt;），遇到危险命令直接报错。&lt;&#x2F;li&gt;
&lt;li&gt;工具执行结果结构化返回，别让 LLM 猜。&lt;&#x2F;li&gt;
&lt;li&gt;操作命令行工具时，stdout 和 stderr 都很重要，不能只给 exit code。&lt;&#x2F;li&gt;
&lt;li&gt;工具之间要有明确边界，避免混淆。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RunCommandTool&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;Tool&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    DANGEROUS_COMMANDS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;del&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; _validate_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; base_cmd&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Optional&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; base_cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;DANGEROUS_COMMANDS&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Dangerous command blocked: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;base_cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Context&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ToolResult&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 校验命令，执行并返回结果&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;4-prompt-she-ji-rang-llm-an-tao-lu-chu-pai&quot;&gt;4. Prompt 设计：让 LLM 按套路出牌&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-prompt-she-ji-rang-llm-an-tao-lu-chu-pai&quot; aria-label=&quot;Anchor link for: 4-prompt-she-ji-rang-llm-an-tao-lu-chu-pai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;组织良好的提示词能显著提升 LLM 的输出质量。对于 Coding Agent 来说尤其重要，因为 LLM 的输出格式很容易失控。&lt;&#x2F;p&gt;
&lt;p&gt;我的经验：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt 里要列出所有工具和参数 schema。&lt;&#x2F;li&gt;
&lt;li&gt;多给几个调用示例，覆盖常见用法。&lt;&#x2F;li&gt;
&lt;li&gt;Observation 反馈要简洁，别堆无用信息。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Bub 的 ReAct Prompt 结构：&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;You are an AI assistant with access to tools. When you need to use a tool, follow this format:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Thought: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Action: run_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Action Input: {&amp;quot;command&amp;quot;: &amp;quot;ls&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Observation: &amp;lt;output&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Final Answer: &amp;lt;your answer&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ReAct 的好处是简单直接，容易落地，虽然 token 消耗大，但能快速试错、跨模型迁移。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;5-milestone-zi-dong-xiu-lei-xing-zhu-jie&quot;&gt;5. milestone：自动修类型注解&lt;a class=&quot;zola-anchor&quot; href=&quot;#5-milestone-zi-dong-xiu-lei-xing-zhu-jie&quot; aria-label=&quot;Anchor link for: 5-milestone-zi-dong-xiu-lei-xing-zhu-jie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;定义好 Agent Loop、工具和 Prompt 后，Bub 的第一个 milestone 就是自动修复了一个 mypy 报错。&lt;&#x2F;p&gt;
&lt;p&gt;比如：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    def __init__(self):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        self.console = Console()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        self._show_debug = False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    def __init__(self) -&amp;gt; None:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        self.console: Console = Console()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        self._show_debug: bool = False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;实际的 Agent Loop：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;只让 agent 改类型注解、格式化、重命名，别让它碰复杂逻辑。&lt;&#x2F;li&gt;
&lt;li&gt;先用命令行工具执行 &lt;code&gt;mypy&lt;&#x2F;code&gt;，拿到报错信息。&lt;&#x2F;li&gt;
&lt;li&gt;让 agent 生成修复建议，再用 file edit 工具应用到代码。&lt;&#x2F;li&gt;
&lt;li&gt;修完自动再跑一次 mypy，确保没新问题。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;踩过的坑：&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;模型对代码上下文理解有限，经常修错。&lt;&#x2F;li&gt;
&lt;li&gt;不验证，bug 越修越多。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;6-jin-jie-wan-fa-yu-gong-cheng-zi-cha&quot;&gt;6. 进阶玩法与工程自查&lt;a class=&quot;zola-anchor&quot; href=&quot;#6-jin-jie-wan-fa-yu-gong-cheng-zi-cha&quot; aria-label=&quot;Anchor link for: 6-jin-jie-wan-fa-yu-gong-cheng-zi-cha&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;随着功能扩展，踩的坑也越来越多。我的一些经验：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;工具扩展时，建议单一职责，参数 schema 明确。&lt;&#x2F;li&gt;
&lt;li&gt;长对话要截断或摘要，别让 LLM 超窗。&lt;&#x2F;li&gt;
&lt;li&gt;生产环境建议沙箱&#x2F;虚拟机，命令行工具默认禁危险命令。&lt;&#x2F;li&gt;
&lt;li&gt;LLM 输出格式不稳时要有 fallback 兜底。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;7-zong-jie&quot;&gt;7. 总结&lt;a class=&quot;zola-anchor&quot; href=&quot;#7-zong-jie&quot; aria-label=&quot;Anchor link for: 7-zong-jie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Bub 还在早期，但已经能帮我自动修 bug、跑命令、读写文件。我希望这只是一个开始，然后得到更多有意思的反馈。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;baby-step-coding-agent&#x2F;bub-it.jpeg&quot; alt=&quot;Bub it. Build.it&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;can-kao-zi-liao&quot;&gt;参考资料&lt;a class=&quot;zola-anchor&quot; href=&quot;#can-kao-zi-liao&quot; aria-label=&quot;Anchor link for: can-kao-zi-liao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;ampcode.com&#x2F;how-to-build-an-agent&quot;&gt;How to Build an Agent (ampcode)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;blog&#x2F;tiny-agents&quot;&gt;Tiny Agents: Building LLM-Powered Agents from Scratch (HuggingFace)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;bub&quot;&gt;Bub: Bub it. Build it.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>让 LlamaIndex 接上 Cloudflare AI Gateway</title>
        <published>2025-07-11T00:00:00+00:00</published>
        <updated>2025-07-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/llama-index-cloudflare-ai-gateway/"/>
        <id>https://psiace.me/zh/posts/llama-index-cloudflare-ai-gateway/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/llama-index-cloudflare-ai-gateway/">&lt;h2 id=&quot;wei-shen-me-zhe-teng-zhe-ge&quot;&gt;为什么折腾这个&lt;a class=&quot;zola-anchor&quot; href=&quot;#wei-shen-me-zhe-teng-zhe-ge&quot; aria-label=&quot;Anchor link for: wei-shen-me-zhe-teng-zhe-ge&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;单供应商的 LLM 太脆弱：OpenAI 宕机、Anthropic 限流，就等于业务停摆。Cloudflare AI Gateway 给了一个诱人的承诺：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;多家模型的统一入口；&lt;&#x2F;li&gt;
&lt;li&gt;内置缓存、限流、熔断；&lt;&#x2F;li&gt;
&lt;li&gt;请求失败自动切换。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;问题是，LlamaIndex 的 LLM 调用直接命中各家 API，没法自适应 Gateway。我需要一个中间层，让原有代码不改，直接享受多云编排。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jie-jue-fang-an&quot;&gt;解决方案&lt;a class=&quot;zola-anchor&quot; href=&quot;#jie-jue-fang-an&quot; aria-label=&quot;Anchor link for: jie-jue-fang-an&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;写了一个轻量 wrapper：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;llms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cloudflare_ai_gateway&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; CloudflareAIGateway&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;llms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;openai&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; OpenAI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;llms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;anthropic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Anthropic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;openai_llm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; OpenAI&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;gpt-4o-mini&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; api_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;anthropic_llm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Anthropic&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;claude-3-5-sonnet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; api_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gateway_llm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; CloudflareAIGateway&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    llms&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;openai_llm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; anthropic_llm&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    account_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-cloudflare-account-id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    gateway&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-gateway-name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    api_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;your-cloudflare-api-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;resp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; gateway_llm&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;chat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;ChatMessage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2 + 2 = ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;作用就是：截住 LlamaIndex 发出的请求，改写为 Cloudflare 期待的格式，处理返回值。原始业务代码不用动。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;neng-zuo-shen-me&quot;&gt;能做什么&lt;a class=&quot;zola-anchor&quot; href=&quot;#neng-zuo-shen-me&quot; aria-label=&quot;Anchor link for: neng-zuo-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;顺序尝试多个模型，失败自动换下一个；&lt;&#x2F;li&gt;
&lt;li&gt;支持 Cloudflare 的流式接口、异步调用；&lt;&#x2F;li&gt;
&lt;li&gt;统一注入鉴权、重试、日志；&lt;&#x2F;li&gt;
&lt;li&gt;经过实测的模型：OpenAI、Anthropic；&lt;&#x2F;li&gt;
&lt;li&gt;理论兼容：Google AI Studio、DeepSeek、Grok、Azure OpenAI、Perplexity、Replicate 等。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;ru-he-ti-yan&quot;&gt;如何体验&lt;a class=&quot;zola-anchor&quot; href=&quot;#ru-he-ti-yan&quot; aria-label=&quot;Anchor link for: ru-he-ti-yan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;PR 在提审（&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;run-llama&#x2F;llama_index&#x2F;pull&#x2F;19395&quot;&gt;#19395&lt;&#x2F;a&gt;），不过代码已经能跑：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rep&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; llama-index-llms-cloudflare-ai-gateway&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; OPENAI_API_KEY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ANTHROPIC_API_KEY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; CLOUDFLARE_ACCOUNT_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; CLOUDFLARE_API_KEY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; CLOUDFLARE_GATEWAY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;uv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pytest&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tests&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;zhu-yi-shi-xiang&quot;&gt;注意事项&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhu-yi-shi-xiang&quot; aria-label=&quot;Anchor link for: zhu-yi-shi-xiang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Cloudflare 虽然提供 OpenAI 兼容接口，但做中间层能解锁更多功能（自定义头、特定路由、日志追踪）。&lt;&#x2F;li&gt;
&lt;li&gt;多模型编排别忘了考虑一致性：模型切换后回答风格可能不同，需要在应用层消化。&lt;&#x2F;li&gt;
&lt;li&gt;缓存命中率很依赖 prompt 规范，必要时结合 embedding 去重。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这个封装的意义不在于“又造了个轮子”，而是告诉你：在 LlamaIndex 体系里，替换底层 LLM 客户端是很容易的。运维侧想要多云容灾、成本优化，只需要写一个薄薄的适配层。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>用 WebAssembly 为 Code Agent 范式构建安全沙箱</title>
        <published>2025-07-08T00:00:00+00:00</published>
        <updated>2025-07-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/wasmtime-executor-for-code-agents/"/>
        <id>https://psiace.me/zh/posts/wasmtime-executor-for-code-agents/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/wasmtime-executor-for-code-agents/">&lt;p&gt;Code Agent（代码代理范式）的能力令人惊叹，但安全性问题同样令人担忧。在我测试第一个 Code Agent 时，它很快就尝试安装包、访问环境变量，甚至想要读取系统文件。&lt;strong&gt;我们需要一个真正安全的执行环境。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-quan-tiao-zhan&quot;&gt;安全挑战&lt;a class=&quot;zola-anchor&quot; href=&quot;#an-quan-tiao-zhan&quot; aria-label=&quot;Anchor link for: an-quan-tiao-zhan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;代码执行型 AI 代理（Code Agent 范式）确实能完成很多任务——数据分析、数学计算、代码调试。但它们缺乏对系统边界的认知，可能带来严重的安全风险。&lt;&#x2F;p&gt;
&lt;p&gt;典型的安全威胁场景：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;权限越界&lt;&#x2F;strong&gt;：尝试访问 &lt;code&gt;&#x2F;etc&#x2F;passwd&lt;&#x2F;code&gt;、系统环境变量&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;恶意包安装&lt;&#x2F;strong&gt;：从被污染的 PyPI 源安装恶意包&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;资源耗尽&lt;&#x2F;strong&gt;：无限循环、内存泄漏导致系统崩溃&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;网络攻击&lt;&#x2F;strong&gt;：发起 DDoS、端口扫描等恶意行为&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;像 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;smolagents&#x2F;blob&#x2F;main&#x2F;src&#x2F;smolagents&#x2F;remote_executors.py&quot;&gt;Hugging Face smolagents&lt;&#x2F;a&gt; 之类的项目已经意识到了这个问题，提供了多种执行器选项来平衡功能性和安全性。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;webassembly-de-an-quan-you-shi&quot;&gt;WebAssembly 的安全优势&lt;a class=&quot;zola-anchor&quot; href=&quot;#webassembly-de-an-quan-you-shi&quot; aria-label=&quot;Anchor link for: webassembly-de-an-quan-you-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;WebAssembly 的核心价值不在于性能，而在于&lt;strong&gt;原生安全设计&lt;&#x2F;strong&gt;。作为从浏览器安全模型发展而来的技术，WASM 提供了：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;能力安全模型&lt;&#x2F;strong&gt;：基于最小权限原则，只能访问明确授权的资源&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;细粒度资源控制&lt;&#x2F;strong&gt;：精确监控 CPU 使用、内存分配、网络访问&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;执行确定性&lt;&#x2F;strong&gt;：相同的输入总是产生相同的输出，便于审计&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;语言无关性&lt;&#x2F;strong&gt;：支持多种编程语言的安全执行&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Simon Willison 在他的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;til.simonwillison.net&#x2F;webassembly&#x2F;python-in-a-wasm-sandbox&quot;&gt;TIL 文章&lt;&#x2F;a&gt; 中详细探讨了这个方案，&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=34581487&quot;&gt;Hacker News 社区也有深入讨论&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;虽然 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;smolagents&quot;&gt;Hugging Face smolagents&lt;&#x2F;a&gt; 已经提供了基于 Pyodide 和 Deno 的 &lt;code&gt;WasmExecutor&lt;&#x2F;code&gt;，但我想探索一个基于 wasmtime 的本地执行方案，看看有什么不同的技术权衡。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ji-shu-shi-xian&quot;&gt;技术实现&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-shu-shi-xian&quot; aria-label=&quot;Anchor link for: ji-shu-shi-xian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;基于 wasmtime-py 和 VMware 的 Python WASM 运行时，我实现了一个简单的沙箱执行器：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; wasmtime_executor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; WasmtimePythonExecutor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; smolagents&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; CodeAgent&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; InferenceClientModel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WasmtimeCodeAgent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;CodeAgent&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; create_python_executor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; WasmtimePythonExecutor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            additional_authorized_imports&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;additional_authorized_imports&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            max_print_outputs_length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;max_print_outputs_length&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            **&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;executor_kwargs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;agent&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; WasmtimeCodeAgent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    tools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;InferenceClientModel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    additional_authorized_imports&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;math&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;json&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Calculate the square root of 125&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;核心实现思路：利用 VMware 提供的 Python WASM 二进制文件，通过 wasmtime-py 进行运行时管理，并实现与 smolagents 的兼容层。关键的技术差异在于&lt;strong&gt;本地执行&lt;&#x2F;strong&gt;，避免了对外部 Deno 运行时的依赖。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ji-shu-ping-gu&quot;&gt;技术评估&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-shu-ping-gu&quot; aria-label=&quot;Anchor link for: ji-shu-ping-gu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;优势方面：&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;与 smolagents 框架的无缝集成&lt;&#x2F;li&gt;
&lt;li&gt;基础 Python 操作的良好支持&lt;&#x2F;li&gt;
&lt;li&gt;完善的错误处理和异常捕获&lt;&#x2F;li&gt;
&lt;li&gt;执行状态的有效隔离和持久化&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;本地化部署&lt;&#x2F;strong&gt;，减少网络依赖&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;技术权衡：&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;安全隔离 vs Python 生态系统限制&lt;&#x2F;li&gt;
&lt;li&gt;执行安全性 vs 性能开销&lt;&#x2F;li&gt;
&lt;li&gt;确定性执行 vs 配置复杂性&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;本地控制&lt;&#x2F;strong&gt; vs 远程服务调用&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;sheng-chan-jiu-xu-xing&quot;&gt;生产就绪性&lt;a class=&quot;zola-anchor&quot; href=&quot;#sheng-chan-jiu-xu-xing&quot; aria-label=&quot;Anchor link for: sheng-chan-jiu-xu-xing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;当前状态：实验性项目&lt;&#x2F;strong&gt;。这个实现主要用于概念验证和技术探索。&lt;&#x2F;p&gt;
&lt;p&gt;生产环境部署需要解决的关键问题：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;资源限制和配额管理&lt;&#x2F;li&gt;
&lt;li&gt;包依赖管理和安全扫描&lt;&#x2F;li&gt;
&lt;li&gt;性能优化和缓存策略&lt;&#x2F;li&gt;
&lt;li&gt;完整的审计日志和监控&lt;&#x2F;li&gt;
&lt;li&gt;安全漏洞的持续评估&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;但对于技术研究、原型验证、理解安全边界？这个实现提供了很好的起点。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ji-shu-jia-zhi&quot;&gt;技术价值&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-shu-jia-zhi&quot; aria-label=&quot;Anchor link for: ji-shu-jia-zhi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;这个项目的真正价值不在于具体的实现代码，而在于证明了&lt;strong&gt;Code Agent 范式存在多种安全沙箱方案&lt;&#x2F;strong&gt;。虽然 smolagents 提供了基于 Pyodide 的 Deno 沙箱，wasmtime 为本地执行提供了另一种技术选择。开发者可以基于现有的代理框架，添加安全边界，保持功能完整性，同时探索不同的技术权衡。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jin-yi-bu-tan-suo&quot;&gt;进一步探索&lt;a class=&quot;zola-anchor&quot; href=&quot;#jin-yi-bu-tan-suo&quot; aria-label=&quot;Anchor link for: jin-yi-bu-tan-suo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;完整的实现代码和详细文档在我的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;psiace&#x2F;tree&#x2F;main&#x2F;demo&#x2F;wasmtime-executor&quot;&gt;Wasmtime 执行器项目&lt;&#x2F;a&gt; 中。代码虽然粗糙，但功能完整。欢迎克隆、测试、改进。&lt;&#x2F;p&gt;
&lt;p&gt;理解 Code Agent 范式安全挑战的最佳方式就是动手实践。即使是简单的概念验证项目，也能带来深刻的技术洞察。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;can-kao-zi-liao&quot;&gt;参考资料&lt;a class=&quot;zola-anchor&quot; href=&quot;#can-kao-zi-liao&quot; aria-label=&quot;Anchor link for: can-kao-zi-liao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;smolagents&quot;&gt;Hugging Face smolagents&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;psiace&#x2F;tree&#x2F;main&#x2F;demo&#x2F;wasmtime-executor&quot;&gt;Wasmtime 执行器项目&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;til.simonwillison.net&#x2F;webassembly&#x2F;python-in-a-wasm-sandbox&quot;&gt;Simon Willison 的 WASM Python 沙箱&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vmware-labs&#x2F;webassembly-language-runtimes&quot;&gt;VMware WebAssembly 语言运行时&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>当 RAG 遇上编程助手</title>
        <published>2025-06-18T00:00:00+00:00</published>
        <updated>2025-06-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/rag-in-coding-agent/"/>
        <id>https://psiace.me/zh/posts/rag-in-coding-agent/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/rag-in-coding-agent/">&lt;blockquote&gt;
&lt;p&gt;我的日常工作是和 RAG 打交道，最近 Coding Agent 大热，Claude Code 、Cursor 这样的工具已经成为了研发必备的效率神器，于是尝试调研和学习了一下，抛砖引玉。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Coding Agent 中其实不少环节都可以用到 RAG（检索增强生成），把&quot;查资料&quot;和&quot;写代码&quot;这两件事结合起来。具体来说：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;理解你想干什么&lt;&#x2F;strong&gt;：分析需求，找到相关代码和文档&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;快速定位文件&lt;&#x2F;strong&gt;：在大项目里找到关键模块&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;写出合适的代码&lt;&#x2F;strong&gt;：基于实际情况和最佳实践&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;帮你调试&lt;&#x2F;strong&gt;：分析错误，搜索解决方案&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;说白了，就是让编程助手从&quot;代码生成器&quot;变成真正的&quot;软件工程师&quot;。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;xie-dai-ma-de-zhen-shi-tong-dian&quot;&gt;写代码的真实痛点&lt;a class=&quot;zola-anchor&quot; href=&quot;#xie-dai-ma-de-zhen-shi-tong-dian&quot; aria-label=&quot;Anchor link for: xie-dai-ma-de-zhen-shi-tong-dian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;作为一个软件工程师，大部分时间我们都在干这些事：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;搞懂一个巨大项目是怎么工作的&lt;&#x2F;li&gt;
&lt;li&gt;在几百个文件里找到那个该死的模块&lt;&#x2F;li&gt;
&lt;li&gt;看着莫名其妙的报错发呆&lt;&#x2F;li&gt;
&lt;li&gt;学新框架新工具&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;rag-in-coding-agent&#x2F;swe-bench.png&quot; alt=&quot;SWE Benchmark&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;这些事情真的很烦，也很费时间。Coding Agent 应该帮我们处理这些重复劳动，让我们可以自由表达自己的想法。假如你的 “编程搭子” 还不够聪明，理解不了你的代码，找不到对的信息，那几乎只会搞砸一切，更别说帮你调试了。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;coding-agent-dao-di-shi-shen-me&quot;&gt;Coding Agent 到底是什么&lt;a class=&quot;zola-anchor&quot; href=&quot;#coding-agent-dao-di-shi-shen-me&quot; aria-label=&quot;Anchor link for: coding-agent-dao-di-shi-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;想象一下，你要做一个从没做过的功能。通常你会这样：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;先 Google 找例子&lt;&#x2F;li&gt;
&lt;li&gt;翻框架文档&lt;&#x2F;li&gt;
&lt;li&gt;在自己项目里搜类似的代码&lt;&#x2F;li&gt;
&lt;li&gt;上 StackOverflow 看看别人怎么解决的&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Coding Agent 就是一个可以自主执行这些动作的智能体，或者说把这个过程自动化了。它不仅可以充当搜索引擎进行学习，还能把找到的信息组合起来，帮你写代码。&lt;&#x2F;p&gt;
&lt;p&gt;原理其实很简单：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;检索（Retrieval）&lt;&#x2F;strong&gt;：找相关的东西——代码、文档、问答&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;生成（Generation）&lt;&#x2F;strong&gt;：用这些信息写出新的代码或解决方案&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;就这两步，但效果比单纯的代码生成器强多了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;当然，为了让一切更加顺利，还需要添加反馈机制。根据调试信息优化并进行修正。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;rag-zen-me-rang-bian-cheng-zhu-shou-bian-cong-ming&quot;&gt;RAG 怎么让编程助手变聪明&lt;a class=&quot;zola-anchor&quot; href=&quot;#rag-zen-me-rang-bian-cheng-zhu-shou-bian-cong-ming&quot; aria-label=&quot;Anchor link for: rag-zen-me-rang-bian-cheng-zhu-shou-bian-cong-ming&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;结合 RAG，编程助手就能处理我们平时遇到的各种问题了。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;rag-in-coding-agent&#x2F;coderag-bench.png&quot; alt=&quot;CodeRAG Benchmark&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;整个过程大概是这样的：&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-gao-qing-chu-ni-yao-gan-shen-me&quot;&gt;1. &lt;strong&gt;搞清楚你要干什么&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-gao-qing-chu-ni-yao-gan-shen-me&quot; aria-label=&quot;Anchor link for: 1-gao-qing-chu-ni-yao-gan-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;你说&quot;给 API 加个用户认证&quot;，助手得先理解：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;要 JWT、OAuth 还是别的方案？&lt;&#x2F;li&gt;
&lt;li&gt;现有代码哪里需要改？&lt;&#x2F;li&gt;
&lt;li&gt;你用的什么框架？&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;然后开始工作——去翻文档找例子，把你的需求搞清楚。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-shou-ji-xiang-guan-zi-liao&quot;&gt;2. &lt;strong&gt;收集相关资料&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-shou-ji-xiang-guan-zi-liao&quot; aria-label=&quot;Anchor link for: 2-shou-ji-xiang-guan-zi-liao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;然后就是搜集阶段，像个勤快的实习生一样，到处找：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;官方文档&lt;&#x2F;strong&gt;：框架的使用指南&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;代码例子&lt;&#x2F;strong&gt;：你项目里或者开源项目的类似实现&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;社区问答&lt;&#x2F;strong&gt;：StackOverflow、GitHub 上的讨论&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;最佳实践&lt;&#x2F;strong&gt;：编码规范和安全建议&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;把这些都混在一起，就是传说中的&quot;知识汤&quot;。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-xie-dai-ma-bing-ce-shi&quot;&gt;3. &lt;strong&gt;写代码并测试&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-xie-dai-ma-bing-ce-shi&quot; aria-label=&quot;Anchor link for: 3-xie-dai-ma-bing-ce-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;有了这些资料，助手就能写出比较靠谱的代码了。但它不会直接给你，而是先在沙箱里跑一遍：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;看看有没有明显的错误&lt;&#x2F;li&gt;
&lt;li&gt;确认确实能解决你的问题&lt;&#x2F;li&gt;
&lt;li&gt;有问题的话马上调整&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;4-chu-li-cheng-gong-he-shi-bai&quot;&gt;4. &lt;strong&gt;处理成功和失败&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-chu-li-cheng-gong-he-shi-bai&quot; aria-label=&quot;Anchor link for: 4-chu-li-cheng-gong-he-shi-bai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;代码跑通了当然好，但如果出错了，它不会放弃：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;分析错误信息&lt;&#x2F;li&gt;
&lt;li&gt;去找类似问题的解决方案&lt;&#x2F;li&gt;
&lt;li&gt;用新信息再试一遍&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这个循环让 Coding Agent 变得靠谱多了。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5-jiao-fu-cheng-guo&quot;&gt;5. &lt;strong&gt;交付成果&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#5-jiao-fu-cheng-guo&quot; aria-label=&quot;Anchor link for: 5-jiao-fu-cheng-guo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;最后，助手会把完整的解决方案给你——不只是代码，还有说明文档。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;zui-da-de-keng-shen-me-shi-hou-qu-cha-zi-liao&quot;&gt;最大的坑：什么时候去查资料？&lt;a class=&quot;zola-anchor&quot; href=&quot;#zui-da-de-keng-shen-me-shi-hou-qu-cha-zi-liao&quot; aria-label=&quot;Anchor link for: zui-da-de-keng-shen-me-shi-hou-qu-cha-zi-liao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;用 RAG 有个很关键的问题：&lt;strong&gt;什么时候该去查资料&lt;&#x2F;strong&gt;？&lt;&#x2F;p&gt;
&lt;p&gt;太早查可能漏掉重要信息，太晚查又会拖慢速度。我觉得这样比较合理：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;通用的东西（框架文档、编码规范）提前准备好&lt;&#x2F;li&gt;
&lt;li&gt;具体问题（调试、特殊需求）现查现用&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这样既不会太慢，也不会出错。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;shen-me-xin-xi-gai-cun-shen-me-gai-diu&quot;&gt;什么信息该存，什么该丢&lt;a class=&quot;zola-anchor&quot; href=&quot;#shen-me-xin-xi-gai-cun-shen-me-gai-diu&quot; aria-label=&quot;Anchor link for: shen-me-xin-xi-gai-cun-shen-me-gai-diu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;不是所有信息都一样重要。有些东西（比如框架规则）得一直记着，有些（比如这次运行的日志）用完就可以扔了。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;rag-in-coding-agent&#x2F;knowledge-soup.png&quot; alt=&quot;Knowledge Soup&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;这样处理可能会是一个不错的路线：&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;知识类型&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;怎么存&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;怎么找&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;编码规范&lt;&#x2F;td&gt;&lt;td&gt;一直存着&lt;&#x2F;td&gt;&lt;td&gt;知识图谱快速查找&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;文档教程&lt;&#x2F;td&gt;&lt;td&gt;按版本存&lt;&#x2F;td&gt;&lt;td&gt;语义搜索相关部分 + 代码结构映射&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;问答和代码库&lt;&#x2F;td&gt;&lt;td&gt;先临时后永久&lt;&#x2F;td&gt;&lt;td&gt;API 查询 + 缓存&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;运行时反馈&lt;&#x2F;td&gt;&lt;td&gt;临时存储&lt;&#x2F;td&gt;&lt;td&gt;即时检索和更新&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;这样既不会太慢，也不会占太多空间。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;执行的上下文越长，无效的信息越多，也需要及时压缩和截断，保留真正有效的部分。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;xiang-shi-shi-de-hua-cong-jian-dan-kai-shi&quot;&gt;想试试的话，从简单开始&lt;a class=&quot;zola-anchor&quot; href=&quot;#xiang-shi-shi-de-hua-cong-jian-dan-kai-shi&quot; aria-label=&quot;Anchor link for: xiang-shi-shi-de-hua-cong-jian-dan-kai-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;如果你也想写个编程助手，但不想搞得太复杂，可以这样开始：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;rag-in-coding-agent&#x2F;swe-agent.png&quot; alt=&quot;SWE Agent&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;先写一些规则和提示词&lt;&#x2F;li&gt;
&lt;li&gt;用简单的搜索工具找文档&lt;&#x2F;li&gt;
&lt;li&gt;写个脚本查 StackOverflow&lt;&#x2F;li&gt;
&lt;li&gt;用 &lt;code&gt;grep&lt;&#x2F;code&gt;、&lt;code&gt;lint&lt;&#x2F;code&gt; 这些工具收集反馈&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;这样就有个基础版本了，后面再慢慢改进。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;xie-zai-zui-hou&quot;&gt;写在最后&lt;a class=&quot;zola-anchor&quot; href=&quot;#xie-zai-zui-hou&quot; aria-label=&quot;Anchor link for: xie-zai-zui-hou&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Coding Agent 确实在改变编程的方式。它把&quot;查资料&quot;和&quot;写代码&quot;结合起来，让编程助手真正能帮上忙——理解你的需求、找到相关文件、写出能用的代码、帮你调试问题。&lt;&#x2F;p&gt;
&lt;p&gt;不管你是新手还是老手，这些效率工具总归能让工作轻松一些。如果你想自己搞一个，建议从简单的开始，慢慢试验。反正现在这个领域变化很快，说不定你就能做出下一个爆款工具。&lt;&#x2F;p&gt;
&lt;p&gt;总之，这个方向还是很有意思的，值得关注。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>RAG 没有捷径</title>
        <published>2025-04-17T00:00:00+00:00</published>
        <updated>2025-04-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/rag-is-the-way/"/>
        <id>https://psiace.me/zh/posts/rag-is-the-way/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/rag-is-the-way/">&lt;p&gt;去年我从数据库基础设施跳进 RAG 项目时，以为终于能摆脱底层细节，结果是另一种更复杂的基础设施扑面而来。RAG 看似应用层，其实处处是工程化的坑。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jian-suo-bu-zhi-shi-zhao-dao&quot;&gt;检索：不只是“找到”&lt;a class=&quot;zola-anchor&quot; href=&quot;#jian-suo-bu-zhi-shi-zhao-dao&quot; aria-label=&quot;Anchor link for: jian-suo-bu-zhi-shi-zhao-dao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;传统搜索里，我们调索引、调排序，指标相对稳定。RAG 的检索要面对的是语义空间——向量近邻、模型偏差、上下文漂移。今天 QA 能命中“三季度发货策略”，明天可能因为语境不同完全跑偏。检索的目标从“找到哪条记录”变成“理解用户真正想说什么，并确保返回的语段能支撑后续推理”。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;agent-bie-bei-ming-zi-pian-liao&quot;&gt;Agent：别被名字骗了&lt;a class=&quot;zola-anchor&quot; href=&quot;#agent-bie-bei-ming-zi-pian-liao&quot; aria-label=&quot;Anchor link for: agent-bie-bei-ming-zi-pian-liao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;大家给 Agent 起了很多酷炫的名字：规划代理、推理代理、工具代理……但它们大多还是条件语句堆出来的工作流。区别只是条件不是硬编码，而是 LLM 动态生成。重点不在“更智能”，而在“如何把工具、状态、反馈闭环结构化”。我们需要的是一个可观察、可替换的流程引擎，模型只是其中的决策组件。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;grounding-truth-zui-hou-de-mao-dian&quot;&gt;Grounding Truth：最后的锚点&lt;a class=&quot;zola-anchor&quot; href=&quot;#grounding-truth-zui-hou-de-mao-dian&quot; aria-label=&quot;Anchor link for: grounding-truth-zui-hou-de-mao-dian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;没有扎实的事实校验，RAG 系统只是会讲好听故事的随机鹦鹉。Grounding 不是选配，而是价值锚定。你得持续补充可验证的知识底座，让领域专家参与反馈循环，设计清晰的“证据链”输出格式。否则，Agent 再聪明也只是在幻觉上做推理。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fu-za-xing-cong-na-li-lai&quot;&gt;复杂性从哪里来&lt;a class=&quot;zola-anchor&quot; href=&quot;#fu-za-xing-cong-na-li-lai&quot; aria-label=&quot;Anchor link for: fu-za-xing-cong-na-li-lai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;数据形态多样&lt;&#x2F;strong&gt;：PDF、截图、音视频、传感器数据同时存在，且要保持语义一致。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;一致性概念模糊&lt;&#x2F;strong&gt;：知识会被实时更新，旧答案随时过期。你需要定义“足够新”“足够可信”的标准。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;成本与体验拉扯&lt;&#x2F;strong&gt;：检索准确度、上下文长度、延迟、推理深度，一环牵动一环。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这比建一个数据库、一个 API 难多了，但也更有意思。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wei-shen-me-huan-yao-gan&quot;&gt;为什么还要干&lt;a class=&quot;zola-anchor&quot; href=&quot;#wei-shen-me-huan-yao-gan&quot; aria-label=&quot;Anchor link for: wei-shen-me-huan-yao-gan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;因为我们在重新定义“信息系统”：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;让系统理解人的意图，而不是死背关键词；&lt;&#x2F;li&gt;
&lt;li&gt;让工具链能自我学习、自动拼装；&lt;&#x2F;li&gt;
&lt;li&gt;把抽象的语言推理和现实世界的事实连接起来。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这是一种新的基础设施：检索、智能体与真实感三元同构。谁能把这三者编排好，谁就掌握下一代知识系统的主动权。&lt;&#x2F;p&gt;
&lt;p&gt;所以，当别人问我为什么离开数据库领域去做 AI 应用时，我会说：“我没离开基础设施，我只是换了一种方式去构建它。”&lt;&#x2F;p&gt;
&lt;p&gt;现在，请允许我回去调向量量化、训几个不听话的 Agent，并确保文本切分策略不会把事实撕裂。这，就是日常的 RAG 工程。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>NebulaGraph MCP Server 正式开源！探索 AI+图数据库无限可能</title>
        <published>2025-03-11T00:00:00+00:00</published>
        <updated>2025-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/announcing-nebulagraph-mcp-server-v010/"/>
        <id>https://psiace.me/zh/posts/announcing-nebulagraph-mcp-server-v010/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/announcing-nebulagraph-mcp-server-v010/">&lt;h2 id=&quot;yi-bei-jing&quot;&gt;一、背景&lt;a class=&quot;zola-anchor&quot; href=&quot;#yi-bei-jing&quot; aria-label=&quot;Anchor link for: yi-bei-jing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;过去几周，Model Context Protocol (MCP) 在技术社区中引发了广泛的讨论和关注。借此机会，我参与了几个相关的开源项目，包括为 &lt;strong&gt;LlamaIndex 官方仓库贡献了 McpToolSpec 实现&lt;&#x2F;strong&gt;，以及和 Xuanwo、FrostMing 合作开发了一版 &lt;strong&gt;Model Context Protocol Server for Apache OpenDAL™&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;MCP 是目前唯一一个在生态上具有优势的标准。在这一背景下，我们 &lt;strong&gt;基于 NebulaGraph 3.x 实现了一个简单的 NebulaGraph MCP Server，作为 NebulaGraph X MCP 生态中的第一个基础组件，供大家探索 AI 与图数据库结合的可能性&lt;&#x2F;strong&gt;，希望能够看到更多在这个模式下的有趣工作。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;er-model-context-protocol-mcp&quot;&gt;二、Model Context Protocol (MCP)&lt;a class=&quot;zola-anchor&quot; href=&quot;#er-model-context-protocol-mcp&quot; aria-label=&quot;Anchor link for: er-model-context-protocol-mcp&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;MCP 是由 Anthropic 团队推出的一项开放协议，旨在为 AI 系统提供统一的、高效的方式访问多种数据资源。通过采用客户端-服务器架构，MCP 将数据访问标准化，解决了传统 AI 系统在不同数据源之间的碎片化问题。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mcp-he-xin-te-dian&quot;&gt;MCP 核心特点&lt;a class=&quot;zola-anchor&quot; href=&quot;#mcp-he-xin-te-dian&quot; aria-label=&quot;Anchor link for: mcp-he-xin-te-dian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;标准化的通信方式&lt;&#x2F;strong&gt;：通过 MCP，AI 助手能够有效地访问各种数据源，比如本地数据、远程服务和企业工具。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;开放性与生态优势&lt;&#x2F;strong&gt;：目前 MCP 社区中已有近 1000 个 MCP Server 实现，覆盖搜索、天气、数据库等多个领域，支持工具的快速接入。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;灵活的架构&lt;&#x2F;strong&gt;：通过定义客户端和服务端的交互协议，MCP 为开发者提供了构建可扩展、可复用系统的基础。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;虽然目前在安全性和可靠性上仍有一些挑战，但随着协议规范的完善和成熟开发模式的引入，这些问题将逐步得到解决。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;san-nebulagraph-mcp-server-gong-neng&quot;&gt;三、NebulaGraph MCP Server 功能&lt;a class=&quot;zola-anchor&quot; href=&quot;#san-nebulagraph-mcp-server-gong-neng&quot; aria-label=&quot;Anchor link for: san-nebulagraph-mcp-server-gong-neng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;由于最近一段时间一直围绕 GraphRAG 和 Agentic Workflow 做一些工作，利用大模型和智能体进行图上数据的洞见和挖掘是一个非常重要的议题。为此，我快速开发了 NebulaGraph MCP Server，以支持 NebulaGraph 3.x 作为工具接入 MCP 生态，供语言模型（如 Claude、GPT 等）调用和使用。&lt;&#x2F;p&gt;
&lt;p&gt;目前 &lt;strong&gt;NebulaGraph MCP Server 基于 FastMCP 实现，遵循 MCP 的核心规范，旨在提供高效、轻量的图数据库连接服务。&lt;&#x2F;strong&gt; 通过将 NebulaGraph 的功能暴露为标准化的工具接口，该 Server 能够让大模型轻松调用 NebulaGraph 数据，实现简单的图探索任务。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多种传输方式&lt;&#x2F;strong&gt;：
&lt;ul&gt;
&lt;li&gt;支持 stdio 和 SSE 两种传输模式，满足不同开发和部署场景的需求。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;基础图探索能力&lt;&#x2F;strong&gt;：
&lt;ul&gt;
&lt;li&gt;图空间（Graph Space）列出：允许模型查询可用的图空间。&lt;&#x2F;li&gt;
&lt;li&gt;模式（Schema）查询：支持查询指定图空间的模式定义。&lt;&#x2F;li&gt;
&lt;li&gt;查询执行（Query Execution）：支持通过 MCP Server 执行 NebulaGraph 查询。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;内置算子模板&lt;&#x2F;strong&gt;：
&lt;ul&gt;
&lt;li&gt;实现了路径搜索和邻居发现等常用操作的模板，方便语言模型按需调用这些工具，快速获取图数据的初步洞察（Insight）。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;为了展示它的效果，我基于 LlamaIndex 中的 McpToolSpec 和 ReActAgent 构建了一个简单的示例，下面是对应的截图：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;announcing-nebulagraph-mcp-server-v010&#x2F;llamaindex-with-nebulagraph-mcp.png&quot; alt=&quot;LlamaIndex with NebulaGraph MCP&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;si-jie-yu&quot;&gt;四、结语&lt;a class=&quot;zola-anchor&quot; href=&quot;#si-jie-yu&quot; aria-label=&quot;Anchor link for: si-jie-yu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;NebulaGraph MCP Server&lt;&#x2F;strong&gt; 是对 MCP 生态的一个初步尝试，旨在为语言模型和图数据库的结合提供一个起点。随着协议的逐步成熟和生态的扩展，我们期待它能够在更多真实场景中发挥价值。如果您对这一方向感兴趣，欢迎一起探索、尝试！&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>把 MCP 工具塞进 LlamaIndex 工作流</title>
        <published>2025-02-11T00:00:00+00:00</published>
        <updated>2025-02-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/integrate-mcp-tools-into-llamaindex/"/>
        <id>https://psiace.me/zh/posts/integrate-mcp-tools-into-llamaindex/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/integrate-mcp-tools-into-llamaindex/">&lt;h2 id=&quot;yi-qian-yan&quot;&gt;一、前言&lt;a class=&quot;zola-anchor&quot; href=&quot;#yi-qian-yan&quot; aria-label=&quot;Anchor link for: yi-qian-yan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;本文主要介绍了如何将 MCP（Model Context Protocol，模型上下文协议）工具转换为可以直接使用的 LlamaIndex 工具，使 LlamaIndex 用户能像使用 Claude, Cursor 等现代 AI 应用一样无缝集成这些服务。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;er-ji-shu-bei-jing&quot;&gt;二、技术背景&lt;a class=&quot;zola-anchor&quot; href=&quot;#er-ji-shu-bei-jing&quot; aria-label=&quot;Anchor link for: er-ji-shu-bei-jing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2-1-shen-me-shi-mcp-xie-yi&quot;&gt;2.1 什么是 MCP 协议？&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-1-shen-me-shi-mcp-xie-yi&quot; aria-label=&quot;Anchor link for: 2-1-shen-me-shi-mcp-xie-yi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;MCP（模型上下文协议，https:&#x2F;&#x2F;modelcontextprotocol.io）是面向 AI 应用交互的服务构建协议。开发者可通过该协议构建具备数据资源（resources）、功能工具（tools）和提示模板（prompts）的服务端点。例如，我们可以定义获取 IP 详细信息的 fetch_ipinfo 工具：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mcp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;tool&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fetch_ipinfo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;kwargs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; IPDetails&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;获取指定IP的详细信息&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    参数:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        ip(str or None): 目标 IP 地址，格式如 192.168.1.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        **kwargs: 传递给 IPInfo 处理器的附加参数&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    返回:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        IPDetails: 包含城市、时区等信息的结构化数据&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    handler&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ipinfo&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        access_token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;IPINFO_API_TOKEN&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user-agent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;basic-mcp-server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        **&lt;&#x2F;span&gt;&lt;span&gt;kwargs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    details&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; handler&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getDetails&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ip_address&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;ip&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; IPDetails&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;details&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;all&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;2-2-llamaindex-kuang-jia-te-zheng&quot;&gt;2.2 LlamaIndex 框架特征&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-2-llamaindex-kuang-jia-te-zheng&quot; aria-label=&quot;Anchor link for: 2-2-llamaindex-kuang-jia-te-zheng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;LlamaIndex（https:&#x2F;&#x2F;github.com&#x2F;run-llama&#x2F;llama_index）是构建知识索引系统的核心框架，其核心价值在于将外部信息结构化地接入大语言模型，实现高效的信息检索、智能问答和对话生成。当需要集成动态数据源时，将 MCP 工具转换为 LlamaIndex 工具成为关键技术需求。&lt;&#x2F;p&gt;
&lt;p&gt;在 LlamaIndex 中，NebulaGraph 已经有两种方法实现 GraphRAG：KnowledgeGraphIndex 用来对任何私有数据从零构建知识图谱（基于 LLM 或者其他语言模型），再 4 行代码进行 Graph RAG：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph_store&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; NebulaGraphStore&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    space_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;space_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    edge_types&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;edge_types&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    rel_prop_names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;rel_prop_names&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    tags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tags&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;storage_context&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; StorageContext&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;from_defaults&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;graph_store&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;graph_store&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Build KG&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kg_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; KnowledgeGraphIndex&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;from_documents&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    documents&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    storage_context&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;storage_context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    max_triplets_per_chunk&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    space_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;space_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    edge_types&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;edge_types&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    rel_prop_names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;rel_prop_names&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    tags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tags&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kg_query_engine&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; kg_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;as_query_engine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;KnowledgeGraphRAGQueryEngine 则可以在任何已经存在的知识图谱上进行 GraphRAG:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph_store&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; NebulaGraphStore&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    space_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;space_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    edge_types&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;edge_types&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    rel_prop_names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;rel_prop_names&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    tags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tags&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;storage_context&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; StorageContext&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;from_defaults&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;graph_store&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;graph_store&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph_rag_query_engine&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; KnowledgeGraphRAGQueryEngine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    storage_context&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;storage_context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;san-wei-shen-me-xu-yao-jiang-mcp-ji-cheng-zhi-llamaindex&quot;&gt;三、为什么需要将 MCP 集成至 LlamaIndex&lt;a class=&quot;zola-anchor&quot; href=&quot;#san-wei-shen-me-xu-yao-jiang-mcp-ji-cheng-zhi-llamaindex&quot; aria-label=&quot;Anchor link for: san-wei-shen-me-xu-yao-jiang-mcp-ji-cheng-zhi-llamaindex&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;在实际 AI 应用开发中，集成 MCP 工具主要解决以下需求：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;功能复用：利用现有 MCP 生态（项目列表见 https:&#x2F;&#x2F;github.com&#x2F;AlexMili&#x2F;Awesome-MCP）快速扩展系统能力&lt;&#x2F;li&gt;
&lt;li&gt;流程统一：建立标准化工具调用范式，简化大模型对外部 API 的调用复杂度&lt;&#x2F;li&gt;
&lt;li&gt;自动化管理：通过自动转换机制实现 MCP 工具到 LlamaIndex FunctionTool 对象的映射，便于 Agent 自动调度&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;该集成方案可以有效降低开发成本，同时发挥 LlamaIndex 在上下文管理和对话生成方面的优势。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;si-ji-shu-shi-xian-fang-an&quot;&gt;四、技术实现方案&lt;a class=&quot;zola-anchor&quot; href=&quot;#si-ji-shu-shi-xian-fang-an&quot; aria-label=&quot;Anchor link for: si-ji-shu-shi-xian-fang-an&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;实现流程包含三个关键阶段：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;MCP 服务通信：通过 MCPClient 类建立服务连接，支持工具发现（list_tools）和调用执行（call_tool）&lt;&#x2F;li&gt;
&lt;li&gt;适配器构建：定义 MCPToolAdapter 类，将 MCP 工具元数据转换为 LlamaIndex 的 FunctionTool 对象&lt;&#x2F;li&gt;
&lt;li&gt;智能代理集成：在 LlamaIndex Agent 中加载转换后的工具，实现自动化调用&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;wu-he-xin-dai-ma-jie-xi&quot;&gt;五、核心代码解析&lt;a class=&quot;zola-anchor&quot; href=&quot;#wu-he-xin-dai-ma-jie-xi&quot; aria-label=&quot;Anchor link for: wu-he-xin-dai-ma-jie-xi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;xie-yi-zhuan-huan-gua-pei-qi&quot;&gt;协议转换适配器&lt;a class=&quot;zola-anchor&quot; href=&quot;#xie-yi-zhuan-huan-gua-pei-qi&quot; aria-label=&quot;Anchor link for: xie-yi-zhuan-huan-gua-pei-qi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; FunctionTool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; pydantic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; create_model&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; BaseModel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; MCPToolAdapter&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; client&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; list_tools&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        tools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;list_tools&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            FunctionTool&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;from_defaults&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;_create_tool_fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tool&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tool&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tool&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;description&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                fn_schema&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;_create_pydantic_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tool&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;schema&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; tool&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; _create_pydantic_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; json_schema&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 实现JSON Schema到Pydantic模型的动态转换&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;lei-xing-xi-tong-ying-she&quot;&gt;类型系统映射&lt;a class=&quot;zola-anchor&quot; href=&quot;#lei-xing-xi-tong-ying-she&quot; aria-label=&quot;Anchor link for: lei-xing-xi-tong-ying-she&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;JSON_TYPE_MAPPING&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;number&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; float&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;boolean&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;object&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; create_dynamic_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;schema&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; prop&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;properties&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;items&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        py_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; JSON_TYPE_MAPPING&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;prop&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;required&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            fields&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;py_type&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Field&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            fields&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;Optional&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;py_type&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Field&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; create_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;DynamicModel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt;fields&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;fu-wu-diao-yong-feng-zhuang&quot;&gt;服务调用封装&lt;a class=&quot;zola-anchor&quot; href=&quot;#fu-wu-diao-yong-feng-zhuang&quot; aria-label=&quot;Anchor link for: fu-wu-diao-yong-feng-zhuang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fetch_ipinfo_wrapper&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;**&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;kwargs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; mcp_client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;call_tool&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fetch_ipinfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; kwargs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;guan-jian-ji-shu-chuang-xin-dian&quot;&gt;关键技术创新点&lt;a class=&quot;zola-anchor&quot; href=&quot;#guan-jian-ji-shu-chuang-xin-dian&quot; aria-label=&quot;Anchor link for: guan-jian-ji-shu-chuang-xin-dian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;动态模式转换：实现 JSON Schema 到 Pydantic 模型的运行时转换，保证参数校验的严格性&lt;&#x2F;li&gt;
&lt;li&gt;异步调用管道：基于 Python asyncio 构建非阻塞式服务调用，提升工具执行效率&lt;&#x2F;li&gt;
&lt;li&gt;协议抽象层：通过适配器模式解耦 MCP 协议与 LlamaIndex 框架，保证系统扩展性&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;将 MCP 工具的输入参数转换为 Pydantic 模型的原因在于：MCP 工具使用 JSON Schema 格式定义输入参数（在工具对象的 inputSchema 中，类型为 Dict[str, Any] ），而 create_model_from_json_schema 函数将其转换为 Pydantic 模型，该模型用作 LlamaIndex 中 FunctionTool 的 fn_schema。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liu-llamaindex-zhong-de-mcp-gong-ju-diao-yong-shi-jian&quot;&gt;六、LlamaIndex 中的 MCP 工具调用实践&lt;a class=&quot;zola-anchor&quot; href=&quot;#liu-llamaindex-zhong-de-mcp-gong-ju-diao-yong-shi-jian&quot; aria-label=&quot;Anchor link for: liu-llamaindex-zhong-de-mcp-gong-ju-diao-yong-shi-jian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;以下代码来自 llamaindex_mcp_example.py，完整展示了 MCPToolAdapter 与 LlamaIndex 的集成方式：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;llms&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; ChatMessage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;agent&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; ReActAgent&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ReActChatFormatter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;agent&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;react&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;prompts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; REACT_CHAT_SYSTEM_HEADER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;llms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;azure_openai&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; AzureOpenAI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llamaindex_mcp_adapter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; MCPToolAdapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; mcp_client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; MCPClient&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; anyio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; dotenv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; argparse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dotenv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;load_dotenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 系统级指令模板&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;SYSTEM_PROMPT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;您是一个智能法律助手&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;在回答用户问题前，必须通过IP信息确认用户所在司法管辖区&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;操作规则：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;- 当涉及地理位置、时区等问题时，自动调用fetch_ipinfo工具&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;- 法律咨询类问题需结合IP所在国家&#x2F;地区法律体系&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; get_agent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;adapter&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; MCPToolAdapter&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;智能代理初始化函数&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; adapter&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;list_tools&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 获取MCP工具列表&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 配置Azure OpenAI大语言模型&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    llm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; AzureOpenAI&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AZURE_OPENAI_MODEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;gpt-4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        max_tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AZURE_OPENAI_MAX_TOKENS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4096&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        azure_endpoint&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AZURE_OPENAI_ENDPOINT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        api_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AZURE_OPENAI_API_KEY&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        api_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AZURE_OPENAI_API_VERSION&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        engine&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AZURE_OPENAI_ENGINE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 构建ReAct智能代理&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    agent&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ReActAgent&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;from_tools&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        llm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;llm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        tools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tools&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        react_chat_formatter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;ReActChatFormatter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            system_header&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;SYSTEM_PROMPT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; REACT_CHAT_SYSTEM_HEADER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        max_iterations&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 限制最大推理步数&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        verbose&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;True&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 启用详细日志&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; handle_user_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;message_content&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; agent&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; ReActAgent&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;消息处理流水线&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ChatMessage&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;from_str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;message_content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;achat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;user_message&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[智能代理响应] &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 命令行参数解析&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        parser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; argparse&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ArgumentParser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_argument&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;--client_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                          choices&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdio&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                          default&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdio&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                          help&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;连接模式：sse(Server-Sent Events)或stdio(标准输入输出)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        args&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parse_args&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; MCP客户端初始化&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;client_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; MCPClient&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;http:&#x2F;&#x2F;0.0.0.0:8000&#x2F;sse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; SSE长连接模式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; MCPClient&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                            #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 子进程模式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;                &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;venv&#x2F;bin&#x2F;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;mcp_server.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;--server_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdio&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 工具适配器初始化&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        adapter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; MCPToolAdapter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;client&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        agent&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; get_agent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;adapter&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 执行测试用例&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        await&lt;&#x2F;span&gt;&lt;span&gt; handle_user_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;我的IP所在城市是哪里？&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        await&lt;&#x2F;span&gt;&lt;span&gt; handle_user_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;持有大麻在我国是否合法？&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    anyio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 启动异步运行时&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;guan-jian-shi-xian-jie-xi&quot;&gt;关键实现解析&lt;a class=&quot;zola-anchor&quot; href=&quot;#guan-jian-shi-xian-jie-xi&quot; aria-label=&quot;Anchor link for: guan-jian-shi-xian-jie-xi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;工具获取机制：
&lt;ul&gt;
&lt;li&gt;通过 adapter.list_tools() 动态加载 MCP 服务端注册的工具列表&lt;&#x2F;li&gt;
&lt;li&gt;自动将每个 MCP 工具转换为 LlamaIndex 的 FunctionTool 对象&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;智能代理配置：
&lt;ul&gt;
&lt;li&gt;使用 Azure OpenAI 作为底层大语言模型引擎&lt;&#x2F;li&gt;
&lt;li&gt;集成 ReAct 推理框架，支持多步工具调用&lt;&#x2F;li&gt;
&lt;li&gt;设置 20 步的最大推理深度防止无限循环&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;消息处理流程：
&lt;ul&gt;
&lt;li&gt;将用户输入封装为标准化 ChatMessage&lt;&#x2F;li&gt;
&lt;li&gt;通过 agent.achat() 触发自动化工具调用链&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;qi-yun-xing-demo&quot;&gt;七、运行 Demo&lt;a class=&quot;zola-anchor&quot; href=&quot;#qi-yun-xing-demo&quot; aria-label=&quot;Anchor link for: qi-yun-xing-demo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;7-1-biao-zhun-shu-ru-shu-chu-mo-shi&quot;&gt;7.1 标准输入输出模式&lt;a class=&quot;zola-anchor&quot; href=&quot;#7-1-biao-zhun-shu-ru-shu-chu-mo-shi&quot; aria-label=&quot;Anchor link for: 7-1-biao-zhun-shu-ru-shu-chu-mo-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; llamaindex_mcp_example.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-client_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; stdio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;zhi-xing-shu-chu-shi-li&quot;&gt;执行输出示例&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhi-xing-shu-chu-shi-li&quot; aria-label=&quot;Anchor link for: zhi-xing-shu-chu-shi-li&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[DEBUG] 检测到ListToolsRequest协议请求&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[工具调用] 步骤ID: ede14770-91c9-428b... | 输入: 我的IP所在城市是哪里？&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[推理日志] 当前用户语言：中文，需调用工具获取数据&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[动作触发] fetch_ipinfo | 参数: {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[网络请求] 调用MCP工具耗时128ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[观察结果] {&amp;quot;ip&amp;quot;: &amp;quot;183.193.123.192&amp;quot;, &amp;quot;city&amp;quot;: &amp;quot;上海&amp;quot;, &amp;quot;country&amp;quot;: &amp;quot;CN&amp;quot;...}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[最终响应] 您的IP所在城市为上海&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[法律咨询] 步骤ID: e728f5d0-6c0e-454a... | 输入: 持有大麻是否合法？&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[推理日志] 已确认用户所在国家：中国&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[知识库检索] 加载中国刑法第357条&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[最终响应] 根据中国法律，持有大麻属违法行为，最高可判处有期徒刑&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;7-2-sse-fu-wu-mo-shi&quot;&gt;7.2 SSE 服务模式&lt;a class=&quot;zola-anchor&quot; href=&quot;#7-2-sse-fu-wu-mo-shi&quot; aria-label=&quot;Anchor link for: 7-2-sse-fu-wu-mo-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 终端1：启动SSE服务端&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mcp_server.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-server_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 终端2：运行客户端&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; llamaindex_mcp_example.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-client_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;ba-ji-shu-fang-an-zong-jie&quot;&gt;八、技术方案总结&lt;a class=&quot;zola-anchor&quot; href=&quot;#ba-ji-shu-fang-an-zong-jie&quot; aria-label=&quot;Anchor link for: ba-ji-shu-fang-an-zong-jie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;通过以下三步实现深度集成：&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xie-yi-tong-xin-ceng&quot;&gt;协议通信层&lt;a class=&quot;zola-anchor&quot; href=&quot;#xie-yi-tong-xin-ceng&quot; aria-label=&quot;Anchor link for: xie-yi-tong-xin-ceng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;基于 MCPClient 实现服务发现与工具调用&lt;&#x2F;li&gt;
&lt;li&gt;支持 SSE&#x2F;STDIO 双模连接，适应不同部署场景&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;lei-xing-zhuan-huan-ceng&quot;&gt;类型转换层&lt;a class=&quot;zola-anchor&quot; href=&quot;#lei-xing-zhuan-huan-ceng&quot; aria-label=&quot;Anchor link for: lei-xing-zhuan-huan-ceng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;动态将 JSON Schema 转换为 Pydantic 模型&lt;&#x2F;li&gt;
&lt;li&gt;实现参数自动校验与类型提示&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; create_dynamic_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;schema&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 自动生成带字段描述的Pydantic模型&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;map_type&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;prop&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Field&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;prop&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; prop&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;properties&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;items&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; create_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;DynamicModel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt;fields&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;zhi-neng-dai-li-ceng&quot;&gt;智能代理层&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhi-neng-dai-li-ceng&quot; aria-label=&quot;Anchor link for: zhi-neng-dai-li-ceng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;集成 ReAct 推理框架实现自动化工具调度&lt;&#x2F;li&gt;
&lt;li&gt;通过系统提示词约束工具使用规范&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;SYSTEM_PROMPT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;法律咨询必须遵循以下规则：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;1. 首次响应前必须调用fetch_ipinfo确认用户辖区&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;2. 引用法律条文需标注具体条款编号&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;3. 不得对未覆盖地区提供法律建议&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;通过持续扩展 MCP 生态，开发者可快速构建具备专业领域能力的智能代理系统。欢迎访问 MCP 开发者社区获取更多工具资源。&lt;&#x2F;p&gt;
&lt;p&gt;查看源代码：https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;psiac&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>VLM 解析非结构化图像：一个极简可扩展方案</title>
        <published>2024-11-28T00:00:00+00:00</published>
        <updated>2024-11-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/a-dead-simple-way-to-vlm-parsing/"/>
        <id>https://psiace.me/zh/posts/a-dead-simple-way-to-vlm-parsing/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/a-dead-simple-way-to-vlm-parsing/">&lt;p&gt;这篇文章展示一种非常直接的做法：用 VLM（Visual Language Models）解析图片中的非结构化信息。&lt;&#x2F;p&gt;
&lt;p&gt;它足够简单，但也保留了明确的扩展路径，比如继续支持 PDF、表格、视频帧等更复杂场景。&lt;&#x2F;p&gt;
&lt;p&gt;如果你想要一条更重型的工业化路线，可以看 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.llamaindex.ai&#x2F;llamaparse&quot;&gt;LlamaParse&lt;&#x2F;a&gt; 这类产品，它会叠加 OCR、表格解析等更多步骤。&lt;&#x2F;p&gt;
&lt;p&gt;我们先看一个常见场景：你有一批图片，需要抽取文字；或者你想给图片生成可检索描述，用于全文搜索。&lt;&#x2F;p&gt;
&lt;p&gt;这类事情，正适合交给 VLM。&lt;&#x2F;p&gt;
&lt;p&gt;我示例里用的是 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;run-llama&#x2F;llama_index&quot;&gt;llama_index&lt;&#x2F;a&gt;，但核心思路和具体框架无关，迁移到你自己的客户端也很容易。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xian-shang-dai-ma&quot;&gt;先上代码&lt;a class=&quot;zola-anchor&quot; href=&quot;#xian-shang-dai-ma&quot; aria-label=&quot;Anchor link for: xian-shang-dai-ma&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;第一步是定义一个明确的提示词，让模型知道输出结构和覆盖范围。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;BASIC_PROMPT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        Please analyze this image comprehensively and provide the following information:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        1. General Overview:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Main subject matter and content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Overall composition and context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Key visual elements present&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        2. Text Content:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Transcribe any visible text accurately&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Include headers, labels, and captions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Note any important text formatting or emphasis&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        3. Data Visualization (if present):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - For tables:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Convert to markdown format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Preserve column headers and data relationships&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - For charts&#x2F;graphs:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Describe the type of visualization&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Explain key trends and patterns&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * List important data points and values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - For diagrams&#x2F;flowcharts:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Explain the structure and relationships&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Describe the flow or process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;             * Note any important symbols or annotations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        4. Additional Details:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Identify any branding or logos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Note color schemes if significant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;           - Describe any relevant metadata or context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        Please format the response clearly and maintain the original structure of any data.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;接下来是一个最小可运行的图片解析器：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; pathlib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; typing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; List&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; base64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; BytesIO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; PIL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;multi_modal_llms&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; MultiModalLLM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;multi_modal_llms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;generic_utils&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; ImageDocument&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SimpleImageParser&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; model&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; MultiModalLLM&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; model&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;prompt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; BASIC_PROMPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;A simple parser for extracting information from images using VLMs.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    Args:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        model (MultiModalLLM): The multi-modal language model to use for parsing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process_image&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; image_path&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Convert image to base64 encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Image&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;image_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        buffered&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; BytesIO&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;save&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;buffered&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; format&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PNG&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; base64&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;b64encode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;buffered&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getvalue&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;decode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;utf-8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; image_path&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Parse image content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image_data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;process_image&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;image_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image_doc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImageDocument&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            image_url&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;data:image&#x2F;jpeg;base64,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;image_data&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;acomplete&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            prompt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;prompt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            image_documents&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;image_doc&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;核心只有两步：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;把图片转成 base64。&lt;&#x2F;li&gt;
&lt;li&gt;作为 &lt;code&gt;image_documents&lt;&#x2F;code&gt; 传给 VLM。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;pao-yi-quan&quot;&gt;跑一圈&lt;a class=&quot;zola-anchor&quot; href=&quot;#pao-yi-quan&quot; aria-label=&quot;Anchor link for: pao-yi-quan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;下面是如何使用这个解析器：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; argparse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; pathlib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; llama_index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;multi_modal_llms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;openai&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; OpenAIMultiModal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; dotenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; load_dotenv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;load_dotenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    parser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; argparse&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ArgumentParser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Parse image content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_argument&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;image_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; help&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Path to the image file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    args&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parse_args&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    image_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Path&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;image_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; image_path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;exists&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Image file does not exist: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;image_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Initialize the VLM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; OpenAIMultiModal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MULTI_MODAL_LLM_MODEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;gpt-4o-mini&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        api_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MULTI_MODAL_LLM_API_KEY&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        api_base&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MULTI_MODAL_LLM_API_BASE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;api.openai.com&#x2F;v1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        max_new_tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MULTI_MODAL_LLM_MAX_TOKENS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;512&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        temperature&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MULTI_MODAL_LLM_TEMPERATURE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0.7&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        verbose&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MULTI_MODAL_LLM_VERBOSE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;False&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lower&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Create parser and parse image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    parser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; SimpleImageParser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;image_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;result&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    asyncio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这段代码会初始化 VLM，创建解析器，然后输出解析结果。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yun-xing-demo&quot;&gt;运行 Demo&lt;a class=&quot;zola-anchor&quot; href=&quot;#yun-xing-demo&quot; aria-label=&quot;Anchor link for: yun-xing-demo&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;完整示例代码在这里：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;psiace&#x2F;tree&#x2F;main&#x2F;demo&#x2F;vlm-parsing&quot;&gt;psiace&#x2F;demo&#x2F;vlm-parsing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;运行方式：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; basic.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;image_pat&lt;&#x2F;span&gt;&lt;span&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;示例图片是一张家庭网关界面截图（来源：&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Home_gateway_example.png&quot;&gt;Home gateway example&lt;&#x2F;a&gt;）：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;a-dead-simple-way-to-vlm-parsing&#x2F;example.png&quot; alt=&quot;Home gateway example&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;终端中的解析输出示例：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;a-dead-simple-way-to-vlm-parsing&#x2F;example-result.png&quot; alt=&quot;Home gateway example result&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-ru-he-kuo-zhan-zhe-ge-parser&quot;&gt;Bonus：如何扩展这个 Parser&lt;a class=&quot;zola-anchor&quot; href=&quot;#bonus-ru-he-kuo-zhan-zhe-ge-parser&quot; aria-label=&quot;Anchor link for: bonus-ru-he-kuo-zhan-zhe-ge-parser&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;下面是几个实用扩展方向：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;格式支持&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;code&gt;pdf2image&lt;&#x2F;code&gt; 处理 PDF。&lt;&#x2F;li&gt;
&lt;li&gt;用 &lt;code&gt;opencv-python&lt;&#x2F;code&gt; 抽取视频帧后再解析。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;输出形态&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;增加 JSON 输出：&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; parse_to_json&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; image_path&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;image_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Add your JSON transformation logic here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; json_result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;用 Jinja2 等模板工具生成更稳定的结构化文本。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;处理流水线&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;接入 Tesseract OCR 做文字前处理。&lt;&#x2F;li&gt;
&lt;li&gt;追加表格解析能力。&lt;&#x2F;li&gt;
&lt;li&gt;用 asyncio 做批处理。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;系统集成&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;接入 llama-index 做 RAG。&lt;&#x2F;li&gt;
&lt;li&gt;进一步封装成自动化工作流。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.llamaindex.ai&#x2F;&quot;&gt;llama-index Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;platform.openai.com&#x2F;&quot;&gt;OpenAI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;pillow.readthedocs.io&#x2F;&quot;&gt;PIL (Python Imaging Library)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;如果你只想快速验证“VLM 解析图片”是否有业务价值，这个极简方案足够开始。&lt;&#x2F;p&gt;
&lt;p&gt;先跑通最小闭环，再决定是否引入 OCR、表格结构化和更复杂的工程管线。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>别急着招 DevRel</title>
        <published>2024-03-08T00:00:00+00:00</published>
        <updated>2024-03-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/you-do-not-need-the-fucking-devrel/"/>
        <id>https://psiace.me/zh/posts/you-do-not-need-the-fucking-devrel/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/you-do-not-need-the-fucking-devrel/">&lt;h2 id=&quot;xian-bie-da-yan-gao-pai&quot;&gt;先别打广告牌&lt;a class=&quot;zola-anchor&quot; href=&quot;#xian-bie-da-yan-gao-pai&quot; aria-label=&quot;Anchor link for: xian-bie-da-yan-gao-pai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;很多团队把 DevRel 想成会写文案、会上台、能在社交媒体刷存在感的“吉祥物”。真要这样，不如直接买块广告牌，或者训练一只会说话的鹦鹉。DevRel 如果只是扩音器，迟早会在会议室里被当成背景音。&lt;&#x2F;p&gt;
&lt;p&gt;真正的 DevRel 是把产品和开发者社区连接起来的桥。从用户视角出发，帮团队把复杂的技术语言翻译成可理解、可落地的解决方案。他既要懂产品路线，也要摸得清社区脉搏；既能撸代码，也能写故事。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;san-jian-shi-xiang-qing-chu&quot;&gt;三件事想清楚&lt;a class=&quot;zola-anchor&quot; href=&quot;#san-jian-shi-xiang-qing-chu&quot; aria-label=&quot;Anchor link for: san-jian-shi-xiang-qing-chu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-quan-ze-zi-yuan-yao-pi-pei&quot;&gt;1. 权责资源要匹配&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-quan-ze-zi-yuan-yao-pi-pei&quot; aria-label=&quot;Anchor link for: 1-quan-ze-zi-yuan-yao-pi-pei&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;DevRel 需要参与决策，至少要能影响产品优先级和内容走向。如果每次都被挡在“等业务拍板”之外，他说的任何话都会显得苍白。给予授权，也意味着给足资源：真实数据、工程背景、核心成员的时间。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-xu-shi-yao-yi-zhi&quot;&gt;2. 叙事要一致&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-xu-shi-yao-yi-zhi&quot; aria-label=&quot;Anchor link for: 2-xu-shi-yao-yi-zhi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;让 DevRel 深入团队，把一线的设计取舍、踩坑记录都吸纳进来。只有这样，他们写出来的内容才像亲历者——不是新闻稿，也不是照本宣科的教程，而是能回答“为什么值得一试”这样的疑问。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-cheng-ken-bi-xing-shi-geng-nan&quot;&gt;3. 诚恳比形式更难&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-cheng-ken-bi-xing-shi-geng-nan&quot; aria-label=&quot;Anchor link for: 3-cheng-ken-bi-xing-shi-geng-nan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;社区对虚假的热情特别敏感。与其用堆砌的 buzzword，不如老老实实讲“我们是怎么解决 X 问题的”“我们做错过什么”。真诚是唯一的复利策略。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shen-me-shi-hou-zan-huan&quot;&gt;什么时候暂缓&lt;a class=&quot;zola-anchor&quot; href=&quot;#shen-me-shi-hou-zan-huan&quot; aria-label=&quot;Anchor link for: shen-me-shi-hou-zan-huan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;如果你还没准备好让 DevRel 拿到这些权力与资源，那就别急着招人。让创始人或者资深工程师先上阵：他们说话更有分量，也更容易获得团队信任。真正需要 DevRel 的时刻，是你想把这套叙事机制变成常态的时候。&lt;&#x2F;p&gt;
&lt;p&gt;DevRel 永远不是灵丹妙药。它是一种长期投入，需要团队，把“讲清楚”和“做得好”同时放在心上。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>A New Beginning, with Astro</title>
        <published>2023-09-25T00:00:00+00:00</published>
        <updated>2023-09-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/a-new-beginning/"/>
        <id>https://psiace.me/zh/posts/a-new-beginning/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/a-new-beginning/">&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;中文翻译正在整理，以下为英文原文。&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;hey-world&quot;&gt;Hey, World!&lt;a class=&quot;zola-anchor&quot; href=&quot;#hey-world&quot; aria-label=&quot;Anchor link for: hey-world&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I am delighted to announce the launch of my new blog, which is powered by &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;withastro&#x2F;&quot;&gt;Astro&lt;&#x2F;a&gt; and features the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chrismwilliams&#x2F;astro-theme-cactus&quot;&gt;Astro Cactus&lt;&#x2F;a&gt; theme.&lt;&#x2F;p&gt;
&lt;p&gt;In this fresh start, I have cleared all previous content to create a clean slate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-and-why-not&quot;&gt;Why and Why Not?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-and-why-not&quot; aria-label=&quot;Anchor link for: why-and-why-not&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The idea of starting anew had been on my mind for a few months, but it was my recent conversation with &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;xuanwo&quot;&gt;@Xuanwo&lt;&#x2F;a&gt; that finally pushed me to take action.&lt;&#x2F;p&gt;
&lt;p&gt;There are numerous reasons behind this decision:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I aspire to connect with a broader audience and have a more significant impact.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I aim to express my insights more effectively, moving beyond mere documentation of events.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;However, in reality, the decision was not driven by extensive contemplation; it was simply a matter of “Why not?”&lt;&#x2F;p&gt;
&lt;p&gt;Striving to do my best is sufficient.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I hope you’ll join me on this exciting journey!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Apache OpenDAL (Incubating) ：无痛数据访问新体验</title>
        <published>2023-07-05T00:00:00+00:00</published>
        <updated>2023-07-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/apache-opendal/"/>
        <id>https://psiace.me/zh/posts/apache-opendal/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/apache-opendal/">&lt;blockquote&gt;
&lt;p&gt;本文主要根据 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;note.xuanwo.io&#x2F;#&#x2F;page&#x2F;opendal%2F%E9%9D%A2%E5%90%91%20java%20%E7%94%A8%E6%88%B7%E7%9A%84%E4%BB%8B%E7%BB%8D&quot;&gt;面向 Java 用户的介绍 | @Xuanwo&lt;&#x2F;a&gt; 整理而来。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;如果你致力于构建云原生、跨云优先的应用程序及服务，或者希望支持可配置的存储后端以满足复杂的数据访问需要，再或者，你厌倦了在各种 SDK 中进行周旋并期待一个统一的抽象与开发体验，Apache OpenDAL (Incubating) 将会是你的绝佳拍档。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;zh&#x2F;posts&#x2F;apache-opendal&#x2F;apache-opendal.png&quot; alt=&quot;Apache OpenDAL (Incubating) Arch&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;opendal-shi-shen-me&quot;&gt;OpenDAL 是什么&lt;a class=&quot;zola-anchor&quot; href=&quot;#opendal-shi-shen-me&quot; aria-label=&quot;Anchor link for: opendal-shi-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;OpenDAL 是一个数据访问层，允许用户以统一的方式轻松有效地从各种存储服务中检索数据。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;数据访问层&lt;&#x2F;strong&gt; 意味着：OpenDAL 在数据读写流程中处于一个 &lt;strong&gt;承上启下&lt;&#x2F;strong&gt; 的关键位置，我们屏蔽了不同存储后端的实现细节，对外提供了一套统一的接口抽象。&lt;&#x2F;p&gt;
&lt;p&gt;接下来，让我们试着回答「OpenDAL 不是什么」，从另一个角度来解构 OpenDAL ：&lt;&#x2F;p&gt;
&lt;h3 id=&quot;opendal-bu-shi-dai-li-fu-wu&quot;&gt;OpenDAL 不是代理服务&lt;a class=&quot;zola-anchor&quot; href=&quot;#opendal-bu-shi-dai-li-fu-wu&quot; aria-label=&quot;Anchor link for: opendal-bu-shi-dai-li-fu-wu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;OpenDAL 以库的形式提供，而并非代理各种存储后端的服务或应用。&lt;&#x2F;p&gt;
&lt;p&gt;如果你希望将 OpenDAL 集成到现有项目中，需要通过 OpenDAL 支持的语言来调用 OpenDAL 的接口直接访问存储服务。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;opendal-bu-shi-sdk-ju-he-qi&quot;&gt;OpenDAL 不是 SDK 聚合器&lt;a class=&quot;zola-anchor&quot; href=&quot;#opendal-bu-shi-sdk-ju-he-qi&quot; aria-label=&quot;Anchor link for: opendal-bu-shi-sdk-ju-he-qi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;尽管 OpenDAL 取代了各类 SDK 在应用架构中的生态位，但 OpenDAL 并不是以 SDK 聚合器的形式进行实现。&lt;&#x2F;p&gt;
&lt;p&gt;换句话说，OpenDAL 不是简单的调用各个存储服务的 SDK，我们基于统一的 Rust 核心开发自行实现了各个存储服务的对接，确保抹平服务之间的细节差异。&lt;&#x2F;p&gt;
&lt;p&gt;以 S3 为例，OpenDAL 手动构造 HTTP Request 并解析 HTTP Response，保证所有行为都符合 API 规范并且完全纳入 OpenDAL 的掌控之中。得益于 OpenDAL 以原生形式接管数据访问流程，我们可以轻松为各种存储后端实现统一的重试和日志机制，并确保行为的一致性。&lt;&#x2F;p&gt;
&lt;p&gt;而对于 S3 的兼容服务，由于原生存储服务的限制和 API 实现的差异，兼容程度和行为细节都可能会与 S3 存在差异，比如 OSS 对 Range 的默认实现就需要设置一个独立的 Header 才能确保行为一致。OpenDAL 除了对接原生存储服务之外，也会对兼容性服务进行针对性处理，以确保用户的数据访问体验。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;opendal-de-you-shi&quot;&gt;OpenDAL 的优势&lt;a class=&quot;zola-anchor&quot; href=&quot;#opendal-de-you-shi&quot; aria-label=&quot;Anchor link for: opendal-de-you-shi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;OpenDAL 并不是唯一一个致力于提供数据访问抽象的项目，但相比于其他同类项目，OpenDAL 具有如下优势：&lt;&#x2F;p&gt;
&lt;h3 id=&quot;feng-fu-de-fu-wu-zhi-chi&quot;&gt;丰富的服务支持&lt;a class=&quot;zola-anchor&quot; href=&quot;#feng-fu-de-fu-wu-zhi-chi&quot; aria-label=&quot;Anchor link for: feng-fu-de-fu-wu-zhi-chi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;OpenDAL 支持数十种存储服务，覆盖场景全面，支持按需选用：
&lt;ul&gt;
&lt;li&gt;标准存储协议：FTP，HTTP，SFTP，WebDAV 等&lt;&#x2F;li&gt;
&lt;li&gt;对象存储服务：azblob，gcs，obs，oss，s3 等&lt;&#x2F;li&gt;
&lt;li&gt;文件存储服务：fs, azdfs，hdfs，webhdfs, ipfs 等&lt;&#x2F;li&gt;
&lt;li&gt;消费级存储服务（网盘）：Google Drive，OneDrive，Dropbox 等&lt;&#x2F;li&gt;
&lt;li&gt;Key Value 存储服务：Memory，Redis，Rocksdb 等&lt;&#x2F;li&gt;
&lt;li&gt;缓存服务：Ghac，Memcached 等&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;wan-zheng-de-kua-yu-yan-bang-ding&quot;&gt;完整的跨语言绑定&lt;a class=&quot;zola-anchor&quot; href=&quot;#wan-zheng-de-kua-yu-yan-bang-ding&quot; aria-label=&quot;Anchor link for: wan-zheng-de-kua-yu-yan-bang-ding&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;以 Rust 为核心，OpenDAL 现在提供 Python&#x2F;Node.js&#x2F;Java&#x2F;C 等多个语言的绑定支持，同时也在积极开发其他语言的绑定。&lt;&#x2F;li&gt;
&lt;li&gt;跨语言绑定不光为其他语言提供统一的存储访问抽象，设计和实现上也尽可能遵循各种语言约定俗成的命名风格和开发习惯，为快速上手使用铺平道路。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;qiang-da-de-zhong-jian-jian-zhi-chi&quot;&gt;强大的中间件支持&lt;a class=&quot;zola-anchor&quot; href=&quot;#qiang-da-de-zhong-jian-jian-zhi-chi&quot; aria-label=&quot;Anchor link for: qiang-da-de-zhong-jian-jian-zhi-chi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;OpenDAL 提供原生的中间件能力，主要包括
&lt;ul&gt;
&lt;li&gt;错误重试：OpenDAL 支持细粒度的错误重试能力，除了常见的请求重试之外，支持从断点续传，不需要重新读取整个文件。&lt;&#x2F;li&gt;
&lt;li&gt;可观测性支持：OpenDAL 对所有操作都实现了 logging，tracing，metrics 支持，开启中间件就能直接获得对存储的可观测性能力。&lt;&#x2F;li&gt;
&lt;li&gt;此外还有并发控制，流控，模糊测试等。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;jian-dan-yi-yong&quot;&gt;简单易用&lt;a class=&quot;zola-anchor&quot; href=&quot;#jian-dan-yi-yong&quot; aria-label=&quot;Anchor link for: jian-dan-yi-yong&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OpenDAL 的 API 经过良好的设计并在实际使用中不断打磨，文档覆盖全面，方便快速上手。下面是一个使用 Python 绑定访问 HDFS 的例子：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; opendal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; opendal&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Operator&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hdfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; name_node&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hdfs:&#x2F;&#x2F;192.16.8.10.103&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;op&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;path&#x2F;to&#x2F;file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;opendal-de-shi-yong-chang-jing&quot;&gt;OpenDAL 的使用场景&lt;a class=&quot;zola-anchor&quot; href=&quot;#opendal-de-shi-yong-chang-jing&quot; aria-label=&quot;Anchor link for: opendal-de-shi-yong-chang-jing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;目前 OpenDAL 被广泛应用于有云原生需要的各种场景，包括但不限于数据库、数据管道和缓存等，主要用户案例包括：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Databend：OLAP 云原生数据仓库，使用 OpenDAL 来读写持久化数据（s3，azblob，gcs，hdfs 等）和缓存数据（fs，redis，rocksdb，moka 等）&lt;&#x2F;li&gt;
&lt;li&gt;GreptimeDB：云原生时序数据库，使用 OpenDAL 来读写持久化数据（s3，azblob 等）&lt;&#x2F;li&gt;
&lt;li&gt;RisingWave：用于流处理的分布式 SQL 数据库，使用 OpenDAL 来读写持久化数据 （s3，azblob，hdfs 等）&lt;&#x2F;li&gt;
&lt;li&gt;Vector: 可观察性数据管道，使用 OpenDAL 来写入持久化数据（目前以 hdfs 的使用为主）&lt;&#x2F;li&gt;
&lt;li&gt;Sccache：支持云存储的类 ccache 工具，主要用于缓存 rust&#x2F;cpp 语言的编译产物，使用 OpenDAL 来读写缓存数据（s3 和 ghac 等）&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;opendal-de-wei-lai-gui-hua&quot;&gt;OpenDAL 的未来规划&lt;a class=&quot;zola-anchor&quot; href=&quot;#opendal-de-wei-lai-gui-hua&quot; aria-label=&quot;Anchor link for: opendal-de-wei-lai-gui-hua&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;除了进一步满足云原生数据访问需求之外，OpenDAL 将会持续拓展用户场景，积极探索在数据科学、移动应用等方面的使用。同时，OpenDAL 也会持续打磨现有的实现和绑定，为用户提供更好的集成体验。&lt;&#x2F;p&gt;
&lt;p&gt;OpenDAL 还将会探索如何改善用户在数据管理和服务集成的工作流：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;打磨 oli 命令行工具，帮助用户无痛管理数据。&lt;&#x2F;li&gt;
&lt;li&gt;实现 oay 代理服务，为用户提供高质量的兼容 API 。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;另外，由于 OpenDAL 目前是一个跨多语言的项目，我们还计划撰写一系列入门教程，帮助大家从 0 开始，在学习语言的同时掌握 OpenDAL 的使用技巧。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zhi-xie&quot;&gt;致谢&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhi-xie&quot; aria-label=&quot;Anchor link for: zhi-xie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;opendal.apache.org&#x2F;&quot;&gt;Apache OpenDAL(Incubating) | Website&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apache&#x2F;incubator-opendal&quot;&gt;apache&#x2F;incubator-opendal | GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;note.xuanwo.io&#x2F;#&#x2F;page&#x2F;opendal%2F%E9%9D%A2%E5%90%91%20java%20%E7%94%A8%E6%88%B7%E7%9A%84%E4%BB%8B%E7%BB%8D&quot;&gt;面向 Java 用户的介绍 | @Xuanwo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>我永远讨厌 Python Fibonacci</title>
        <published>2022-09-30T00:00:00+00:00</published>
        <updated>2022-09-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/master-python-fibonacci/"/>
        <id>https://psiace.me/zh/posts/master-python-fibonacci/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/master-python-fibonacci/">&lt;p&gt;这里是 PsiACE，好久没和大家见面做公开的汇报了。&lt;&#x2F;p&gt;
&lt;p&gt;目前的话人在澳门，总体上还不错，最近一段时间做饭水平急速提高，并且不得不捡起好久没写过的 Python 。&lt;&#x2F;p&gt;
&lt;p&gt;「回」字大概有四种写法，Python Fibonacci 则更多，让我们一起来看一下吧。&lt;&#x2F;p&gt;
&lt;p&gt;这篇文章主要从两个方面来介绍，前半部分主要关注 Fibonacci 的不同算法实现，后半部分则会关注如何使用 C&#x2F;C++ 等来拓展 Fibonacci 。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fibonacci-de-bu-tong-suan-fa-shi-xian&quot;&gt;Fibonacci 的不同算法实现&lt;a class=&quot;zola-anchor&quot; href=&quot;#fibonacci-de-bu-tong-suan-fa-shi-xian&quot; aria-label=&quot;Anchor link for: fibonacci-de-bu-tong-suan-fa-shi-xian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;link.zhihu.com&#x2F;?target=https%3A&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fibonacci%23Fibonacci_sequence&quot;&gt;斐波那契数列&lt;&#x2F;a&gt;（Fibonacci sequence）是以意大利数学家 &lt;code&gt;列昂纳多·斐波那契&lt;&#x2F;code&gt; 的名字命名的数列。&lt;&#x2F;p&gt;
&lt;p&gt;斐波那契数列在计算机里面有很多用途，例如斐波那契查找（二分查找的一种改进），斐波那契堆等。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;di-gui&quot;&gt;递归&lt;a class=&quot;zola-anchor&quot; href=&quot;#di-gui&quot; aria-label=&quot;Anchor link for: di-gui&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;根据 Fibonacci 定义，可以轻松写出一个递归算法：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;ji-yi-hua&quot;&gt;记忆化&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-yi-hua&quot; aria-label=&quot;Anchor link for: ji-yi-hua&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;一个简单的优化思路是采用记忆化，因为是一个递归的计算方法，保存之前的结果会比较有利。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    @&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lru_cache&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;进一步优化的话可以选择递推形式的算法，比如记忆全部的前置结果。大概是线性级别。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;但是事实上，我们不需要记录那么多中间结果，仅需要保留前两个值即可：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;shu-xue&quot;&gt;数学&lt;a class=&quot;zola-anchor&quot; href=&quot;#shu-xue&quot; aria-label=&quot;Anchor link for: shu-xue&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;更进一步地，如果将其递推公式整理为通项公式，可以得到下面的算法：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sqrt5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;**&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fibN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; sqrt5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; sqrt5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; round&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fibN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; sqrt5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这种方法非常快，但是要考虑 &lt;code&gt;int&lt;&#x2F;code&gt; 溢出，仅仅对小数据量有效。(常数级别)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ju-zhen-cheng-fa&quot;&gt;矩阵乘法&lt;a class=&quot;zola-anchor&quot; href=&quot;#ju-zhen-cheng-fa&quot; aria-label=&quot;Anchor link for: ju-zhen-cheng-fa&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;那么还有没有其他方法呢？比如矩阵乘法，大概是对数级别：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; matrix_pow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;q&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; res&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; matrix_pow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ret&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ret&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; matrix_multiply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ret&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; matrix_multiply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; ret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; matrix_multiply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; j&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            c&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;j&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;j&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;j&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;shi-yong-c-c-tuo-zhan-fibonacci&quot;&gt;使用 C &#x2F; C++ 拓展 Fibonacci&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-yong-c-c-tuo-zhan-fibonacci&quot; aria-label=&quot;Anchor link for: shi-yong-c-c-tuo-zhan-fibonacci&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;一个非常典型的观点是，Python是一种适合初学者、开发快速的语言，但没有很大的性能优势。甚至在 PyCon 上，&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gvanrossum&quot;&gt;@gvanrossum&lt;&#x2F;a&gt; 也说，必须让 Python 语言的速度水平提高 2 倍，借此与 C++ 等高性能编程语言正面对抗。&lt;&#x2F;p&gt;
&lt;p&gt;显然，存在一些已知的改善性能的办法，并且在主流的数据科学包以及 web framework 包中得到了应用。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;降低时间复杂度。不管是什么原因导致程序变慢，只要可以，直接选择一个更快的算法。&lt;&#x2F;li&gt;
&lt;li&gt;并行化代码。如果存在多个闲置的处理器，可以尝试将任务分割成可以同时处理的子任务。&lt;&#x2F;li&gt;
&lt;li&gt;使用更快的语言重写代码中较慢的部分。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;使用 C &#x2F; C++ 拓展 Python 的显著好处：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;一方面，得益于 Python 的简单易用，可以提供一套清晰和简化的接口，降低下游开发人员的精力投入，加速应用的开发。&lt;&#x2F;li&gt;
&lt;li&gt;另一方面，得益于其他语言的性能和编译优化，可以显著改善程序性能。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;ru-he-shi-yong-c-c-tuo-zhan-python&quot;&gt;如何使用 C &#x2F; C++ 拓展 Python&lt;a class=&quot;zola-anchor&quot; href=&quot;#ru-he-shi-yong-c-c-tuo-zhan-python&quot; aria-label=&quot;Anchor link for: ru-he-shi-yong-c-c-tuo-zhan-python&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;使用 Python 的 ctypes 模块&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;ctypes 是 Python 官方提供的 FFI 模块，适用于动态链接库。调用时的处理复杂度基本转移到 Python，无法很好利用 Python 中的一些能力。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;使用 Python CAPI&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;CPython 为 C &#x2F; C++ 提供了一套 API ，可以使用 Python 原生的一些能力完成 C &#x2F; C++ 与 Python 的交互。但是在调试方面依然需要采用 C &#x2F; C++ 工具链，而且因为调用了 Python 底层的 CAPI，有时候需要手动去操控 Python 的引用计数来完成 Python 的 GC 机制。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;使用 Cython&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Cython 是一种面向 Python 和 Cython 语言的一个优化过的静态编译器。Cython 会将 Python 和 Cython 翻译成 C&#x2F;C++，然后编译成一个静态链接库供 Python 使用。&lt;&#x2F;p&gt;
&lt;p&gt;Cython 除了提供 CAPI 之外，还提供了大部分的封装好的模块和函数，而对于 Unicode 或者 Python 的异常机制，Cython 会帮助你自动翻译成 C&#x2F;C++ 。由于 Cython 做的是代码转译，粒度相对较粗，所以无法做一些细粒度优化。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;使用 SWIG&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;SWIG 并不只是提供 C&#x2F;C++ 对 Python 的拓展，还提供对 Java、Perl 等其他语言的拓展支持，就是写一个拓展可以在多处使用。&lt;&#x2F;p&gt;
&lt;p&gt;使用 SWIG 的最大优点是可以使同一套代码拓展多种语言，但是对于某些特性，依然还是要针对 Python 在配置文件中显式地写出一些 Python CAPI 相关的调用，在调试方面，也是只能使用 C&#x2F;C++ 配套的调试工具。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shi-li-yu-xing-neng&quot;&gt;示例与性能&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-li-yu-xing-neng&quot; aria-label=&quot;Anchor link for: shi-li-yu-xing-neng&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;让我们继续回到斐波那契数列的例子，之前的内容中，我们曾经讨论过它的算法和一些优化。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;递归&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;接下来的内容中，将会使用递归算法作为基准来展现不同的优化，除了并行部分之外，我们将会使用 &lt;code&gt;fib(47)&lt;&#x2F;code&gt; 进行性能评估。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;并行&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;通过使用 multiprocessing 进行池化，我们得以同时执行多个计算任务，这使得在一些特定场景下具有性能优势。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; multiprocessing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; multiprocessing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; mp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;function for calculate fibannaci number&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; parallel_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; paralleing throught pool.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; multiprocessing&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Pool&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cpu_count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; One-time parallel calculation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;parallel_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;30&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Recursive calculation one by one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;30&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;31&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;33&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;简单看一下性能：&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Language&lt;&#x2F;th&gt;&lt;th&gt;Time, s&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Python Recursive&lt;&#x2F;td&gt;&lt;td&gt;1.377&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Python Parallel&lt;&#x2F;td&gt;&lt;td&gt;0.669&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;快速算法 - 记忆化&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;递归算法相当朴素，也非常的慢，更加快速的算法我们在之前有过讨论，这里给出一个缓存最近结果的一个简单算法。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; functools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; lru_cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lru_cache&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;PyPy - JIT&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;PyPy 是 CPython 的替代品。它是使用与之共同开发的 RPython 语言构建的。使用它而不是 CPython 的主要原因是速度: 它通常运行得更快。&lt;&#x2F;p&gt;
&lt;p&gt;PyPy 实现了 Python 2.7.18和3.7.10。它支持所有的核心语言，通过 Python 2.7 测试套件和几乎所有的 3.7 测试套件。它支持大多数常用的 Python 标准库模块。&lt;&#x2F;p&gt;
&lt;p&gt;PyPy 快速的秘密在于使用了 JIT 技术，以下是 JIT 编译为提高性能而采取的步骤：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;标识代码中最常用的组件，例如循环中的函数。&lt;&#x2F;li&gt;
&lt;li&gt;在运行时将这些组件转换为机器码。&lt;&#x2F;li&gt;
&lt;li&gt;优化生成的机器码。&lt;&#x2F;li&gt;
&lt;li&gt;用优化的机器码版本替换以前的实现。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;很高兴，我们的递归版本可以自然地利用 PyPy 进行编译以获得性能上的提升。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;C&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;由于要展示 C&#x2F;C++ 拓展的能力，我们也提供 C 语言版本做一个比较。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;include&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdio.h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;include&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdint.h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%llu&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;ctypes&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;同样的，我们仿照之前的 C 语言版本，编写对应的共享库。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;file fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;share.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;include&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdint.h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;file fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;share.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;include&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdint.h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;接下来，让我们使用 &lt;code&gt;ctypes&lt;&#x2F;code&gt; 来调用它。主要的部分都很简单，需要注意的是，&lt;code&gt;uint64_t&lt;&#x2F;code&gt; 对应的是 &lt;code&gt;c_ulonglong&lt;&#x2F;code&gt; ，我们需要指定参数类型和结果类型。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;ctypes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; ctypes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; CDLL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c_ulonglong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ctypes_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use ctypes to load the library&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; CDLL&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;ctypes_fib.so&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We need to give the argument and return types explicitly&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;c_fib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;argtypes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;c_ulonglong&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;c_fib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;restype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; c_ulonglong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; lib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ctypes_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;接着，我们需要编译共享库，并像运行其他 Python 程序那样执行。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; gcc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;O3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;fPIC&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;shared&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;std=c99&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  fib-share.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ctypes_fib.so&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-ctypes.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;CAPI&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;相比其他几种方法，CAPI 会显得复杂一些，所以，我大概会推荐你去阅读 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;llllllllll.github.io&#x2F;c-extension-tutorial&#x2F;&quot;&gt;How to Write and Debug C Extension Modules&lt;&#x2F;a&gt; 。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;include&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Python.h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; long&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cfib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; long&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cfib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cfib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PyDoc_STRVAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib_doc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;compute the nth Fibonacci number&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span&gt; PyObject&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pyfib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;PyObject&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; PyObject&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; as_unsigned_long &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PyLong_AsUnsignedLong&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    PyObject&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; result &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PyLong_FromUnsignedLong&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cfib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;as_unsigned_long&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; result&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PyMethodDef methods&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;PyCFunction&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; pyfib&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; METH_O&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fib_doc&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PyDoc_STRVAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib_module_doc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;provides a Fibonacci function&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PyModuleDef fib_module &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    PyModuleDef_HEAD_INIT&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fib_module_doc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    methods&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    NULL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PyMODINIT_FUNC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PyInit_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PyModule_Create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;fib_module&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;所有的函数返回类型都是 PyObject 的指针，参数类型是是 PyObject 的两个指针，前者对应 Python 类里方法的 self，后者对应串里的参数。&lt;&#x2F;p&gt;
&lt;p&gt;完成我们需要的函数之后，需要显示地声明模块暴露在外的方法，接受参数的类型以及文档。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; .&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;__all__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;构建 CPython 扩展模块的最常见方法是使用 setuptools 和 setup.py 文件。我们从一个普通的 setuptools setup.py 文件开始：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; setuptools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; setup&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; find_packages&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Extension&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fibcapi&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0.1.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    packages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;find_packages&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    classifiers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Development Status :: 3 - Alpha&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;License :: OSI Approved :: GNU General Public License v2 (GPLv2)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Natural Language :: English&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Programming Language :: Python :: 3 :: Only&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Programming Language :: Python :: Implementation :: CPython&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    ext_modules&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        Extension&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fib.fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fib&#x2F;fib.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;从根目录运行以下命令：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; setup.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build_ext&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-inplace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;最后，像写一个普通的Python程序一样调用它。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Cython&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;如果使用 Cython, 代码可以更改为：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cdef&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;long&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;需要使用下面的命令来编译：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cython&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-embed&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib.pyx.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib.pyx&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; gcc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;O3&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python3-config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-embed&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-cflags&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib.pyx.c&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;python3-config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-embed&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-ldflags&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;SWIG&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;首先，让我们复用之前 ctypes 一节中的 &lt;code&gt;fib-share.h&lt;&#x2F;code&gt; 和 &lt;code&gt;fib-share.c&lt;&#x2F;code&gt; 。&lt;&#x2F;p&gt;
&lt;p&gt;接着，定义对应的 SWIG 接口文件，为了使用 &lt;code&gt;uint64_t&lt;&#x2F;code&gt; ，我们不得不引入 &lt;code&gt;stdint.i&lt;&#x2F;code&gt; 。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;file fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;swig.i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;include &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stdint.i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;module fibswig&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;uint64_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;然后，我们需要编写一点 python 代码来调用 swig 共享库&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; fibswig&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fibswig&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;c_fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;接着，我们需要编译共享库，并像运行其他 Python 程序那样执行。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; swig&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-swig.i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; gcc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;fPIC&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-share.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-swig_wrap.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;I&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;usr&#x2F;include&#x2F;python3.10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ld&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;fPIC&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;shared&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-share.o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-swig_wrap.o&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; _fibswig.so&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fib-swig.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;性能汇总&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Lang&lt;&#x2F;th&gt;&lt;th&gt;Time, s&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Python3&lt;&#x2F;td&gt;&lt;td&gt;530.974&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Python3 (PyPy)&lt;&#x2F;td&gt;&lt;td&gt;39.398&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Python - Cache&lt;&#x2F;td&gt;&lt;td&gt;0.013&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;&#x2F;td&gt;&lt;td&gt;3.336&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;ctypes&lt;&#x2F;td&gt;&lt;td&gt;3.245&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CAPI&lt;&#x2F;td&gt;&lt;td&gt;3.300&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Cython&lt;&#x2F;td&gt;&lt;td&gt;4.487&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;SWIG&lt;&#x2F;td&gt;&lt;td&gt;13.368&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;zhi-xie&quot;&gt;致谢&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhi-xie&quot; aria-label=&quot;Anchor link for: zhi-xie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;leetcode.cn&#x2F;problems&#x2F;fibonacci-number&#x2F;&quot;&gt;509. 斐波那契数 - 力扣&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;extending&#x2F;extending.html&quot;&gt;Extending Python with C or C++&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;ctypes.html&quot;&gt;&lt;code&gt;ctypes&lt;&#x2F;code&gt; — A foreign function library for Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;realpython.com&#x2F;build-python-c-extension-module&#x2F;&quot;&gt;Building a Python C Extension Module&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;towardsdatascience.com&#x2F;write-your-own-c-extension-to-speed-up-python-x100-626bb9d166e7&quot;&gt;Write Your Own C-extension to Speed Up Python by 100x&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;delta-force&#x2F;extending-python-with-c-f4e9656fbf5d&quot;&gt;Extending Python with C&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;web.mit.edu&#x2F;people&#x2F;amliu&#x2F;vrut&#x2F;python&#x2F;ext&#x2F;intro.html&quot;&gt;Extending Python with C or C++ code&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.zhihu.com&#x2F;question&#x2F;23003213&quot;&gt;如何实现 C&#x2F;C++ 与 Python 的通信？&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;zhuanlan.zhihu.com&#x2F;p&#x2F;363434563&quot;&gt;Python 和 C&#x2F;C++ 拓展程序的性能优化&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;blog.brickgao.com&#x2F;2015&#x2F;08&#x2F;14&#x2F;extending-Python-with-C-and-C-Plus-Plus&#x2F;&quot;&gt;用 C&#x2F;C++ 拓展 Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>谈谈过去的一年</title>
        <published>2022-07-05T00:00:00+00:00</published>
        <updated>2022-07-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/talk-about-the-past-year/"/>
        <id>https://psiace.me/zh/posts/talk-about-the-past-year/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/talk-about-the-past-year/">&lt;p&gt;这里是 PsiACE，本来应该继续写迭代记录之「十日谈」的，但距离上一期已经又过去月余，就不太提得起兴趣。&lt;&#x2F;p&gt;
&lt;p&gt;今天就做个特别篇好啦，毕竟 22 年已经过半，在职业道路上也慢慢前进了一年，算是一个比较有意思的时间节点。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zhi-de-kai-xin-de-xiao-li-cheng-bei&quot;&gt;值得开心的小里程碑&lt;a class=&quot;zola-anchor&quot; href=&quot;#zhi-de-kai-xin-de-xiao-li-cheng-bei&quot; aria-label=&quot;Anchor link for: zhi-de-kai-xin-de-xiao-li-cheng-bei&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;个人向&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;减少碳水 + 增加散步 = 减重计划，颇有成效，瘦掉 7 、8 斤，感觉回到标准身材指日可待。&lt;&#x2F;li&gt;
&lt;li&gt;逐步开始有效的日程&#x2F;时间管理，感觉比较关键的步骤是记录而非追踪。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;开源向&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psiace&#x2F;&quot;&gt;@PsiACE&lt;&#x2F;a&gt; 累计 233 fo，&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;repsiace&quot;&gt;推上&lt;&#x2F;a&gt; 也有 300+ 。&lt;&#x2F;li&gt;
&lt;li&gt;在 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;databend&#x2F;&quot;&gt;datafuselabs&#x2F;databend&lt;&#x2F;a&gt; 上的提交数量突破 400 。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dataslime&#x2F;ritelinked&quot;&gt;dataslime&#x2F;ritelinked&lt;&#x2F;a&gt; 达成 10w 下载量，目前也有一些其他朋友在用。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;databend-internals&quot;&gt;PsiACE&#x2F;databend-internals&lt;&#x2F;a&gt; 最近好像被翻了牌子，目前有 160 star 。&lt;&#x2F;li&gt;
&lt;li&gt;开始在 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;casbin&quot;&gt;@casbin&lt;&#x2F;a&gt; 的 GSoC 活动担任导师，也推动 Databend 参与 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;summer-ospp.ac.cn&#x2F;&quot;&gt;OSPP&lt;&#x2F;a&gt; 。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;qing-nian-ren-de-xiao-xiao-fan-nao&quot;&gt;青年人的小小烦恼&lt;a class=&quot;zola-anchor&quot; href=&quot;#qing-nian-ren-de-xiao-xiao-fan-nao&quot; aria-label=&quot;Anchor link for: qing-nian-ren-de-xiao-xiao-fan-nao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;生活向&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;可能关家里太久，整个人不太活跃，很多有趣的想法都搁置了下来。&lt;&#x2F;li&gt;
&lt;li&gt;好想女朋友，好想女朋友，好想女朋友。（疫情什么的，实在太讨厌了）&lt;&#x2F;li&gt;
&lt;li&gt;睡眠质量还蛮好，但是总觉得睡不太够，失眠也比较严重。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;职业向&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;有几个月状态比较低落，虽然期间也搞出了 databend-perf 、databend-internals ，但确实不那么满意。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;perf.databend.rs&#x2F;&quot;&gt;databend-perf&lt;&#x2F;a&gt; 上线几个月，跑出不少 bug ，最近又在罢工。&lt;&#x2F;li&gt;
&lt;li&gt;前段时间 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BohuTANG&#x2F;&quot;&gt;@BohuTANG&lt;&#x2F;a&gt; 问到入职一年来的成长，并提及 Owner 意识。感觉自己应该多向 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Xuanwo&quot;&gt;@Xuanwo&lt;&#x2F;a&gt; 、&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flaneur2020&quot;&gt;@flaneur2020&lt;&#x2F;a&gt; 学习。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;hou-xu-de-yi-xie-ji-hua&quot;&gt;后续的一些计划&lt;a class=&quot;zola-anchor&quot; href=&quot;#hou-xu-de-yi-xie-ji-hua&quot; aria-label=&quot;Anchor link for: hou-xu-de-yi-xie-ji-hua&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;学习向&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;把英语和数学往起捡一下。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;工作向&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;试图对 databend-query 进行一轮 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;databend&#x2F;issues&#x2F;6180&quot;&gt;拆分&lt;&#x2F;a&gt; &#x2F; &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;databend&#x2F;issues&#x2F;5001&quot;&gt;测试重构&lt;&#x2F;a&gt; 。&lt;&#x2F;li&gt;
&lt;li&gt;继续打磨 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PsiACE&#x2F;databend-internals&quot;&gt;PsiACE&#x2F;databend-internals&lt;&#x2F;a&gt; ，及时增补新内容，争取正式并入 datafuselabs 进行维护。&lt;&#x2F;li&gt;
&lt;li&gt;持续探索开发者运营方面的一些好的形式和策略。&lt;&#x2F;li&gt;
&lt;li&gt;提高自己的技术水平和投入，争取能够落地一些 looks great 的想法。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;暂时先这样，或许，下个迭代见！&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>逃离编译时的内存溢出</title>
        <published>2022-02-23T00:00:00+00:00</published>
        <updated>2022-02-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/escape-oom-at-build-time/"/>
        <id>https://psiace.me/zh/posts/escape-oom-at-build-time/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/escape-oom-at-build-time/">&lt;p&gt;今天写周报的时候提到了这个话题，顺便就记录一下如何逃离 Rust 编译时的内存溢出。&lt;&#x2F;p&gt;
&lt;p&gt;内存溢出，也就是 Out of Memory（OOM），从字面就能看出来，是要用到的内存大于系统能提供的最大内存而引起的故障。&lt;&#x2F;p&gt;
&lt;p&gt;Databend 中的 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;databend&#x2F;tree&#x2F;main&#x2F;common&#x2F;functions&quot;&gt;common&#x2F;functions&lt;&#x2F;a&gt; 模块为用户提供常用 SQL 函数支持，体量本身就很大，并且在新一轮的改造中引入了很多需要 codegen 的环节。于是，我们又遇到了老朋友（CI 又挂了）：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;(signal: 9, SIGKILL: kill) warning: build failed, waiting for other jobs to finish... error: build failed.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;使用 &lt;code&gt;-Z time-passes&lt;&#x2F;code&gt; 这个 RUSTFLAGS 可以帮助观测一些指标，就很容易判断出来是 OOM 。而且之前的一些反馈和报错也能够佐证是发生在链接阶段。&lt;&#x2F;p&gt;
&lt;p&gt;那么，该怎么办呢？最简单的办法是「大就是好，多就是美」，加钱上更多内存，或者分配更大的 Swap 空间（没错，就像我之前有一个 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;psiace.me&#x2F;btrfs-32gib-swapfile-on-fedora&#x2F;&quot;&gt;暴力的 32GiB Swapfile&lt;&#x2F;a&gt;）。这当然可以一劳永逸，但：前者无疑会消耗钱包，目前内存条还是一个很大的负担，而且对于笔记本之类，更换的余地也有限；后者虽然守住了钱包，但是白白占去那么大一块空间，而且说不得会影响一些性能。&lt;&#x2F;p&gt;
&lt;p&gt;让我们一起看一下，有没有什么过渡的选项可以缓解这一尴尬的局面，进行一些有限的平衡。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;geng-kuai-geng-gao-geng-qiang-de-mold&quot;&gt;「更快、更高、更强」的 mold&lt;a class=&quot;zola-anchor&quot; href=&quot;#geng-kuai-geng-gao-geng-qiang-de-mold&quot; aria-label=&quot;Anchor link for: geng-kuai-geng-gao-geng-qiang-de-mold&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;是的，既然是链接器的问题，那么最简单的办法就是换一个。Rust 默认的 linker 选项设定的是 &lt;code&gt;cc&lt;&#x2F;code&gt;，这意味着会利用到 gnu 工具链中的 &lt;code&gt;ld&lt;&#x2F;code&gt;，尽管 gnu 在自由软件领域有着卓越的贡献，但以目前的经验而言，这并不是一个好的现代选择。它的一个有力的竞争者是 llvm 工具链中的 lld 。&lt;&#x2F;p&gt;
&lt;p&gt;而到了今天，我们还有另外一个更加优越的候选人 —— 「&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rui314&#x2F;mold&quot;&gt;mold&lt;&#x2F;a&gt;」，在实际使用中，表现出与 lld 相当、甚至超过的性能，并且使用更少的内存。&lt;&#x2F;p&gt;
&lt;p&gt;该如何与 Rust 工具链结合使用呢，有这么两种方法：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;mold -run&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;采用这种模式，可以帮助我们快速体验 mold ，这得益于内置的拦截机制，可以将指向 ld ，ld.lld ，ld.gold 的命令转向 mold 自身。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; With Make.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mold&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;run&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; make&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;make-options-if-an&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Or with Cargo.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mold&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;run&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cargo-options-if-an&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;编辑 .cargo&#x2F;config.toml&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;添加下面的内容即可，如果是按 &lt;code&gt;sudo make install&lt;&#x2F;code&gt; 安装的，&lt;code&gt;path&#x2F;to&#x2F;mold&lt;&#x2F;code&gt; 大概率会指向 &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;mold&lt;&#x2F;code&gt; 。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;x86_64-unknown-linux-gnu&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;linker&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;clang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;rustflags&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-C&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;link-arg=-fuse-ld=&#x2F;path&#x2F;to&#x2F;mold&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;chuan-xin-de-fu-hao-xiu-shi-fang-an&quot;&gt;船新的符号修饰方案&lt;a class=&quot;zola-anchor&quot; href=&quot;#chuan-xin-de-fu-hao-xiu-shi-fang-an&quot; aria-label=&quot;Anchor link for: chuan-xin-de-fu-hao-xiu-shi-fang-an&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;符号修饰，或者说 symbol mangling ，是现代计算机程序设计语言的编译器用于解决由于程序实体的名字必须唯一而导致的问题的一种技术。&lt;&#x2F;p&gt;
&lt;p&gt;Rust 目前有一个自己设计符号修饰方案，&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2603&quot;&gt;rust-lang&#x2F;rfcs#2603&lt;&#x2F;a&gt;，通过启用这一方案，在有重复组件的情况下，会生成更小的符号。&lt;&#x2F;p&gt;
&lt;p&gt;要想启用这一特性，同样有两种方法：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;RUSTFLAGS&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;在目前最新的 Rust nightly 中，可以使用 &lt;code&gt;-C symbol-manging-version=v0&lt;&#x2F;code&gt; 这个 RUSTFLAG ，相对旧一点的版本可能需要使用 &lt;code&gt;-Z symbol-manging-version=v0&lt;&#x2F;code&gt; 。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;RUSTFLAGS=&quot;-C symbol-manging-version=v0&quot; cargo &lt;cargo-options-if-any&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;编辑 .cargo&#x2F;config.toml&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;添加下面的内容即可，如果报错，请试试 &lt;code&gt;-Z&lt;&#x2F;code&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;nightly-x86_64-unknown-linux-gnu&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;rustflags&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-C&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;symbol-mangling-version=v0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;huan-neng-zuo-shen-me&quot;&gt;还能做什么？&lt;a class=&quot;zola-anchor&quot; href=&quot;#huan-neng-zuo-shen-me&quot; aria-label=&quot;Anchor link for: huan-neng-zuo-shen-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;拆分成更小的单元，让编译每个部分的时候不会太吃力；或者去掉一些笨重的依赖，让它不那么费劲；或者对编译选项进行更多调整，进行针对性优化。&lt;&#x2F;p&gt;
&lt;p&gt;好吧，今天就到这里咯，祝大家都能逃离 OOM ，换上更强悍的机器。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;笑死，清理了半天依赖，还剩下不到 900 个。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>论文十问</title>
        <published>2022-02-19T00:00:00+00:00</published>
        <updated>2022-02-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/ten-questions-for-reading-a-paper/"/>
        <id>https://psiace.me/zh/posts/ten-questions-for-reading-a-paper/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/ten-questions-for-reading-a-paper/">&lt;p&gt;最近有试着在读论文，由于自身积累问题，往往试图跳过其中艰深的部分，不能很好汲取其中的精华。&lt;&#x2F;p&gt;
&lt;p&gt;最近看到沈向洋老师的 “论文十问”，觉得很有帮助，现摘抄如下：&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lun-wen-shi-wen&quot;&gt;论文十问&lt;a class=&quot;zola-anchor&quot; href=&quot;#lun-wen-shi-wen&quot; aria-label=&quot;Anchor link for: lun-wen-shi-wen&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q1 论文试图解决什么问题？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q2 这是否是一个新的问题？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q3 这篇文章要验证一个什么科学假设？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q4 有哪些相关研究？如何归类？谁是这一课题在领域内值得关注的研究员？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q5 论文中提到的解决方案之关键是什么？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q6 论文中的实验是如何设计的？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q7 用于定量评估的数据集是什么？代码有没有开源？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q8 论文中的实验及结果有没有很好地支持需要验证的科学假设？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q9 这篇论文到底有什么贡献？&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&#x2F;&gt;
Q10 下一步呢？有什么工作可以继续深入？&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;yi-dian-e-wai-shuo-ming&quot;&gt;一点额外说明&lt;a class=&quot;zola-anchor&quot; href=&quot;#yi-dian-e-wai-shuo-ming&quot; aria-label=&quot;Anchor link for: yi-dian-e-wai-shuo-ming&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;需要正确区分问题之间的边界，既要讲出关键，又不能车轱辘话来回滚。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;尽量使用原文中的表达，并帮助没有前置知识的读者理解主题。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;十答应当能够表达清楚论文的主要工作和贡献。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>在 Fedora 上为 Btrfs 新建 32GiB Swapfile</title>
        <published>2022-01-23T00:00:00+00:00</published>
        <updated>2022-01-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/btrfs-32gib-swapfile-on-fedora/"/>
        <id>https://psiace.me/zh/posts/btrfs-32gib-swapfile-on-fedora/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/btrfs-32gib-swapfile-on-fedora/">&lt;p&gt;受到 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datafuselabs&#x2F;databend&#x2F;pull&#x2F;3946&quot;&gt;Databend - set swap to 10G&lt;&#x2F;a&gt; 的感召，检查了一下自己本子的 Swap ，只有大概 8G 的 zram 。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ swapon -s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       Size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       Used&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    Priority&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;dev&#x2F;zram0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      partition&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  8388604&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;       100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;完蛋，不能顺利跑完 grcov 限定版 unit-test 的原因大概就在这里了（之前有讨论过是 OOM）。本着「大就是好，多就是美」的原则，决定给它来个超级加倍，再塞个 32 GiB 的 Swapfile 上去。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;btrfs-xian-ding-zhi-chu-shi-hua-swapfile&quot;&gt;Btrfs 限定之初始化 Swapfile&lt;a class=&quot;zola-anchor&quot; href=&quot;#btrfs-xian-ding-zhi-chu-shi-hua-swapfile&quot; aria-label=&quot;Anchor link for: btrfs-xian-ding-zhi-chu-shi-hua-swapfile&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;自 5.0 内核之后，Btrfs 才支持创建 Swapfile ，而且有一些特别的要求：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Swapfile 不能放在 snapshotted subvolume （快照子卷）上。&lt;&#x2F;li&gt;
&lt;li&gt;不支持跨多设备文件系统上的 Swapfile 。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;所以正确的做法是：新建一个 non-snapshotted subvolume ，然后在该子卷之下创建禁用压缩的 Swapfile 。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Create a non-snapshotted subvolume.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora &#x2F;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo btrfs subvolume create swap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Create&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; subvolume&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;swap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Enter the subvolume.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora &#x2F;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ cd swap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Create a zero-length swapfile.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo truncate -s 0 .&#x2F;swapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Set the swapfile attribute to avoid copy-on-write.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo chattr +C .&#x2F;swapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Disable compression.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo btrfs property set .&#x2F;swapfile compression none&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;注意，这些需要在系统根目录下完成，以避免权限问题和设置问题。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;she-ding-swapfile-zuo-wei-swap-cheng-fen-zhi-yi&quot;&gt;设定 Swapfile 作为 Swap 成分之一&lt;a class=&quot;zola-anchor&quot; href=&quot;#she-ding-swapfile-zuo-wei-swap-cheng-fen-zhi-yi&quot; aria-label=&quot;Anchor link for: she-ding-swapfile-zuo-wei-swap-cheng-fen-zhi-yi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Swapfile 是创建特定交换分区的一种替代方案，好处是方便创建和删除、也便于动态变更大小。&lt;&#x2F;p&gt;
&lt;p&gt;这种方案比较适合 SSD 空间充裕的情况。刚好可以组成一个 memory -&amp;gt; zram -&amp;gt; swapfile 的多级交换。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Fill the swapfile to a suitable size, usually half of memory or close to memory size.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This is only for fun, so I chose a huge 32GiB, which is admittedly wasteful.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo dd&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;w&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; bs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;M&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;7&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; status&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;33980153856&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt; (34&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; GB,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; GiB&lt;&#x2F;span&gt;&lt;span&gt;) copied, 20 s, 1.7 GB&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;32768+0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; records&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;32768+0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; records&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; out&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;34359738368&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt; (34&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; GB,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; GiB&lt;&#x2F;span&gt;&lt;span&gt;) copied, 21.2624 s, 1.6 GB&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Set correct permissions.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo chmod 600 .&#x2F;swapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Format the swapfile as swap.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo mkswap .&#x2F;swapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Setting&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; up&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; swapspace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; version&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; GiB&lt;&#x2F;span&gt;&lt;span&gt; (34359734272&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;no&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; label,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; UUID=2e48f371-62a9-487a-9613-382b386b2836&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Enable the swapfile and set its priority.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Since zram has priority 100, set this to 50. After all, zram is much faster than a swapfile.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora swap&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo swapon --priority 50 .&#x2F;swapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;jian-cha-swap-kong-jian-bing-she-zhi-zi-dong-gua-zai&quot;&gt;检查 Swap 空间并设置自动挂载&lt;a class=&quot;zola-anchor&quot; href=&quot;#jian-cha-swap-kong-jian-bing-she-zhi-zi-dong-gua-zai&quot; aria-label=&quot;Anchor link for: jian-cha-swap-kong-jian-bing-she-zhi-zi-dong-gua-zai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;那么，经过之前两步，已经得到了接近 40GiB 的 Swap 空间，接下来就是检查一下，并设置挂载。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use free to check the overview.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ free -m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;               total&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        used&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        free&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      shared&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  buff&#x2F;cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   available&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Mem:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;           15453&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;        5206&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;         290&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;         109&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;        9956&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;        9808&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Swap:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;          40959&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;           2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;       40957&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use swapon to check details.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ swapon -s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       Size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       Used&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    Priority&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;dev&#x2F;zram0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      partition&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  8388604&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    2560&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;swap&#x2F;swapfile&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  file&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;       33554428&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;   0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;       50&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Edit fstab and add an entry to mount it.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The subvolume name must be included here. UUID is optional.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;psiace@fedora &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;$ sudo nano &#x2F;etc&#x2F;fstab&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;swap&#x2F;swapfile&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    none&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    swap&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    defaults&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;can-kao-zi-liao&quot;&gt;参考资料&lt;a class=&quot;zola-anchor&quot; href=&quot;#can-kao-zi-liao&quot; aria-label=&quot;Anchor link for: can-kao-zi-liao&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;笑死，一个多年 Fedora 用户看的文档大多都来自 Arch Wiki 。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Improving_performance#zram_or_zswap&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Btrfs#Swap_file&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Swap#Swap_file_creation&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Fstab&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;克制 Rust 编译大型项目时 OOM 还有一些小技巧，也许下次可以水一点内容。&lt;&#x2F;p&gt;
&lt;p&gt;我没有摸鱼！（手动狗头）&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>2021 年度总结 - Life is not a struggle</title>
        <published>2022-01-01T00:00:00+00:00</published>
        <updated>2022-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/2021-life-is-not-a-struggle/"/>
        <id>https://psiace.me/zh/posts/2021-life-is-not-a-struggle/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/2021-life-is-not-a-struggle/">&lt;p&gt;说是年度总结，却是在 2022 的第一天夜里才匆匆写几句，就是留个念头。&lt;&#x2F;p&gt;
&lt;p&gt;2021 年首要的关键字就是 &lt;strong&gt;「工作」&lt;&#x2F;strong&gt; 咯，从 7 月份入职，整整半年过去，应该算是顺利成为职场新人了。非常感谢 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BohuTANG&quot;&gt;@BohuTANG&lt;&#x2F;a&gt; 和 Datafuse Labs，让我有机会体验「全职开源 + 远程办公」的生活。成功凑了不少 commits 在 GitHub 上，还要继续努力才行。&lt;&#x2F;p&gt;
&lt;p&gt;回过头看看 2021 上半年，几乎就只有两次答辩的时候去了一段时间学校，感觉确实是离校园生活越来越远了。中间五月份因为扭伤比较严重，在床上躺了将近一个月，想起来还挺怨念的。不知道能不能有机会边工作边读读书（xs，总想着回炉重造是怎么回事）。&lt;&#x2F;p&gt;
&lt;p&gt;总之呢，2021 已经过去了。「Life is not a struggle」，希望自己能够与生活和解。新的一年，不要那么贪心，做好每一件事情，扎扎实实投入到学习和工作之中。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;另，昨天发了好多遍「早睡早起」，然而还是没做到 :(&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>Arch Linux 初始服务器设置</title>
        <published>2018-09-11T00:00:00+00:00</published>
        <updated>2018-09-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/init-server-setup-with-archlinux/"/>
        <id>https://psiace.me/zh/posts/init-server-setup-with-archlinux/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/init-server-setup-with-archlinux/">&lt;p&gt;&lt;strong&gt;本文所涉步骤仅在阿里云上进行了验证，但应当同样适用于其它云服务供应商。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;part-0-qian-yan&quot;&gt;Part 0：前言&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-0-qian-yan&quot; aria-label=&quot;Anchor link for: part-0-qian-yan&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我刚刚完成从 Red Hat 系（Fedora, CentOS）&lt;del&gt;完全&lt;&#x2F;del&gt;迁移到 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.archlinux.org&#x2F;&quot;&gt;Arch Linux&lt;&#x2F;a&gt; 的过程，这并不算是一个十分稳妥的选择，因为 Red Hat 系向来以高可靠性著称，即便是被称作试验田的 Fedora 也很少会因为稀奇古怪的问题而崩溃。但是，Arch Linux 作为一个滚动更新的发行版，它可以满足我对新鲜事物的好奇，并且该发行版提供的 Arch Wiki 以及 AUR 确实是值得我喜爱。&lt;&#x2F;p&gt;
&lt;p&gt;在将桌面系统更换为 Manjaro Linux（一个基于 Arch Linux 的发行版，便于上手）之后，我开始准备将我在阿里云的 ECS 实例也切换到 Arch Linux 上。在这里有一个小小的争论，因为大部分人认为这不是一个稳妥的选择，频繁更新造成的不稳定，以及需要重启以确保它可以正常启用服务。但另一方面，使用 Arch Linux 的好处同样很明显，时刻最新有助于安全性的提升，丰富的软件和优秀的用户群在各个方面提供帮助（是的，而且我觉得他们足够活跃，这至少意味着你的问题可以得到更加及时的回应），最重要的，百科全书式的 Arch Wiki（在所有 GNU&#x2F;Linux 系统里，只有两个在相关方面如此出色，另一个是 Gentoo）。我知道这并不足以说服那些追求稳定服务的运维人员，但至少我说服了我自己。值得一提的是 Arch Linux 的官网是运行在 Arch Linux 服务器上的。&lt;&#x2F;p&gt;
&lt;p&gt;好吧，让我们开始！&lt;&#x2F;p&gt;
&lt;h2 id=&quot;part-1-shi-yong-vps2arch-chuang-jian-arch-linux-fu-wu-qi&quot;&gt;Part 1：使用 vps2arch 创建 Arch Linux 服务器&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-1-shi-yong-vps2arch-chuang-jian-arch-linux-fu-wu-qi&quot; aria-label=&quot;Anchor link for: part-1-shi-yong-vps2arch-chuang-jian-arch-linux-fu-wu-qi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;说实在的，我更喜欢 Vultr，因为它提供的操作系统版本更新，而且有我一直喜爱的 Fedora。不过这都不重要了，因为它们都不直接支持 Arch Linux，我正在考虑要不要添加它的徽标到正在设计的网站上，这样一定会吸引不少人的目光。&lt;&#x2F;p&gt;
&lt;p&gt;创建自定义镜像是一件麻烦的工作，它需要花费一定的时间，而且并不是一项对新手友好的事情。好在，我们有 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;drizzt&#x2F;vps2arch&#x2F;&quot;&gt;vps2arch&lt;&#x2F;a&gt;，感谢 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;drizzt&quot;&gt;@drizzt&lt;&#x2F;a&gt; 以及其他贡献者所作出的努力。在一个初始创建为 CentOS 7.4 的 ECS 实例上，我们仅仅需要执行三条命令，接下来就可以完全按照提示进行了。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;注意，一切数据将会被清空，但将保留你的 root 密码并提供一个支持 SSH 的基础系统。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;wget&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; http:&#x2F;&#x2F;tinyurl.com&#x2F;vps2arch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;chmod&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; +x&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; vps2arch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;vps2arch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;重启之后，你将进入到 Arch Linux 中，一切都准备好了。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;part-2-cai-qu-yi-xie-pei-zhi-bu-zou-zuo-wei-ji-ben-she-zhi-de-yi-bu-fen&quot;&gt;Part 2：采取一些配置步骤作为基本设置的一部分&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-2-cai-qu-yi-xie-pei-zhi-bu-zou-zuo-wei-ji-ben-she-zhi-de-yi-bu-fen&quot; aria-label=&quot;Anchor link for: part-2-cai-qu-yi-xie-pei-zhi-bu-zou-zuo-wei-ji-ben-she-zhi-de-yi-bu-fen&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;yuan-cheng-ssh-lian-jie&quot;&gt;远程 SSH 连接&lt;a class=&quot;zola-anchor&quot; href=&quot;#yuan-cheng-ssh-lian-jie&quot; aria-label=&quot;Anchor link for: yuan-cheng-ssh-lian-jie&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;你可以先在本地尝试一下 &lt;code&gt;ssh root@your.ecs.ip.address&lt;&#x2F;code&gt;，如果你此前没有使用过 SSH 连接，它可能是可用的。但如果用过，则会出现一大段警告，并无法连接。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Someone could be eavesdropping on you right now (man-in-the-middle attack)!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;It is also possible that a host key has just been changed.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这个时候，我们需要使用 &lt;code&gt;ssh-keygen -R your.ecs.ip.address&lt;&#x2F;code&gt; 来清除产生冲突的旧密钥。再重新进行连接。厌倦了每次输入密码？那么考虑在本地使用 &lt;code&gt;ssh-copy-id username@your.ecs.ip.address&lt;&#x2F;code&gt; 将公钥添加到服务器中。之后，你应当可以直接连接到 ECS 实例。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;chuang-jian-fei-root-yong-hu-bing-cai-yong-sudo-shou-yu-guan-li-quan-xian&quot;&gt;创建非 ROOT 用户并采用 SUDO 授予管理权限&lt;a class=&quot;zola-anchor&quot; href=&quot;#chuang-jian-fei-root-yong-hu-bing-cai-yong-sudo-shou-yu-guan-li-quan-xian&quot; aria-label=&quot;Anchor link for: chuang-jian-fei-root-yong-hu-bing-cai-yong-sudo-shou-yu-guan-li-quan-xian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;使用 SSH 连接到你的服务器。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;useradd newusername&lt;&#x2F;code&gt; 将添加一个名为 newusername 的用户，而 &lt;code&gt;passwd newusername&lt;&#x2F;code&gt; 将为他设置密码。&lt;&#x2F;p&gt;
&lt;p&gt;接下来需要创建用户主目录并赋权，否则在你切换到新用户后仍然停留在根目录里（命令行提示会指出）。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;home&#x2F;newusername&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;chown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; newusername:newusername&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;home&#x2F;newusername&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;为了能够给新建用户授予管理权限，我们首先要安装 sudo 并编辑 &lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt; 文件。&lt;code&gt;pacman -S sudo&lt;&#x2F;code&gt; 安装 sudo，&lt;code&gt;chmod u+w &#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt; 增加写权限；采用 &lt;code&gt;vi &#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt; 编辑，在 &lt;code&gt;root ALL=(ALL) ALL&lt;&#x2F;code&gt; 下面一行添加 &lt;code&gt;newusername ALL=(ALL) ALL&lt;&#x2F;code&gt;，保存退出；&lt;code&gt;chmod u-w &#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt; 撤销写权限。&lt;&#x2F;p&gt;
&lt;p&gt;采用 &lt;code&gt;su - newusername&lt;&#x2F;code&gt; 切换用户到 newusername。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ji-ben-fang-huo-qiang&quot;&gt;基本防火墙&lt;a class=&quot;zola-anchor&quot; href=&quot;#ji-ben-fang-huo-qiang&quot; aria-label=&quot;Anchor link for: ji-ben-fang-huo-qiang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;iptables 已经被安装到了 Arch Linux 中，如果你不是很喜欢使用这个复杂的配置工具，我们可以选择使用 ufw 来进行接下来的步骤。（阿里云的安全组特性已经提供了类似防火墙的访问控制功能，但我认为服务器端也应该做出控制）&lt;&#x2F;p&gt;
&lt;p&gt;此时我们只需要确保防火墙允许 SSH 可以正常连接。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pacman&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ufw&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ufw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; app&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ufw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; allow&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; SSH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ufw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;此时防火墙已经开启，使用 &lt;code&gt;sudo ufw status&lt;&#x2F;code&gt; 可以查看当前状态。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Status: active&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;To                         Action      From&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--                         ------      ----&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SSH                        ALLOW       Anywhere&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SSH (v6)                   ALLOW       Anywhere (v6)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;pu-tong-yong-hu-de-ssh-fang-wen&quot;&gt;普通用户的 SSH 访问&lt;a class=&quot;zola-anchor&quot; href=&quot;#pu-tong-yong-hu-de-ssh-fang-wen&quot; aria-label=&quot;Anchor link for: pu-tong-yong-hu-de-ssh-fang-wen&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;你应当可以用类似 ROOT 用户的方法通过 SSH 登录到远程服务器，&lt;code&gt;ssh newusername@your.ecs.ip.address&lt;&#x2F;code&gt;，输入密码。&lt;&#x2F;p&gt;
&lt;p&gt;本地采用上面提到的 &lt;code&gt;ssh-copy-id&lt;&#x2F;code&gt; 命令可以帮助你启用密钥身份验证。&lt;&#x2F;p&gt;
&lt;p&gt;如果你在 root 用户下已经启用了 SSH 密钥验证，可以通过 rsync 将其复制到普通用户的目录下。（这里假设你仍是上面的普通用户）&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pacman&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .ssh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; su&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-chown=newusername:newusername&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ~&#x2F;.ssh&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;home&#x2F;newusername&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;最后一条语句经测试只能在 root 用户下使用，采用 sudo 指令不可行。&lt;&#x2F;p&gt;
&lt;p&gt;关闭连接，采用 &lt;code&gt;ssh newusername@your.ecs.ip.address&lt;&#x2F;code&gt;，这时应该可以正常使用密钥验证。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;part-3-jie-xia-lai&quot;&gt;Part 3：接下来...&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-3-jie-xia-lai&quot; aria-label=&quot;Anchor link for: part-3-jie-xia-lai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;基本的服务器配置已经处理好了，你可以着手去做你想要做的事情，或许从 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Kickball&#x2F;awesome-selfhosted&quot;&gt;Awesome Selfhosted&lt;&#x2F;a&gt; 中挑选一个自托管服务是一个不错的选择。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>在 Linux 上运行 MASM 汇编</title>
        <published>2018-09-06T00:00:00+00:00</published>
        <updated>2018-09-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/masm-on-linux/"/>
        <id>https://psiace.me/zh/posts/masm-on-linux/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/masm-on-linux/">&lt;p&gt;在 Linux 环境下使用汇编，使用 NASM 或是 GNU AS 无疑会方便很多，但国内的课程大多采用 MASM 进行讲解和作业，为了适应课堂需要，我们需要配置学习环境。&lt;&#x2F;p&gt;
&lt;p&gt;首先，使用最喜欢的包管理工具安装 DOSBox，例如 &lt;code&gt;sudo dnf install dosbox&lt;&#x2F;code&gt;。该软件是一个使用 SDL 库的 DOS 模拟程序，可以再现一个 MS-DOS 兼容环境。&lt;&#x2F;p&gt;
&lt;p&gt;其次，你需要准备使用的 MASM 软件，通常情况下，教师会为你提供 MASM 5.0 上机学习环境（包括 MASM.EXE LINK.EXE LIB.EXE 以及 CREF.EXE），这是可以在 DOS 环境下运行的几个版本之一，请下载它。当然你也可以自行寻找其它合适版本的 MASM，并找出这些程序。&lt;&#x2F;p&gt;
&lt;p&gt;接下来，把你找到的程序（至少包括 MASM.EXE LINK.EXE LIB.EXE 以及 CREF.EXE）放入 &lt;code&gt;~&#x2F;.dosbox&#x2F;MASM&lt;&#x2F;code&gt; 之中（需要在 &lt;code&gt;.dosbox&lt;&#x2F;code&gt; 下新建），然后在 &lt;code&gt;~&#x2F;.dosbox&#x2F;dosbox-0.74.conf&lt;&#x2F;code&gt; 中的 &lt;code&gt;[autoexec]&lt;&#x2F;code&gt; 部分录入：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[autoexec]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Lines in this section will be run at startup.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# You can put your MOUNT lines here.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MOUNT c &#x2F;home&#x2F;yourusername&#x2F;.dosbox&#x2F;MASM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set PATH= %PATH%;c:\;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mount E &#x2F;home&#x2F;yourusername&#x2F;asm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;好了，我们的安装准备已经完成，接下来是测试时间。&lt;&#x2F;p&gt;
&lt;p&gt;在你上面选择存放 &lt;code&gt;.asm&lt;&#x2F;code&gt; 的文件中新建 &lt;code&gt;hello.asm&lt;&#x2F;code&gt;，将 hello world 例程录入：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;asm&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assume &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;cs&lt;&#x2F;span&gt;&lt;span&gt;:codes, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;ds&lt;&#x2F;span&gt;&lt;span&gt;:datas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;datas segment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        str&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; db&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;hello,world&amp;#39;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&amp;#39;$&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;datas ends&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;codes segment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    start&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; ax&lt;&#x2F;span&gt;&lt;span&gt;, datas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; ds&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;ax&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        lea&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; dx&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; ah&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        int&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 21h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; ah&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4ch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        int&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 21h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;codes ends&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    end start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;打开 DOSBox，在命令行依次执行 &lt;code&gt;masm hello.asm&lt;&#x2F;code&gt;、&lt;code&gt;link hello.obj&lt;&#x2F;code&gt; 以及 &lt;code&gt;hello.exe&lt;&#x2F;code&gt;。如果配置成功，程序会输出 &lt;code&gt;hello,world&lt;&#x2F;code&gt;，这意味着我们的 MASM 学习环境已经配置成功了。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;9 月 24 日补充：&lt;&#x2F;p&gt;
&lt;p&gt;关于 &lt;code&gt;~&#x2F;.dosbox&#x2F;dosbox-0.74.conf&lt;&#x2F;code&gt; 的设置：&lt;code&gt;MOUNT c path&#x2F;to&#x2F;your&#x2F;folder&lt;&#x2F;code&gt; 是指定 C 盘的位置，所以完全可以用其他位置来代替。&lt;code&gt;set PATH= %PATH%;c:\;&lt;&#x2F;code&gt; 一句设定了环境变量。&lt;&#x2F;p&gt;
&lt;p&gt;关于 DEBUG 程序：直接放置到 C 盘目录之下即可，输入 &lt;code&gt;debug&lt;&#x2F;code&gt; 即可运行。&lt;&#x2F;p&gt;
&lt;p&gt;关于下载：可以在 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;http:&#x2F;&#x2F;www.phatcode.net&quot;&gt;http:&#x2F;&#x2F;www.phatcode.net&lt;&#x2F;a&gt; 找到相关内容。下载后直接解压，然后找出你所需要的内容放置在 C 盘下即可。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh">
        <title>尝试使用 Jekyll 与 GitHub Pages</title>
        <published>2018-07-14T00:00:00+00:00</published>
        <updated>2018-07-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://psiace.me/zh/posts/try-jekyll-with-github/"/>
        <id>https://psiace.me/zh/posts/try-jekyll-with-github/</id>
        
        <content type="html" xml:base="https://psiace.me/zh/posts/try-jekyll-with-github/">&lt;p&gt;&lt;em&gt;本文将帮助你快速入门，为了避免在介绍上花费过多时间，部分内容请感兴趣的同学自己查看官方网站和文档。&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;jekyllrb.com&quot;&gt;Jekyll&lt;&#x2F;a&gt; 是一个优秀的静态站点生成器，&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;pages.github.com&quot;&gt;GitHub Pages&lt;&#x2F;a&gt; 是 &lt;strong&gt;GitHub&lt;&#x2F;strong&gt; 提供的静态页面托管服务。使用这些，我们可以轻松地为项目&#x2F;组织构建网站，也可以发布自己的博客和简历。&lt;&#x2F;p&gt;
&lt;p&gt;同时使用 Jekyll 和 GitHub Pages 的一个最大的好处是你可以只关注内容，这是由于有很多优秀的设计师和开发人员为 Jekyll 制作了大量的美观实用的主题，而 GitHub 为我们节约了购置服务器的经费。唯一的限制可能仅仅是我们需要一些第三方服务来提供诸如评论和在线表单这样的功能。&lt;&#x2F;p&gt;
&lt;p&gt;本文会介绍以下几个方面的内容：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;本地部署 Jekyll&#x2F;GitHub Pages 环境&lt;&#x2F;li&gt;
&lt;li&gt;启用 GitHub Pages 的用户页面服务&lt;&#x2F;li&gt;
&lt;li&gt;使用优秀的 Jekyll Theme&lt;&#x2F;li&gt;
&lt;li&gt;Jekyll Theme 的组织结构&lt;&#x2F;li&gt;
&lt;li&gt;一些第三方服务和个性化配置&lt;&#x2F;li&gt;
&lt;li&gt;将你的页面发布 :)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;好吧，让我们现在就开始，玩的开心～&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ben-di-bu-shu-jekyll-github-pages-huan-jing&quot;&gt;本地部署 Jekyll&#x2F;GitHub Pages 环境&lt;a class=&quot;zola-anchor&quot; href=&quot;#ben-di-bu-shu-jekyll-github-pages-huan-jing&quot; aria-label=&quot;Anchor link for: ben-di-bu-shu-jekyll-github-pages-huan-jing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;首先我们需要一台联网的计算机，当然，如果没有也不用担心，我会考虑在后面添加如何使用手机来完成这项工作。&lt;&#x2F;p&gt;
&lt;p&gt;首先，你需要安装 Ruby 语言环境，这里提供 Fedora 系统上的命令行安装方法：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dnf&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ruby&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ruby-devel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;如果你使用的是 Ubuntu 系统，只需要把命令换成：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; apt-get&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ruby&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ruby-dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;至于 &lt;code&gt;[Y&#x2F;N]&lt;&#x2F;code&gt; 我们当然是选择 Y :)&lt;&#x2F;p&gt;
&lt;p&gt;如果你在使用 Windows 或是其它操作系统，请参考 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.ruby-lang.org&quot;&gt;Ruby 官网&lt;&#x2F;a&gt;，你可以很轻易得到安装办法。&lt;&#x2F;p&gt;
&lt;p&gt;接下来，使用 GitHub Pages 推荐的依赖方式创建本地环境。可以先安装 Bundler，然后在项目中通过 &lt;code&gt;github-pages&lt;&#x2F;code&gt; 这个 gem 对齐 GitHub Pages 环境：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bundler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myblog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myblog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bundle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;在 &lt;code&gt;Gemfile&lt;&#x2F;code&gt; 中添加：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gem &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;github-pages&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; group&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;jekyll_plugins&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;然后执行：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bundle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bundle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; exec&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; jekyll&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-force&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bundle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; exec&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; jekyll&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; serve&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;不直接使用 &lt;code&gt;gem install bundler jekyll&lt;&#x2F;code&gt; 的原因只是我们想要构建一个与 GitHub Pages 完全相同的环境。&lt;&#x2F;p&gt;
&lt;p&gt;在浏览器中输入它提供的地址（也许是 &lt;code&gt;http:&#x2F;&#x2F;localhost:4000&lt;&#x2F;code&gt; 或是 &lt;code&gt;http:&#x2F;&#x2F;127.0.0.1:4000&#x2F;&lt;&#x2F;code&gt;），你就可以看到一个官方提供的模板。&lt;&#x2F;p&gt;
&lt;p&gt;如果你喜欢它，可以直接在这个上开始工作，打开文件夹，在 &lt;code&gt;_posts&lt;&#x2F;code&gt; 目录下以 &lt;code&gt;yyyy-mm-dd-title.md&lt;&#x2F;code&gt; 按示例新建文件，编辑内容，然后就可以在页面上看到更改了，稍后我会额外介绍这些内容。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;qi-yong-github-pages-de-yong-hu-ye-mian-fu-wu&quot;&gt;启用 GitHub Pages 的用户页面服务&lt;a class=&quot;zola-anchor&quot; href=&quot;#qi-yong-github-pages-de-yong-hu-ye-mian-fu-wu&quot; aria-label=&quot;Anchor link for: qi-yong-github-pages-de-yong-hu-ye-mian-fu-wu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;如果你还没有 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&quot;&gt;GitHub&lt;&#x2F;a&gt; 的账号，我强烈推荐你注册一个，因为这是世界上最为活跃的&lt;del&gt;同性&lt;&#x2F;del&gt;交友社区之一 :) 只要访问主页，你就可以找到入口。&lt;&#x2F;p&gt;
&lt;p&gt;我强烈建议你参考 GitHub 的官方文档，它非常详细地介绍了所有你可能想要了解的内容。当然，你需要一点阅读英文文档的能力，至少要能够使用翻译。&lt;&#x2F;p&gt;
&lt;p&gt;好了，现在你已经有了 GitHub 的账号，通常情况下，我会建议你创建一个名为 &lt;code&gt;yourusername.github.io&lt;&#x2F;code&gt; 的存储库（请容许它使用 README 文档对存储库进行初始化，特别是当你打算试验而没有准备好内容），这样你就可以获得一个由 GitHub 友情提供的子域名，所有在主分支（&lt;code&gt;master&lt;&#x2F;code&gt;）的符合要求的内容都将被重构并发布，通常情况下，你可以在浏览器访问 &lt;code&gt;https:&#x2F;&#x2F;yourusername.github.io&lt;&#x2F;code&gt;，然后看到 &lt;code&gt;README.md&lt;&#x2F;code&gt; 被转化后的内容。&lt;&#x2F;p&gt;
&lt;p&gt;如果它没有正常显示或者你想在其它存储库启用 GitHub Pages，请打开存储库的 &lt;code&gt;Settings&lt;&#x2F;code&gt; 然后根据提示操作。如果你觉得页面光秃秃，可以通过 &lt;code&gt;Choose a theme&lt;&#x2F;code&gt; 来选择一个官方主题，但这不是必要的，因为我们接下来会介绍一些关于使用优秀的 Jekyll 主题和进一步定制的内容。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shi-yong-you-xiu-de-jekyll-theme&quot;&gt;使用优秀的 Jekyll Theme&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-yong-you-xiu-de-jekyll-theme&quot; aria-label=&quot;Anchor link for: shi-yong-you-xiu-de-jekyll-theme&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;造轮子是一件有意思的工作，但它往往需要花费大量的时间，而且一个好的想法可能需要经过大量的调试才能正常工作，如果你不满足于 Jekyll 的几个默认主题，那么我建议你试着使用一些优秀的 Jekyll 主题，它们往往实现了以下功能：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;响应式布局&lt;&#x2F;li&gt;
&lt;li&gt;良好的文件结构&lt;&#x2F;li&gt;
&lt;li&gt;标签云&#x2F;文章分类&lt;&#x2F;li&gt;
&lt;li&gt;优化的 SEO 设置&lt;&#x2F;li&gt;
&lt;li&gt;第三方评论&#x2F;统计插件支持&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;从优秀的 Jekyll 主题开始可以让你更专注于文章本身，而不是看上去数目众多的 CSS 代码 :)&lt;&#x2F;p&gt;
&lt;p&gt;这里我特别推荐三个主题：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Huxpro&#x2F;huxblog-boilerplate&quot;&gt;Huxblog-Boilerplate&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;，by &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Huxpro&#x2F;&quot;&gt;@Huxpro&lt;&#x2F;a&gt;，Apache License v2.0&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Simpleyyt&#x2F;jekyll-theme-next&quot;&gt;Jekyll NexT&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;，by &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Simpleyyt&#x2F;&quot;&gt;@Simpleyyt&lt;&#x2F;a&gt;，Unknown&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;renyuanz&#x2F;leonids&quot;&gt;Leonids&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;，by &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;renyuanz&#x2F;&quot;&gt;@renyuanz&lt;&#x2F;a&gt;，MIT License&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;点击主题名，你将跳转到它们的存储库，请选择你所喜欢的主题下载。&lt;&#x2F;p&gt;
&lt;p&gt;相信我，我们可以完全避开 Git 以及它的命令行工具，如果你不想跳过这些，那么你可能需要另外查看其它文章，我暂时没有介绍这些的计划。&lt;&#x2F;p&gt;
&lt;p&gt;如果你想查找更多主题，我强烈建议你查看 &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;http:&#x2F;&#x2F;jekyllthemes.org&quot;&gt;Jekyll Themes&lt;&#x2F;a&gt;，请从中挑选你喜欢的那个。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jekyll-theme-de-zu-zhi-jie-gou&quot;&gt;Jekyll Theme 的组织结构&lt;a class=&quot;zola-anchor&quot; href=&quot;#jekyll-theme-de-zu-zhi-jie-gou&quot; aria-label=&quot;Anchor link for: jekyll-theme-de-zu-zhi-jie-gou&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;我注意到我此前并没有提示如何使用这些 Jekyll 主题，其实很简单：&lt;code&gt;cd your-jekyll-theme&lt;&#x2F;code&gt;、&lt;code&gt;bundler install&lt;&#x2F;code&gt;、&lt;code&gt;jekyll serve&lt;&#x2F;code&gt;，同样你可以在浏览器得到一个本地预览的版本。即便你使用的命令没有包含 &lt;code&gt;--watch&lt;&#x2F;code&gt; 选项，内容的构建仍然会是实时的。&lt;&#x2F;p&gt;
&lt;p&gt;我知道你已经受够了空荡荡的主题或是为了演示而填充的没意义的内容以及我的啰嗦，但请再稍稍忍耐一下，这里会谈到 Jekyll Theme 的组织结构和一些简单的内容组织方式，这将有助于你下一步修改&#x2F;配置主题。&lt;&#x2F;p&gt;
&lt;p&gt;来吧，让我们用文件管理器或是你喜欢的文本编辑器打开你选定的主题所在的文件夹，看看里面有什么宝贝。&lt;&#x2F;p&gt;
&lt;p&gt;通常情况下，Jekyll Theme 会是下面所示的结构：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _config.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _drafts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   ├── begin-with-the-crazy-ideas.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   └── sample-and-test.markdown&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _includes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   ├── footer.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   └── header.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _layouts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   ├── default.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   └── post.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _posts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   ├── 2015-10-29-how-to-begin.textile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   └── 2013-04-26-hello-world.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   └── members.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── _site&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── index.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;保存配置数据。很多配置选项都会直接从命令行中进行设置，但是如果你把那些配置写在这儿，你就不用非要去记住那些命令了。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_drafts&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;drafts 是未发布的文章。这些文件的格式中都没有 &lt;code&gt;title.MARKUP&lt;&#x2F;code&gt; 数据。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_includes&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;你可以加载这些包含部分到你的布局或者文章中以方便重用。可以用 &lt;code&gt;{% raw %}{% include file.ext %}{% endraw %}&lt;&#x2F;code&gt; 来把文件 &lt;code&gt;_includes&#x2F;file.ext&lt;&#x2F;code&gt; 包含进来。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_layouts&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;layouts 是包裹在文章外部的模板。布局可以在 YAML 头信息中根据不同文章进行选择。标签 &lt;code&gt;{% raw %}{{ content }}{% endraw %}&lt;&#x2F;code&gt; 可以将 content 插入页面中。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_posts&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;这里放的就是你的文章了。文件格式很重要，必须要符合 &lt;code&gt;YEAR-MONTH-DAY-title.MARKUP&lt;&#x2F;code&gt;。The permalinks 可以在文章中自己定制，但是数据和标记语言都是根据文件名来确定的。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_data&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;格式良好的网站数据应该放在这里。Jekyll 引擎将自动加载此目录中的所有 yaml 文件（以 &lt;code&gt;.yml&lt;&#x2F;code&gt; 或 &lt;code&gt;.yaml&lt;&#x2F;code&gt; 结尾的文件）。如目录下有 &lt;code&gt;member.yml&lt;&#x2F;code&gt; 文件，则可以通过 &lt;code&gt;site.data.members&lt;&#x2F;code&gt; 访问该文件的内容。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_site&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;一旦 Jekyll 完成转换，就会将生成的页面放在这里（默认）。最好将这个目录放进你的 &lt;code&gt;.gitignore&lt;&#x2F;code&gt; 文件中。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;index.html&lt;&#x2F;code&gt; 和其它 HTML、Markdown、Textile 文件&lt;&#x2F;p&gt;
&lt;p&gt;如果这些文件中包含 YAML 头信息部分，Jekyll 就会自动将它们进行转换。当然，其他的如 &lt;code&gt;.html&lt;&#x2F;code&gt;、&lt;code&gt;.markdown&lt;&#x2F;code&gt;、&lt;code&gt;.md&lt;&#x2F;code&gt;、或者 &lt;code&gt;.textile&lt;&#x2F;code&gt; 等在你的站点根目录下或者不是以上提到的目录中的文件也会被转换。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;其它文件&#x2F;文件夹&lt;&#x2F;p&gt;
&lt;p&gt;其他一些未被提及的目录和文件如 css 还有 images 文件夹，favicon.ico 等文件都将被完全拷贝到生成的 site 中。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;是的，这里搬运了 Jekyll 官方网站的内容，因为它们已经被介绍的很详尽。我不愿意做一些重复的工作。&lt;&#x2F;p&gt;
&lt;p&gt;我会在下一部分结合实例来讲一下各个部分的使用。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yi-xie-di-san-fang-fu-wu-he-ge-xing-hua-pei-zhi&quot;&gt;一些第三方服务和个性化配置&lt;a class=&quot;zola-anchor&quot; href=&quot;#yi-xie-di-san-fang-fu-wu-he-ge-xing-hua-pei-zhi&quot; aria-label=&quot;Anchor link for: yi-xie-di-san-fang-fu-wu-he-ge-xing-hua-pei-zhi&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;chang-gui&quot;&gt;常规&lt;a class=&quot;zola-anchor&quot; href=&quot;#chang-gui&quot; aria-label=&quot;Anchor link for: chang-gui&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;用你最喜爱的文本编辑器打开你的 Jekyll Theme，首先我们需要编辑 &lt;code&gt;_config.yml&lt;&#x2F;code&gt; 文件，通常情况下，它会包含一些网站所必须的 SEO 信息，以及你一些个人信息，按照你的情况把它填好，如果里面没有你所需要的内容请留空。社交链接和默认的第三方服务通常是在这里进行配置。&lt;&#x2F;p&gt;
&lt;p&gt;哦，我想我们不需要那些为了展示而配备的文章，如果你恰恰和我一样使用 &lt;code&gt;Fedora with Gnome&lt;&#x2F;code&gt;（我只是不确定其它系统的情况）我建议你将它们移动到 &lt;code&gt;模板&lt;&#x2F;code&gt; 文件夹中，这样你就可以按它的格式新建文章。&lt;&#x2F;p&gt;
&lt;p&gt;让我们来看一下用于文章的 &lt;code&gt;.markdown(.md)&lt;&#x2F;code&gt; 文件与平时有什么不同，这里给出一个示例：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;itle&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; E&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lements&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;escription&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; M&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;arkdown-How-To&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ate&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2013-12-24 23:29:08&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ategories&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; F&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;oo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ags&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The purpose of this post is to help you make sure all of HTML elements can display properly. If you use CSS reset, don&amp;#39;t forget to redefine the style by yourself.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-separator&quot;&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Heading 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;##&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Heading 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;###&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Heading 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;####&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Heading 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;#####&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Heading 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;######&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Heading 6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-separator&quot;&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;##&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Paragraph&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Lorem ipsum dolor sit amet, &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-other z-link&quot;&gt;test link&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; consectetur adipiscing elit. &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;**&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;Strong text&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt; pellentesque ligula commodo viverra vehicula. &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-italic&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-italic&quot;&gt;Italic text&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-italic&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; at ullamcorper enim. Morbi a euismod nibh. &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Underline text&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; non elit nisl. &lt;&#x2F;span&gt;&lt;span&gt;~~&lt;&#x2F;span&gt;&lt;span&gt;Deleted text&lt;&#x2F;span&gt;&lt;span&gt;~~&lt;&#x2F;span&gt;&lt;span&gt; tristique, sem id condimentum tempus, metus lectus venenatis mauris, sit amet semper lorem felis a eros.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Interdum et malesuada fames ac ante ipsum primis in faucibus. &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inline z-raw&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inline z-raw&quot;&gt;Sed erat diam&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inline z-raw&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;, blandit eget felis aliquam, rhoncus varius urna.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-quote&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-quote&quot;&gt; Praesent diam elit, interdum ut pulvinar placerat, imperdiet at magna.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;##&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; List Types&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;###&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Definition List&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dl&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dt&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Definition List Title&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dt&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;This is a definition list division.&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;dl&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;###&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ordered List&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list z-begin z-markdown&quot;&gt;1.&lt;&#x2F;span&gt;&lt;span&gt; List Item 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list z-begin z-markdown&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span&gt; List Item 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list z-begin z-markdown&quot;&gt;3.&lt;&#x2F;span&gt;&lt;span&gt; List Item 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;###&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Unordered List&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list z-begin z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; List Item 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list z-begin z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; List Item 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list z-begin z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; List Item 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;##&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Table Header 1&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Table Header 2&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Table Header 3&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; ---&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; ---&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; ---&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Division 1&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Division 2&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Division 3&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Division 1&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Division 2&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Division 3&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Division 1&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Division 2&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; Division 3&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;此文章来自 NexT 主题，介绍了基本的 Markdown 用法，你可以对照页面来看，最前面被一组 &lt;code&gt;---&lt;&#x2F;code&gt; 包围的内容属于 YAML，包含了文档的信息：标题，描述，分类，标签，日期；我建议你为每篇文章添加这些内容来记录。&lt;&#x2F;p&gt;
&lt;p&gt;你可能还需要修改关于介绍博主的内容，一部分主题会在 &lt;code&gt;_config.yml&lt;&#x2F;code&gt; 中进行集成，还有一部分主题会包含一个名为 &lt;code&gt;about&#x2F;resume&lt;&#x2F;code&gt; 的文档，请把里面的内容换成你自己的。还有一种会使用 &lt;code&gt;_data&lt;&#x2F;code&gt; 文件夹内的数据或是引入 &lt;code&gt;_include&lt;&#x2F;code&gt; 文件夹中的内容，也同样请你修改它们，语法很简单，不做赘述。&lt;&#x2F;p&gt;
&lt;p&gt;这样你就可以把信息完全替换成你自己的，但我建议你保留页脚的部分信息，该内容通常会申明你使用的是什么主题。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;di-san-fang-fu-wu&quot;&gt;第三方服务&lt;a class=&quot;zola-anchor&quot; href=&quot;#di-san-fang-fu-wu&quot; aria-label=&quot;Anchor link for: di-san-fang-fu-wu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;啊哦，其实我有点担心是不是描述的足够清楚，如果有什么疑问的话请直接联系我。这一部分会介绍到如何加入第三方服务。&lt;&#x2F;p&gt;
&lt;p&gt;来看看我们需要哪些第三方服务：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;评论
&lt;ul&gt;
&lt;li&gt;多说&lt;&#x2F;li&gt;
&lt;li&gt;Disqus&lt;&#x2F;li&gt;
&lt;li&gt;来必力&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;统计&#x2F;SEO
&lt;ul&gt;
&lt;li&gt;百度&lt;&#x2F;li&gt;
&lt;li&gt;谷歌&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;这里以来必力和谷歌分析为例，选用这两个的原因只是因为方便，你可以自由选择适合你情况的服务。&lt;&#x2F;p&gt;
&lt;h4 id=&quot;qi-yong-gu-ge-fen-xi-cha-jian&quot;&gt;启用谷歌分析插件&lt;a class=&quot;zola-anchor&quot; href=&quot;#qi-yong-gu-ge-fen-xi-cha-jian&quot; aria-label=&quot;Anchor link for: qi-yong-gu-ge-fen-xi-cha-jian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;先说谷歌分析吧，它通常在各个主题之中都有良好的支持，你需要的只是填入它提供的 ID，当然，你需要一个独立的域名来做这件事，还需要番茄 :( 如果你想要使用百度分析，可能需要为域名进行备案，此外，百度的搜索引擎似乎是在 GitHub 的黑名单上。&lt;&#x2F;p&gt;
&lt;p&gt;我这里默认你已经有了域名，也做了番茄，如果你需要注册域名，腾讯阿里都可以提供服务。&lt;&#x2F;p&gt;
&lt;p&gt;打开 Google Analytics，按照提示进行操作，在执行完所有步骤之后，你会得到一个类似 &lt;code&gt;xx-xxxx-xxxx&lt;&#x2F;code&gt; 的字符串，如果没有，请从给出的 Javascript 代码中把它找出来，复制粘贴到 &lt;code&gt;_config.yml&lt;&#x2F;code&gt; 中合适的位置。&lt;&#x2F;p&gt;
&lt;p&gt;很简单不是吗？以这个为例子主要是为了展示它的运作模式。主题通常会通过 Liquid 条件判断检查你在 &lt;code&gt;_config.yml&lt;&#x2F;code&gt; 中是否填写了 &lt;code&gt;ga_track_id&lt;&#x2F;code&gt;，然后把对应的 id 和 domain 填入位置。&lt;&#x2F;p&gt;
&lt;p&gt;这类代码通常位于 &lt;code&gt;_include&#x2F;footer.html&lt;&#x2F;code&gt;，在 Huxblog 中，你可以在 &lt;code&gt;_layout&#x2F;default.html&lt;&#x2F;code&gt; 找到 &lt;code&gt;{% raw %}{% include footer.html %}{% endraw %}&lt;&#x2F;code&gt; 这个语句，使我们可以把 &lt;code&gt;footer.html&lt;&#x2F;code&gt; 包含在页面中。&lt;&#x2F;p&gt;
&lt;h4 id=&quot;an-zhuang-lai-bi-li-ping-lun-cha-jian&quot;&gt;安装来必力评论插件&lt;a class=&quot;zola-anchor&quot; href=&quot;#an-zhuang-lai-bi-li-ping-lun-cha-jian&quot; aria-label=&quot;Anchor link for: an-zhuang-lai-bi-li-ping-lun-cha-jian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;我知道这个第三方评论很少见，但鉴于天朝的环境，如果你想和小伙伴愉快发言，可以考虑一下。&lt;&#x2F;p&gt;
&lt;p&gt;打开 livere.com 按流程注册安装（我不想过多的描述这些没有意义的内容），你会得到一段 js 代码。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;如果你只打算自己用，请直接把它粘贴到 &lt;code&gt;_layout&#x2F;post.html&lt;&#x2F;code&gt; 中合适的位置。通常这是对应你博文所使用的模板。&lt;&#x2F;li&gt;
&lt;li&gt;如果你打算把它做成插件，我建议你在 &lt;code&gt;_include&lt;&#x2F;code&gt; 中新建一个 &lt;code&gt;livere.html&lt;&#x2F;code&gt; 然后把它粘贴进去，将 &lt;code&gt;data-uid&lt;&#x2F;code&gt; 后面引号的内容换成 &lt;code&gt;{% raw %}{{ site.livere_uid }}{% endraw %}&lt;&#x2F;code&gt;，然后在 &lt;code&gt;_config.yml&lt;&#x2F;code&gt; 中合适的位置新建一行 &lt;code&gt;livere_uid: &amp;lt;your-data-uid&amp;gt;&lt;&#x2F;code&gt;，在 &lt;code&gt;_layout&#x2F;post.html&lt;&#x2F;code&gt; 中添加 &lt;code&gt;{% raw %}{% if site.livere_uid %}{{ include livere.html }}{% endif %}{% endraw %}&lt;&#x2F;code&gt;。&lt;&#x2F;li&gt;
&lt;li&gt;如果你想要通过博客的 &lt;code&gt;markdown&lt;&#x2F;code&gt; 文件中的信息头来控制，请按 &lt;code&gt;{% raw %}{% if page.comments == true %}{% if site.livere_uid %}{{ include livere.html }}{% endif %}{% endif %}{% endraw %}&lt;&#x2F;code&gt; 的样式添加到 &lt;code&gt;post.html&lt;&#x2F;code&gt; 中，这样，你只需要在博文信息头中加入 &lt;code&gt;comments: true&lt;&#x2F;code&gt; 就可以使它正常工作。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;本来打算再讲一些其它的内容，一想我拖的时间有些长，而方法都大同小异，以后有需要再补。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jiang-ni-de-ye-mian-fa-bu&quot;&gt;将你的页面发布 :)&lt;a class=&quot;zola-anchor&quot; href=&quot;#jiang-ni-de-ye-mian-fa-bu&quot; aria-label=&quot;Anchor link for: jiang-ni-de-ye-mian-fa-bu&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;本地预览确实很没意思，毕竟只是自娱自乐，还是早点发布比较好，你也不用再在我这里花费更多的时间了。&lt;&#x2F;p&gt;
&lt;p&gt;相信你应该还找得到你在开始创建的 &lt;code&gt;yourusername.github.io&lt;&#x2F;code&gt; 存储库，现在我们要把你本地的 &lt;code&gt;your-jekyll-theme&lt;&#x2F;code&gt; 中的内容上传到那里。&lt;&#x2F;p&gt;
&lt;p&gt;一个很直接的方式就是点击存储库的 &lt;code&gt;Upload&lt;&#x2F;code&gt; 按钮，然后将内容统统拖拽进去。&lt;&#x2F;p&gt;
&lt;p&gt;我觉得这已经足够你完成这项工作，享受你的博客吧。&lt;&#x2F;p&gt;
&lt;p&gt;PS：如果我现在说你直接 &lt;code&gt;fork&lt;&#x2F;code&gt; 一个别人的主题存储库，然后把存储库的名字和内容进行修改就可以得到属于你的网站，你会不会打死我。&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
