<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[后端技术杂谈]]></title>
  <link href="https://www.rowkey.cn/atom.xml" rel="self"/>
  <link href="https://www.rowkey.cn/"/>
  <updated>2026-05-17T03:45:58+00:00</updated>
  <id>https://www.rowkey.cn/</id>
  <author>
    <name><![CDATA[HJ]]></name>
    <email><![CDATA[superhj1987@126.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[从管人到管系统行为：AI时代技术管理者的全新认知框架]]></title>
    <link href="https://www.rowkey.cn/blog/2026/05/17/tech-leader-ai-era-cognitive-framework/"/>
    <updated>2026-05-17T11:44:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/05/17/tech-leader-ai-era-cognitive-framework</id>
    <content type="html"><![CDATA[<p>最近大量使用 AI 进行开发，我逐渐意识到一个趋势：随着 AI 编程的普及，被颠覆的不仅仅是一线工程师的工作方式，对 CTO、技术总监、技术 Leader 这些技术管理者的要求，正在发生截然不同的改变。</p>

<p>过去，技术管理的核心在于“人”与“确定性”；而现在，当 AI 开始接管代码生成，系统正在变得“非确定性”。如何理解和控制这种非确定性，将成为下一代技术管理者的核心壁垒。</p>

<!-- more -->


<h2>传统的确定性时代：管组织与做平衡</h2>

<p>在传统的软件工程时代，代码由工程师一行行敲出来，系统严格按照设定的逻辑执行。</p>

<p>这种模式下，系统是高度确定性的：输入相同，输出必然相同。如果出了 Bug，顺着调用栈一层层 Debug，总能找到引发异常的那行代码。因此，技术管理者不需要每天盯着系统的细枝末节，核心精力主要放在以下三件事：</p>

<ul>
<li><strong>管理复杂组织</strong>：搭建梯队、拆分团队、把控研发效能。</li>
<li><strong>决策技术路线</strong>：选型、架构演进、技术债务管理。</li>
<li><strong>平衡业务与工程</strong>：在有限的资源下，平衡需求交付进度与系统长期健康度。</li>
</ul>


<h2>AI 编程时代：非确定性带来的失控感</h2>

<p>当研发流程全面接入 AI，情况变了。</p>

<p>现在是工程师设计约束，AI 负责生成代码。这种模式打破了传统的确定性——同样的输入，AI 每次给出的实现细节可能完全不同。这带来了一系列连锁反应：</p>

<ul>
<li><strong>调试极其复杂</strong>：代码不再是人类思维的直接映射，遇到 Bug 时，由于存在机器生成的不可解释性，排查链路变长。</li>
<li><strong>系统难以理解</strong>：大量 AI 生成的代码交织在一起，如果不加以严格规范，系统会变成一个连创造者都看不透的黑盒。</li>
<li><strong>风险更难控制</strong>：非确定性的代码直接进入工程环节，边界变得模糊，安全和可用性风险急剧上升。</li>
</ul>


<h2>技术管理者的新定位</h2>

<p>在这样的背景下，技术管理者的核心工作，正在从单纯的“管人”向“管系统行为”演进。未来的首要任务，是解决<strong>“如何完全理解系统为什么这么运行”</strong>的问题。</p>

<p>技术管理者的新角色正在转变为：</p>

<ul>
<li><strong>系统约束设计者</strong>：从设计架构，转变为设计“AI 生成与运行的约束条件”。通过制定严格的上下文准入边界、静态检查校验规则以及自动化测试拦截网，让 AI 在可控轨道内工作。</li>
<li><strong>AI 能力整合者</strong>：准确判断系统的哪些模块该用传统逻辑保底，哪些模块可以放权给 AI 生成。将大模型能力无缝、安全地整合进既有的工程开发链路中。</li>
<li><strong>风险控制负责人</strong>：面对非确定性输出，必须建立一套全新的兜底与熔断机制。从架构设计上控制 AI 产生错误代码或不可控行为的爆炸半径。</li>
</ul>


<h2>结语：建立全新的认知框架</h2>

<p>本质上，AI 时代的研发管理，需要建立一套全新的认知框架。</p>

<p>从管理“人类开发者的产能”，升级为管理“人机协同系统的行为边界”。对现有的技术管理者来说，这不仅是脱离舒适区的巨大挑战，更是抓住下一次技术代差、重塑团队战斗力的绝佳机会。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[SOUL.md 和 AGENTS.md 到底有什么区别？Agent 配置别再混着写了]]></title>
    <link href="https://www.rowkey.cn/blog/2026/04/06/soul-vs-agents/"/>
    <updated>2026-04-06T00:17:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/04/06/soul-vs-agents</id>
    <content type="html"><![CDATA[<p>很多人开始配置自己的 Agent 时，都会很快遇到一个问题：</p>

<p><strong><code>SOUL.md</code> 和 <code>AGENTS.md</code> 看起来都像是在“定义 Agent”，它们到底有什么区别？</strong></p>

<p>如果这两个文件不分清，后面就很容易出现一种典型混乱：人格写进岗位说明，业务流程写进行为准则，文件越写越多，Agent 反而越来越不像一个稳定的助手。</p>

<p>先说结论：</p>

<ul>
<li><code>SOUL.md</code> 负责定义 <strong>这个 Agent 怎么做人、怎么做事、什么不能碰</strong></li>
<li><code>AGENTS.md</code> 负责定义 <strong>这个 Agent 是干什么的、服务谁、交付什么、按什么流程工作</strong></li>
</ul>


<p>一句话：</p>

<p><strong><code>SOUL.md</code> 是灵魂，<code>AGENTS.md</code> 是岗位说明书。</strong></p>

<!-- more -->


<h2>一、为什么很多人会把这两个文件写混</h2>

<p>原因其实很简单：这两个文件都在描述 Agent，而且都不是技术配置项，而是自然语言规则。</p>

<p>于是很容易出现下面这种误写：</p>

<ul>
<li>在 <code>SOUL.md</code> 里写“每周发 3 篇小红书”</li>
<li>在 <code>AGENTS.md</code> 里写“说话别太啰嗦，先给结论”</li>
</ul>


<p>表面上看都能运行，但问题在于：</p>

<ul>
<li>文件边界开始模糊</li>
<li>后续维护的人不知道该改哪</li>
<li>Agent 接收到的行为信号会互相打架</li>
</ul>


<p>这就像你在公司里把“企业文化”和“岗位 KPI”写进同一张纸。</p>

<p>短期看没事，长期一定乱。</p>

<h2>二、<code>SOUL.md</code> 适合放什么</h2>

<p><code>SOUL.md</code> 更适合放那些<strong>跨任务长期有效的行为原则</strong>。</p>

<p>也就是：不管这个 Agent 今天在写文章、查资料、做排期，还是和你对话，它都应该稳定遵守的那一层规则。</p>

<p>它更像下面这些问题的答案：</p>

<ul>
<li>我应该怎么说话？</li>
<li>我做判断时遵循什么原则？</li>
<li>遇到边界问题时，什么必须先请示？</li>
<li>我的默认工作风格是什么？</li>
</ul>


<p>它适合放的内容，大致可以分成 4 类：</p>

<h3>1）表达风格</h3>

<p>比如：</p>

<ul>
<li>少客套，直接给价值</li>
<li>先结论，后细节</li>
<li>默认中文简体</li>
<li>可以适度直接，但不要油腻</li>
</ul>


<h3>2）行为原则</h3>

<p>比如：</p>

<ul>
<li>先做功课再提问</li>
<li>先保护用户，再追求效率</li>
<li>不编造来源</li>
<li>不确定信息必须标注待核实</li>
</ul>


<h3>3）边界与禁区</h3>

<p>比如：</p>

<ul>
<li>未经确认，不对外发布</li>
<li>不擅自联系他人</li>
<li>不替用户做超出授权的决定</li>
<li>涉及隐私和敏感内容默认谨慎</li>
</ul>


<h3>4）协作偏好</h3>

<p>比如：</p>

<ul>
<li>输出长度偏中等</li>
<li>不要太啰嗦</li>
<li>允许直接指出低效做法</li>
<li>遇到复杂问题先自己查，不要先把问题甩回给用户</li>
</ul>


<p>这些东西有一个共同点：</p>

<p><strong>它们不依赖具体业务，而定义的是这个 Agent 的稳定人格和做事方式。</strong></p>

<h2>三、<code>AGENTS.md</code> 适合放什么</h2>

<p>如果说 <code>SOUL.md</code> 解决的是“怎么做人”，那么 <code>AGENTS.md</code> 解决的就是“你到底是干什么的”。</p>

<p>它更适合放那些<strong>业务身份、职责范围、目标、流程和输出物</strong>。</p>

<p>它更像下面这些问题的答案：</p>

<ul>
<li>这个 Agent 的岗位是什么？</li>
<li>它服务谁？</li>
<li>它追求什么业务目标？</li>
<li>它平时交付哪些内容？</li>
<li>它按照什么 workflow 工作？</li>
</ul>


<p>通常来说，<code>AGENTS.md</code> 更适合放 5 类内容。</p>

<h3>1）角色定位</h3>

<p>比如：</p>

<ul>
<li>你是内容运营助理</li>
<li>你是产品助理</li>
<li>你是客服助理</li>
<li>你是销售支持助理</li>
</ul>


<h3>2）业务目标</h3>

<p>比如：</p>

<ul>
<li>沉淀知识资产</li>
<li>建立个人品牌</li>
<li>提升团队交付效率</li>
<li>降低重复沟通成本</li>
</ul>


<h3>3）服务对象 / 平台 / 受众</h3>

<p>比如：</p>

<ul>
<li>主要平台：公众号、小红书</li>
<li>目标受众：AI 从业者、程序员、Java 工程师</li>
<li>服务对象：HJ 本人和他的内容业务</li>
</ul>


<h3>4）核心工作流</h3>

<p>比如：</p>

<ul>
<li>收集输入</li>
<li>梳理观点</li>
<li>生成提纲</li>
<li>产出长文 / 短帖 / 配图提示词</li>
<li>发布前检查</li>
<li>复盘内容表现</li>
</ul>


<h3>5）默认交付物和衡量标准</h3>

<p>比如：</p>

<ul>
<li>默认产出长文、小红书文案、短帖摘要、封面文案</li>
<li>复盘优先级：阅读 > 收藏 > 转发</li>
<li>每周更新频率和平台节奏</li>
</ul>


<p>这些内容有一个共同点：</p>

<p><strong>它们定义的是这个 Agent 的工作岗位，而不是性格。</strong></p>

<h2>四、最直白的判断方法：一句规则到底回答了什么问题</h2>

<p>如果你拿到一条规则，不知道该放哪，就问自己一句：</p>

<p><strong>它到底在回答“我怎么做事”，还是“我做什么事”？</strong></p>

<h3>如果它回答的是“我怎么做事”</h3>

<p>放进 <code>SOUL.md</code>。</p>

<p>例如：</p>

<ul>
<li>少废话</li>
<li>先查再问</li>
<li>不编造</li>
<li>敏感动作先确认</li>
</ul>


<h3>如果它回答的是“我做什么事”</h3>

<p>放进 <code>AGENTS.md</code>。</p>

<p>例如：</p>

<ul>
<li>默认输出公众号长文和小红书文案</li>
<li>主要平台是公众号和小红书</li>
<li>工作流是收集 → 梳理 → 成文 → 检查 → 复盘</li>
<li>复盘指标优先看阅读和收藏</li>
</ul>


<p>这是区分这两个文件最省脑子的办法。</p>

<h2>五、一个常见误区：把所有东西都堆进 <code>SOUL.md</code></h2>

<p>很多人喜欢把一切“对 Agent 的要求”都堆进 <code>SOUL.md</code>，因为它名字听起来更高级。</p>

<p>但这会带来两个问题：</p>

<ul>
<li><code>SOUL.md</code> 变成一个无边界的大杂烩</li>
<li><code>AGENTS.md</code> 反而变空，只剩一句角色介绍</li>
</ul>


<p>这样做的后果是，Agent 会越来越像“有很多态度，但没什么明确职责”。</p>

<p>反过来也一样。</p>

<p>如果你把所有业务流程和 KPI 都塞进 <code>AGENTS.md</code>，却不定义风格和原则，那 Agent 通常会变成另一个问题：</p>

<ul>
<li>很像流程机器人</li>
<li>但没有稳定的判断框架</li>
<li>做事时容易僵、容易飘、容易忽冷忽热</li>
</ul>


<p>所以真正合理的方式，不是二选一，而是：</p>

<ul>
<li><code>SOUL.md</code> 负责“人格和准则”</li>
<li><code>AGENTS.md</code> 负责“业务和工作”</li>
</ul>


<p>两者配合，Agent 才会既稳定，又有明确产出。</p>

<h2>六、如果你要自己配 Agent，我建议按这个方式写</h2>

<p>最简单的模板可以是这样。</p>

<h3><code>SOUL.md</code></h3>

<p>只保留 4 类：</p>

<ul>
<li>风格</li>
<li>原则</li>
<li>边界</li>
<li>协作偏好</li>
</ul>


<h3><code>AGENTS.md</code></h3>

<p>只保留 5 类：</p>

<ul>
<li>角色</li>
<li>目标</li>
<li>受众 / 平台</li>
<li>工作流</li>
<li>交付物 / KPI</li>
</ul>


<p>如果你按这个思路来写，后面维护会轻松很多。</p>

<p>因为每次新增规则时，你都知道自己是在改：</p>

<ul>
<li>“这个 Agent 的做事方式”</li>
<li>还是“这个 Agent 的业务职责”</li>
</ul>


<p>这两个东西一旦分清，整个 Agent 配置就会明显稳定下来。</p>

<h2>结语</h2>

<p>Agent 配置这件事，表面上看是在写几个 Markdown 文件，本质上其实是在回答两个问题：</p>

<ul>
<li>这个助手应该成为什么样的人？</li>
<li>这个助手应该承担什么样的工作？</li>
</ul>


<p>前一个问题，交给 <code>SOUL.md</code>。</p>

<p>后一个问题，交给 <code>AGENTS.md</code>。</p>

<p>如果你把这两个文件的边界理顺了，后面很多配置问题都会变简单。</p>

<p>因为你终于不是在“堆规则”，而是在真正地设计一个有灵魂、也有岗位职责的 Agent。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[AI Agent 正在进入工程化深水区：从代码模型、生产框架到多智能体协作协议]]></title>
    <link href="https://www.rowkey.cn/blog/2026/03/31/ai-agent-engineering-depth/"/>
    <updated>2026-03-31T01:10:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/03/31/ai-agent-engineering-depth</id>
    <content type="html"><![CDATA[<p>过去一年，围绕 AI Agent 的讨论大多集中在模型能力本身。</p>

<p>但如果把最近几篇有代表性的内容放在一起看，一个更关键的变化已经出现：<strong>AI Agent 的竞争重心，正在从“模型能力展示”转向“工程系统能力”。</strong></p>

<p>这里的“工程系统能力”，不是一句空话。它至少包含四层：</p>

<ul>
<li>面向特定任务优化的模型能力</li>
<li>可接入生产环境的框架能力</li>
<li>能控制复杂度的架构能力</li>
<li>支撑协作扩展的协议能力</li>
</ul>


<p>如果只记一条：<strong>2026 年的 Agent，已经不再只是“大模型 + 工具调用”，而是在走向一套完整的软件工程体系。</strong></p>

<!-- more -->


<h2>一、模型层正在专用化：从“全能模型”转向“任务最优模型”</h2>

<p>以 Cursor 发布 Composer 2 为例，这类发布最容易被表面解读为“又一个新模型上线”。但如果只盯着 benchmark 分数，其实会错过真正重要的信息。</p>

<p>真正值得关注的是：<strong>垂直场景优化，正在从提示词层面的工程技巧，变成底层模型层面的产品策略。</strong></p>

<p>过去大家默认的路径是：</p>

<ul>
<li>先用一个尽可能强的通用模型</li>
<li>再通过 system prompt、工具定义、上下文拼接去适配业务场景</li>
</ul>


<p>而现在，越来越多产品开始反过来做：</p>

<ul>
<li>先承认模型不需要全能</li>
<li>再针对核心任务做专门训练和强化</li>
<li>最后用更低成本、更高稳定性去打场景穿透</li>
</ul>


<p>在代码生成领域，这个逻辑尤其成立。因为对开发者来说，关键指标从来不是“会不会聊天”，而是：</p>

<ul>
<li>多步修改是否稳定</li>
<li>大工程上下文下是否少犯错</li>
<li>工具调用链条是否顺</li>
<li>生成结果是否更接近可运行状态</li>
<li>成本是否足够低，能支撑高频使用</li>
</ul>


<p>所以代码模型的价值，不在于“像人一样懂很多”，而在于“在狭窄但高价值的任务里做到足够可靠”。</p>

<p>从工程视角看，这一步非常重要。因为一旦模型专用化开始成立，系统设计就会自然进入下一阶段：</p>

<ul>
<li>不同任务会使用不同模型</li>
<li>模型之间会形成分工</li>
<li>上层调度必须决定何时调用哪个能力</li>
<li>成本控制开始成为架构问题，而不是单次推理问题</li>
</ul>


<p>一句话：<strong>模型层一旦专用化，Agent 系统就不再是单核结构，而开始具备多能力模块化特征。</strong></p>

<h2>二、框架层正在生产化：企业真正要的不是“聪明”，而是“可治理”</h2>

<p>如果模型层的关键词是“专用化”，那么框架层的关键词就是“生产化”。</p>

<p>以 AgentScope Java 这类框架为代表，可以明显看到一个趋势：<strong>企业级 Agent 框架的卖点，已经从“快速做 Demo”转向“纳入生产治理体系”。</strong></p>

<p>一个 Demo 能跑起来，解决的是“能不能演示”；而一个生产系统能跑下去，解决的是另一组完全不同的问题：</p>

<ul>
<li>能否中断执行</li>
<li>能否保存状态并恢复</li>
<li>能否限制文件、网络、工具访问权限</li>
<li>能否观察中间推理过程</li>
<li>能否记录请求链路和成本</li>
<li>能否融入已有服务体系、监控体系和发布体系</li>
</ul>


<p>这些问题很少出现在社交媒体上的 Agent 演示视频里，但它们决定了系统是否能进入真实业务。</p>

<p>这也是为什么 Java 框架在企业 Agent 讨论里开始重新获得存在感。不是因为 Java 在模型创新上领先，而是因为大量企业核心系统、权限体系、服务治理体系本来就在 Java 世界里。谁更容易接入这些系统，谁就更容易跨过“从试验到生产”的门槛。</p>

<p>从架构角度看，生产化框架至少意味着三件事。</p>

<h3>1）Agent 不再只是一次性调用，而是一个有生命周期的执行体</h3>

<p>它可能被启动、暂停、中断、恢复、观察、接管。这说明 Agent 已经不再是单纯的“函数调用”，而更接近“状态化任务单元”。</p>

<h3>2）Agent 不再只追求最终答案，而要暴露过程</h3>

<p>生产环境里，最终结果固然重要，但更重要的是：</p>

<ul>
<li>它是怎么得出这个结果的</li>
<li>过程中调用了哪些工具</li>
<li>哪一步失败了</li>
<li>到底是模型错了，还是工具错了，还是上下文错了</li>
</ul>


<p>没有过程可见性，就没有治理能力。</p>

<h3>3）Agent 必须服从企业原有系统边界</h3>

<p>企业不会为了 Agent 重写整套权限和运维体系。真正可落地的框架，必须反过来适应既有系统，而不是要求企业围着 Agent 转。</p>

<p>因此，从这一步开始，Agent 就越来越像软件基础设施问题，而不是一个单独的 AI 功能问题。</p>

<h2>三、架构层正在分层化：多智能体不是默认架构，而是复杂度阈值后的选择</h2>

<p>过去一段时间，“多智能体”几乎成了 Agent 讨论里的政治正确。但真正有实践经验的团队，反而越来越强调另一条原则：<strong>Single Agent First。</strong></p>

<p>这个原则看起来保守，其实非常工程化。原因很简单：多智能体架构虽然听起来强大，但它天然会引入新的系统成本：</p>

<ul>
<li>角色划分成本</li>
<li>上下文切分成本</li>
<li>调度链路成本</li>
<li>状态同步成本</li>
<li>调试与排障成本</li>
<li>Token 与时延成本</li>
</ul>


<p>如果业务复杂度还没高到需要这些机制，那么多智能体带来的收益，很可能不足以覆盖它引入的复杂度。</p>

<p>因此，更合理的路径不是“先上多智能体，再想办法降复杂度”，而是：</p>

<ul>
<li>先用单智能体 + 工具解决大多数任务</li>
<li>只有在复杂度跨过阈值时，才引入多角色协作</li>
</ul>


<p>这个“阈值”通常出现在几类场景：</p>

<ul>
<li>上下文无法放进一个窗口</li>
<li>不同职责需要严格隔离</li>
<li>子任务天然适合并行</li>
<li>流程必须分段控制与校验</li>
<li>不同团队需要分别维护不同智能体能力</li>
</ul>


<p>这意味着，多智能体的本质不是“更聪明”，而是更适合处理复杂系统中的职责拆分与流程编排问题。</p>

<p>从这一点看，多智能体更像微服务演进中的服务拆分：</p>

<ul>
<li>在规模小、逻辑简单时，单体更高效</li>
<li>在复杂度上升后，拆分才开始有意义</li>
<li>拆分本身不是目标，控制复杂度才是目标</li>
</ul>


<h2>四、协议层正在标准化：Agent 系统开始进入“协作时代”</h2>

<p>当模型专用化、框架生产化、架构分层化之后，会自然冒出下一个问题：<strong>多个 Agent 之间如何协作？</strong></p>

<p>如果没有标准协议，所谓“多智能体”很容易退化成一种脆弱的私有编排：</p>

<ul>
<li>谁都能发消息，但格式不统一</li>
<li>上下文传递全靠手工拼接</li>
<li>能力授权边界模糊</li>
<li>任务交付物缺少稳定结构</li>
<li>一旦换一个 Agent 实现，协作链路就断掉</li>
</ul>


<p>这也是 A2A 这类协议值得关注的原因。它的价值，不是又发明了一个新缩写，而是试图回答协作系统里最基础的几个问题：</p>

<ul>
<li>如何发现具备特定能力的 Agent</li>
<li>如何把任务以结构化方式委托出去</li>
<li>如何只传递最小必要上下文</li>
<li>如何定义可验证的交付规格</li>
<li>如何在协作过程中进行受控授权</li>
</ul>


<p>这件事为什么重要？因为它标志着“上下文工程”的边界正在上移。</p>

<p>过去谈上下文工程，大家主要关注的是：</p>

<ul>
<li>prompt 怎么写</li>
<li>检索内容怎么塞</li>
<li>tool schema 怎么设计</li>
<li>memory 如何注入</li>
</ul>


<p>但在多 Agent 系统里，这些问题不再只发生在“人和模型之间”，还发生在“Agent 和 Agent 之间”。</p>

<p>于是新的工程问题出现了：</p>

<ul>
<li>哪些上下文应该共享</li>
<li>哪些上下文必须隔离</li>
<li>信息切片粒度如何定义</li>
<li>任务目标如何结构化描述</li>
<li>结果如何自动验收和回流</li>
</ul>


<p>当这些问题成为主问题时，Agent 系统的本质就已经变了。它不再只是“一个大模型加若干外挂工具”，而是在向“分布式协作系统”靠近。</p>

<h2>五、把四层放在一起看：Agent 正在从能力组件变成系统基础设施</h2>

<p>把前面四层连起来，可以看到一条非常清晰的演进链路：</p>

<ul>
<li>模型层专用化，解决特定任务的能力效率问题</li>
<li>框架层生产化，解决生产环境的治理问题</li>
<li>架构层分层化，解决复杂度与职责分工问题</li>
<li>协议层标准化，解决系统扩展与协作问题</li>
</ul>


<p>这四者不是并列关系，而是递进关系。</p>

<p>因为一旦你开始使用专用模型，就会需要调度；一旦你进入调度，就会需要框架与治理；一旦任务复杂度提高，就会需要角色拆分；一旦角色拆分发生，就会需要标准化协作协议。</p>

<p>所以今天讨论 Agent，最容易犯的错误，就是仍然把它理解成一个单点能力增强工具。实际上，它正在逐步变成一套软件系统的基础设施层。</p>

<p>从这个意义上说，<strong>Agent 的下半场竞争，本质上是软件工程能力的竞争。</strong></p>

<h2>六、对技术团队的实际启示</h2>

<p>如果这个判断成立，那么技术团队下一步最值得做的，不是继续沉迷“模型榜单更新”，而是反过来重建自己的落地顺序：</p>

<h3>1）先定义任务，再定义智能</h3>

<p>不要先问“哪个模型最强”，要先问：</p>

<ul>
<li>这个任务到底是问答、执行、编排还是协作</li>
<li>结果是开放式输出，还是结构化交付</li>
<li>容错成本高不高</li>
<li>有没有人工接管点</li>
<li>是否需要审计与追踪</li>
</ul>


<p>没有任务边界，讨论 Agent 架构几乎一定会失真。</p>

<h3>2）先做单智能体闭环，再决定是否升级多智能体</h3>

<p>先验证这几个东西：</p>

<ul>
<li>工具链路是否稳定</li>
<li>上下文设计是否有效</li>
<li>失败主要来自哪里</li>
<li>哪些环节真的需要拆角色</li>
<li>并发是否真的带来收益</li>
</ul>


<p>很多“多智能体需求”，最后会发现其实是“单智能体上下文和工具设计没做好”。</p>

<h3>3）尽早补齐治理面，而不是最后补</h3>

<p>包括：</p>

<ul>
<li>状态保存</li>
<li>权限隔离</li>
<li>中断恢复</li>
<li>过程观测</li>
<li>成本统计</li>
<li>回放与审计</li>
</ul>


<p>这些能力越晚补，代价越大。因为它们通常不是外挂功能，而是会反向影响你的框架选择与系统边界。</p>

<h2>结语</h2>

<p>如果只看单个新闻，最近这些变化看起来是分散的：一个代码模型升级了，一个 Java Agent 框架火了，一篇多智能体选型文章刷屏了，又出现了新的协作协议。</p>

<p>但把它们放在一起，就会看到更本质的趋势：<strong>AI Agent 正在从“可演示的智能能力”，演化成“可治理、可扩展、可协作的软件系统”。</strong></p>

<p>这意味着接下来的竞争，不只是“谁更聪明”，而是：</p>

<ul>
<li>谁的模型更适合任务</li>
<li>谁的框架更适合生产</li>
<li>谁的架构更能控制复杂度</li>
<li>谁的协议更能支撑协作扩展</li>
</ul>


<p>对于真正做落地的人来说，这反而是个好消息。因为从这一刻开始，Agent 不再只是模型厂商的游戏，而重新变成了系统设计者、架构师和工程团队的主战场。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OpenClaw Gateway 三种对外接口怎么选？]]></title>
    <link href="https://www.rowkey.cn/blog/2026/03/24/openclaw-gateway-protocol-comparison/"/>
    <updated>2026-03-24T16:36:02+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/03/24/openclaw-gateway-protocol-comparison</id>
    <content type="html"><![CDATA[<p>很多团队在接 OpenClaw Gateway 时，第一反应是：到底该用哪个接口？</p>

<p>答案不是“哪个更新就用哪个”，而是看你的目标：是先把能力接入，还是把系统做成可控、可观测、可治理的平台。</p>

<p>如果你只记一条：<strong>Chat Completions 适合快接入，OpenResponses 适合复杂编排，Gateway WS 适合平台控制面。</strong></p>

<p>本文按工程落地视角，把三种协议放到同一张决策图里讲清楚。</p>

<p>先明确一个问题：同一个 Gateway 为什么要提供三种接口？</p>

<p>这是“分层设计”而不是“重复造轮子”——兼容层负责接入效率，原生协议负责控制力与系统治理。</p>

<!-- more -->


<h2>一、三种接口各自解决什么问题</h2>

<h3>1）Gateway 协议（WebSocket）</h3>

<p>这是 OpenClaw 的原生控制面协议。客户端通过 WebSocket 握手（connect），声明 role/scopes/caps，然后以 req/res/event 方式通信。</p>

<p>它最适合做：</p>

<ul>
<li>自研控制台</li>
<li>会话与节点能力统一编排</li>
<li>审批、配置、设备配对、运维级治理</li>
</ul>


<p>一句话：<strong>最完整，但接入门槛最高。</strong></p>

<hr />

<h3>2）OpenAI Chat Completions（<code>/v1/chat/completions</code>）</h3>

<p>这是面向存量生态的兼容接口。你已有 OpenAI SDK 或上层框架时，几乎可以低改造迁移。</p>

<p>它最适合做：</p>

<ul>
<li>快速打通业务链路</li>
<li>验证模型+工具能力</li>
<li>已有 OpenAI 生态资产复用</li>
</ul>


<p>一句话：<strong>上手最快，迁移成本最低。</strong></p>

<hr />

<h3>3）OpenResponses（<code>/v1/responses</code>）</h3>

<p>这是更现代的兼容接口，强调 item 化输入、工具回合、多模态输入（文件/图片）和更细颗粒度的流式事件。</p>

<p>它最适合做：</p>

<ul>
<li>复杂工具调用回合</li>
<li>多模态上下文输入</li>
<li>需要更强可观测事件流的 Agent 系统</li>
</ul>


<p>一句话：<strong>语义更完整，适合复杂场景。</strong></p>

<hr />

<h2>二、工程决策矩阵（可直接拿去评审）</h2>

<h3>维度 1：接入复杂度</h3>

<ul>
<li>最低：Chat Completions</li>
<li>中等：OpenResponses</li>
<li>最高：Gateway WS</li>
</ul>


<h3>维度 2：生态兼容性</h3>

<ul>
<li>最强：Chat Completions</li>
<li>次之：OpenResponses</li>
<li>最弱（但可控性最高）：Gateway WS</li>
</ul>


<h3>维度 3：工具与回合表达能力</h3>

<ul>
<li>Chat Completions：够用，偏经典函数调用形态</li>
<li>OpenResponses：更适合复杂工具回合与结构化交互</li>
<li>Gateway WS：可做全链路控制与事件编排</li>
</ul>


<h3>维度 4：可观测性与治理</h3>

<ul>
<li>Chat Completions：偏业务调用视角</li>
<li>OpenResponses：事件语义更细，观测更自然</li>
<li>Gateway WS：控制面最完整，适合平台治理</li>
</ul>


<h3>维度 5：长期演进空间</h3>

<ul>
<li>Chat Completions：适合作为入口层</li>
<li>OpenResponses：适合作为复杂业务主接口</li>
<li>Gateway WS：适合作为平台核心控制面</li>
</ul>


<hr />

<h2>三、三类典型团队该怎么选</h2>

<h3>场景 A：你要“这周上线”</h3>

<p>选 Chat Completions。</p>

<p>原因：复用现有 SDK，改造最小，最快出结果。</p>

<h3>场景 B：你要“复杂 Agent 工作流”</h3>

<p>选 OpenResponses。</p>

<p>原因：输入输出语义更现代，工具回合、多模态、事件流更顺手。</p>

<h3>场景 C：你要“公司级 AI 平台控制面”</h3>

<p>选 Gateway WS。</p>

<p>原因：只有原生协议能把角色、权限、节点能力、审批、配置纳入一套统一治理模型。</p>

<hr />

<h2>四、推荐落地路径（避免一步到位翻车）</h2>

<h3>Phase 1：先用 Chat Completions 跑通业务闭环</h3>

<p>目标：验证价值，不纠结架构完美。</p>

<h3>Phase 2：把复杂链路迁到 OpenResponses</h3>

<p>目标：提升工具编排能力和事件可观测性。</p>

<h3>Phase 3：控制治理能力下沉到 Gateway WS</h3>

<p>目标：统一权限、审批、配置与节点编排，做成平台而不是脚本集合。</p>

<hr />

<h2>五、生产防坑清单</h2>

<ol>
<li><strong>协议选型不要脱离组织能力</strong>：团队不会维护 WS 客户端，就别上来就全量 WS。</li>
<li><strong>先定义会话键与幂等策略</strong>：没有幂等，重试就是事故放大器。</li>
<li><strong>日志字段跨协议统一</strong>：requestId/sessionKey/runId 必须统一，才能追踪问题。</li>
<li><strong>权限边界先于功能边界</strong>：先做“能不能做”，再做“做什么更快”。</li>
<li><strong>演进路线写进技术方案</strong>：短期兼容层、长期控制面，避免每次重构都推倒重来。</li>
</ol>


<hr />

<h2>结语</h2>

<p>OpenClaw Gateway 三种接口不是替代关系，而是分层协作关系。</p>

<p>对工程团队来说，真正重要的不是“选哪个最先进”，而是：</p>

<ul>
<li>当前阶段怎么最快交付价值</li>
<li>下一阶段怎么平滑升级</li>
<li>最终怎么形成可控、可观测、可治理的平台能力</li>
</ul>


<p>这才是协议选型的终局。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Agent 落地不靠更强模型：后端团队先补这 4 个治理动作]]></title>
    <link href="https://www.rowkey.cn/blog/2026/03/18/agent-governance-for-backend-teams/"/>
    <updated>2026-03-18T21:00:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/03/18/agent-governance-for-backend-teams</id>
    <content type="html"><![CDATA[<p>最近一轮知识库信息放在一起看，结论很清楚：
Agent 已经从“能不能做”进入“能不能稳定做、持续做、规模做”。</p>

<p><strong>真正决定成败的，不是模型上限，而是工程治理下限。</strong></p>

<p>很多团队现在都能把 Agent 跑起来：接 IM、调工具、跑自动化流程。
但一上真实业务就出问题：串会话、误操作、成本飙升、结果不可复盘。
这类问题本质上不是 Prompt 问题，而是系统边界没有建好。</p>

<!-- more -->


<h2>一、会话与并发治理：先保证可预测，再谈性能</h2>

<p>第一步不是提并发，而是先把并发“关进笼子”：</p>

<ul>
<li>同会话串行执行，避免上下文串台</li>
<li>消息队列策略固定（collect / followup）</li>
<li>设置会话排队上限、超时与丢弃规则</li>
</ul>


<p>如果这一层没做，业务一上量就会出现“同一用户前后文互相污染”，后面所有优化都白做。</p>

<h2>二、工具权限治理：把“会执行”变成“可控执行”</h2>

<p>Agent 接了终端、文件、外部 API 后，风险不再是“答错一句话”，而是“做错一件事”。</p>

<p>必须落地三件事：</p>

<ul>
<li>工具最小权限（默认 deny）</li>
<li>高风险动作审批（删除、外发、系统修改）</li>
<li>审计日志留痕（谁在何时执行了什么）</li>
</ul>


<p>没有这层，任何一次误调用都可能直接变生产事故。</p>

<h2>三、稳定性与成本治理：把失败设计成默认路径</h2>

<p>生产环境里，失败不是例外，是常态。
要提前把“故障时怎么继续”设计好：</p>

<ul>
<li>模型/密钥 fallback 链</li>
<li>限流与错误指数退避</li>
<li>上下文压缩 + 工具结果修剪</li>
</ul>


<p>目标只有一个：在坏环境下还能跑，不把服务打穿。</p>

<h2>四、内容运营治理：把一次经验变成团队资产</h2>

<p>纯技术落地如果不转成“可复用内容”，团队学习曲线会重复踩坑。</p>

<p>建议固定复盘模板：</p>

<ul>
<li>本次问题与触发条件</li>
<li>处置动作与回滚策略</li>
<li>可复用检查项</li>
<li>下一次默认配置</li>
</ul>


<p>技术治理 + 内容沉淀同时做，才能形成长期复利。</p>

<h2>上线前最小检查清单（可直接执行）</h2>

<ul>
<li>[ ] 会话边界明确，DM/群聊不串台</li>
<li>[ ] 队列策略配置并压测通过</li>
<li>[ ] 工具最小权限与审批生效</li>
<li>[ ] 关键执行链路可审计</li>
<li>[ ] 模型故障有 fallback 与退避</li>
<li>[ ] 上下文与成本可观测</li>
<li>[ ] 复盘模板落盘并可复用</li>
</ul>


<h2>结语</h2>

<p>Agent 落地不是“再接一个模型”，而是“先建一套护栏”。
先把系统变成可控工程，再把效率放大。
这一步做对了，后面才是真正的规模化红利。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OpenClaw多Agent方案]]></title>
    <link href="https://www.rowkey.cn/blog/2026/03/12/openclaw-multi-agent-architecture/"/>
    <updated>2026-03-12T01:50:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/03/12/openclaw-multi-agent-architecture</id>
    <content type="html"><![CDATA[<p>很多团队把 Agent 做到第二阶段都会遇到同一个问题：</p>

<ul>
<li><p>单个 Agent 已经不够用，要拆“角色分工”。</p></li>
<li><p>一台机器放不下所有任务，要跨多台主机部署。</p></li>
<li><p>代理之间需要通信协作，但又不能互相污染上下文。</p></li>
</ul>


<p>这篇文章基于 OpenClaw 官方文档，系统讲清四件事：<strong>单机多 Agent 怎么搭</strong>、<strong>单主机多 OpenClaw 实例何时可用</strong>、<strong>多 OpenClaw 主机怎么协作</strong>、<strong>代理间如何通信才稳定可控</strong>。</p>

<!-- more -->


<h2>1. 先统一心智模型：OpenClaw 的多 Agent 不是“多人格提示词”</h2>

<p>在 OpenClaw 里，一个 agent 本质是一个“完整隔离单元”，它拥有自己的：</p>

<ul>
<li><p>workspace（包括 AGENTS.md/SOUL.md/USER.md 与本地文件上下文）</p></li>
<li><p>agentDir（认证与 agent 级状态）</p></li>
<li><p>sessions（会话与路由状态）</p></li>
</ul>


<p>所以“多 Agent”是工程级隔离，而不是同一上下文里改几段提示词。</p>

<hr />

<h2>2. 单机多 Agent：推荐的标准架构</h2>

<p>先给结论：<strong>一个 Gateway + 多个 agent + 显式 bindings 路由</strong> 是官方推荐范式。</p>

<h3>2.1 架构骨架</h3>

<ul>
<li><p>一台主机只跑一个 Gateway（官方架构约束）。</p></li>
<li><p>Gateway 持有所有渠道连接（Telegram/WhatsApp/Slack/&hellip;）。</p></li>
<li><p>通过 <code>bindings</code> 把不同 channel/account/peer 的入站消息，确定性路由到不同 agent。</p></li>
<li><p>每个 agent 使用独立 workspace 和 agentDir，避免认证与会话冲突。</p></li>
</ul>


<h3>2.2 最小配置示例（单机多 Agent）</h3>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>{
</span><span class='line'>  "agents": {
</span><span class='line'>    "list": [
</span><span class='line'>      {
</span><span class='line'>        "id": "assistant",
</span><span class='line'>        "default": true,
</span><span class='line'>        "workspace": "~/.openclaw/workspace-assistant",
</span><span class='line'>        "agentDir": "~/.openclaw/agents/assistant/agent"
</span><span class='line'>      },
</span><span class='line'>      {
</span><span class='line'>        "id": "research",
</span><span class='line'>        "workspace": "~/.openclaw/workspace-research",
</span><span class='line'>        "agentDir": "~/.openclaw/agents/research/agent"
</span><span class='line'>      }
</span><span class='line'>    ]
</span><span class='line'>  },
</span><span class='line'>  "bindings": [
</span><span class='line'>    {
</span><span class='line'>      "agentId": "research",
</span><span class='line'>      "match": {
</span><span class='line'>        "channel": "telegram",
</span><span class='line'>        "peer": { "kind": "direct", "id": "tg:123456789" }
</span><span class='line'>      }
</span><span class='line'>    },
</span><span class='line'>    {
</span><span class='line'>      "agentId": "assistant",
</span><span class='line'>      "match": { "channel": "telegram" }
</span><span class='line'>    }
</span><span class='line'>  ]
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>


<h3>2.3 单机模式下的通信方式</h3>

<p>同一 Gateway 内，agent 间协作优先走 session 工具：</p>

<ul>
<li><p><code>sessions_send</code>：向另一个 session 发消息并等待结果（可超时控制）。</p></li>
<li><p><code>sessions_spawn</code>：派生隔离子代理执行长任务，完成后回传摘要。</p></li>
</ul>


<p>这两类通信在同一 Gateway 内是“内生通信”，上下文边界更清晰、可追踪性更好。</p>

<h3>2.4 单主机多 OpenClaw 实例：可做，但要明确边界</h3>

<p>有些团队会在同一台机器上启动多个 OpenClaw 进程（而不是一个 Gateway 托管多个 agent）。这个方案不是主路径，但在“强隔离”诉求下可用。</p>

<p>适用场景：</p>

<ul>
<li><p>你需要把不同业务线彻底隔离到不同进程生命周期。</p></li>
<li><p>你希望为不同实例配置不同端口、不同状态目录、不同系统服务策略。</p></li>
</ul>


<p>必须满足的工程约束：</p>

<ul>
<li><p>每个实例使用独立 <code>OPENCLAW_STATE_DIR</code>。</p></li>
<li><p>每个实例使用独立 Gateway 端口（避免 WS/HTTP 端口冲突）。</p></li>
<li><p>每个实例的 channel 账号登录状态独立管理，避免同账号并发占用。</p></li>
<li><p>每个实例独立 workspace/agentDir，避免会话与认证污染。</p></li>
</ul>


<p>实践建议：如果目标只是“多人格/多角色协作”，优先选择<strong>单 Gateway + 多 agent + bindings</strong>。只有当你明确需要“进程级隔离”时，再采用单主机多实例。</p>

<hr />

<h2>3. 多 OpenClaw 主机：现实可用的 3 种协作拓扑</h2>

<p>这里最容易误解：<strong>OpenClaw 官方当前核心是“单 Gateway 控制面”</strong>。跨主机协作不是默认内建成“跨 Gateway 透明 RPC”。</p>

<p>所以工程上要用“桥接层”把多主机连起来。</p>

<h3>3.1 拓扑 A：渠道桥接（推荐起步）</h3>

<ul>
<li><p>Host-A 的 agent 通过消息渠道（如 Telegram Bot/群）发任务。</p></li>
<li><p>Host-B 作为另一个 OpenClaw 实例在同渠道接收并处理。</p></li>
<li><p>处理结果再通过渠道回发到 Host-A 或人工会话。</p></li>
</ul>


<p>优点：部署快，稳定性高，几乎不用改 OpenClaw 内核。</p>

<h3>3.2 拓扑 B：Webhook / Hook 事件桥接</h3>

<ul>
<li><p>Host-A 将任务打包成结构化事件（JSON）投递给 Host-B 的接收端。</p></li>
<li><p>Host-B 的 Hook/入口会话消费事件并触发 agent 执行。</p></li>
<li><p>回传可走 webhook 回调或消息渠道。</p></li>
</ul>


<p>优点：便于与现有后端系统集成，适合平台化。</p>

<h3>3.3 拓扑 C：外部任务总线桥接（企业场景）</h3>

<ul>
<li><p>两台 OpenClaw 通过外部队列/任务系统（如 Redis Streams、Kafka、SQS）解耦。</p></li>
<li><p>OpenClaw 只做“智能执行器”，任务编排交给外部工作流层。</p></li>
</ul>


<p>优点：吞吐与治理能力最好，但实施复杂度最高。</p>

<hr />

<h2>4. 代理间通信与协作：建议采用“分层协议”</h2>

<h3>4.1 协作协议（建议）</h3>

<ul>
<li><p>控制消息：任务编号、优先级、超时、重试策略。</p></li>
<li><p>业务消息：输入参数、上下文摘要、期望输出格式。</p></li>
<li><p>回执消息：状态（accepted/running/done/failed）、结果摘要、错误分类。</p></li>
</ul>


<h3>4.2 角色分工（建议）</h3>

<ul>
<li><p>Orchestrator Agent：接任务、拆解、派发、汇总。</p></li>
<li><p>Worker Agent：按契约执行单一子任务。</p></li>
<li><p>Reviewer Agent：做一致性检查与质量门禁。</p></li>
</ul>


<h3>4.3 三条硬规则</h3>

<ul>
<li><p><strong>幂等键</strong>：每个任务都要有业务 id，重复投递可安全去重。</p></li>
<li><p><strong>超时与降级</strong>：<code>sessions_send</code>/外部桥接必须有 timeout 与 fallback。</p></li>
<li><p><strong>上下文最小化</strong>：跨代理只传“必要上下文 + 结构化结果”，不要整段历史硬转发。</p></li>
</ul>


<h3>4.4 协议补充：A2A（Google Agent2Agent）与 ANP（Agent Network Protocol）</h3>

<p>在跨系统、跨组织的多代理协作里，可以把 OpenClaw 作为运行时，把 A2A/ANP 当作“外部互联协议层”。</p>

<ul>
<li><p><strong>A2A（Agent2Agent）</strong>：Google 发起的开放互操作协议，强调任务生命周期、能力发现（Agent Card）、长任务状态同步，以及基于 HTTP / SSE / JSON-RPC 的标准化通信。</p></li>
<li><p><strong>ANP（Agent Network Protocol）</strong>：国内社区推动的开源协议，重点放在开放网络中的智能体身份与安全通信（例如 DID 身份、认证与加密通道）。</p></li>
</ul>


<p>一个实用落地方式：</p>

<ul>
<li><p>OpenClaw 内部（同 Gateway 或同实例）优先用 <code>sessions_send</code> / <code>sessions_spawn</code>。</p></li>
<li><p>OpenClaw 与外部 Agent 平台协作时，可通过桥接层接入 A2A。</p></li>
<li><p>在跨组织、需要身份自治与安全互信的场景，可评估引入 ANP 作为身份与通信补充层。</p></li>
</ul>


<p>注意：协议选型要看你的治理边界——企业内统一平台优先 A2A 生态兼容，开放网络互联优先关注 ANP 的身份与安全模型成熟度。</p>

<hr />

<h2>5. 实操中的常见坑</h2>

<ul>
<li><p>把多个 agent 复用同一个 <code>agentDir</code>，导致认证/会话冲突。</p></li>
<li><p>bindings 规则不够具体，出现“路由命中漂移”。</p></li>
<li><p>把跨主机协作当成同机 <code>sessions_send</code>，结果通信链路设计不完整。</p></li>
<li><p>没有幂等，重试时重复执行副作用（重复发消息/重复写库）。</p></li>
<li><p>没有统一状态模型，排障时看不到“任务卡在哪一跳”。</p></li>
</ul>


<hr />

<h2>6. 给团队的落地建议（从 0 到 1）</h2>

<ul>
<li><p>第一步：先在单机把“多 Agent + bindings + sessions_spawn”跑顺。</p></li>
<li><p>第二步：引入一种跨主机桥接（先渠道桥接，再升级 webhook/队列）。</p></li>
<li><p>第三步：补齐治理（幂等、重试、审计、告警、权限边界）。</p></li>
</ul>


<p>这样做的好处是：每一步都可验证，不会把复杂度一次性打满。</p>

<hr />

<h2>7. 总结</h2>

<p>OpenClaw 的多 Agent 架构要点可以压缩成一句话：</p>

<blockquote><p><strong>同机协作用 Gateway 内生会话工具，跨机协作用外部桥接层；隔离、路由、幂等是稳定性的三根柱子。</strong></p></blockquote>

<p>如果你正在做多代理系统，不要先追求“最智能”，先把“能稳定协作”做出来。</p>

<hr />

<h2>参考资料（权威来源）</h2>

<ul>
<li><p>OpenClaw 官方文档：Gateway Architecture<br/>
<a href="https://docs.openclaw.ai/concepts/architecture">https://docs.openclaw.ai/concepts/architecture</a></p></li>
<li><p>OpenClaw 官方文档：Multi-Agent Routing<br/>
<a href="https://docs.openclaw.ai/concepts/multi-agent">https://docs.openclaw.ai/concepts/multi-agent</a></p></li>
<li><p>OpenClaw 官方文档：Session Tools（sessions_send / sessions_spawn）<br/>
<a href="https://docs.openclaw.ai/concepts/session-tool">https://docs.openclaw.ai/concepts/session-tool</a></p></li>
<li><p>OpenClaw 官方文档：Sub-Agents<br/>
<a href="https://docs.openclaw.ai/tools/subagents">https://docs.openclaw.ai/tools/subagents</a></p></li>
<li><p>OpenClaw 官方文档：Configuration Reference<br/>
<a href="https://docs.openclaw.ai/gateway/configuration-reference">https://docs.openclaw.ai/gateway/configuration-reference</a></p></li>
<li><p>Google Developers Blog：Announcing the Agent2Agent Protocol (A2A)<br/>
<a href="https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/">https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/</a></p></li>
<li><p>A2A 协议官方文档（Linux Foundation 托管）<br/>
<a href="https://a2a-protocol.org/latest/">https://a2a-protocol.org/latest/</a></p></li>
<li><p>ANP 官方文档（中文）<br/>
<a href="https://www.agent-network-protocol.com/zh/guide/">https://www.agent-network-protocol.com/zh/guide/</a></p></li>
<li><p>ANP 身份与加密通信层<br/>
<a href="https://agentnetworkprotocol.com/docs/concepts/identity/">https://agentnetworkprotocol.com/docs/concepts/identity/</a></p></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OpenClaw 架构剖析]]></title>
    <link href="https://www.rowkey.cn/blog/2026/03/03/openclaw-architecture/"/>
    <updated>2026-03-03T00:15:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/03/03/openclaw-architecture</id>
    <content type="html"><![CDATA[<p>上一篇聊了「OpenClaw 是什么」。这一篇更偏工程视角：<strong>OpenClaw 到底怎么实现一个可长期运行的 Agent 系统？消息是怎么进来的？怎么路由到 Agent？工具调用与定时任务如何编排？</strong></p>

<p>如果你做过 Agent 落地，会很熟悉这些关键词：channel、tool、session、cron、memory、安全边界、幂等、观测……OpenClaw 的价值在于把这些抽象成一套可部署的 runtime。</p>

<!-- more -->


<h2>1. OpenClaw 由哪些模块组成？</h2>

<p><img src="https://www.rowkey.cn/post_images/openclaw/arch.jpg" width="450"/></p>

<p>你可以把 OpenClaw 想成三层：</p>

<p>1) <strong>接入层（Channels）</strong>：连接外部世界（Telegram/钉钉/QQ/…），负责收消息、发消息。</p>

<p>2) <strong>编排层（Gateway + Routing + Sessions）</strong>：决定“这条消息交给哪个 Agent/哪个会话”，并维护状态与生命周期。</p>

<p>3) <strong>执行层（Agents + Tools/Skills + Jobs）</strong>：Agent 负责决策，Tools 负责执行，Jobs（cron 等）负责触发。</p>

<p>对应到工程实体，大致是：</p>

<blockquote><p>关键约束（和官方架构一致）：<strong>一台主机一个 Gateway</strong>、<strong>连接首帧必须是 <code>connect</code> 握手</strong>、<strong>事件流默认不回放（客户端需自行补拉状态）</strong>。</p></blockquote>

<ul>
<li><strong>Gateway（守护进程）</strong>：常驻运行，连接多个 channel provider，维护连接与重连。</li>
<li><strong>Channel Plugin</strong>：每个渠道一个适配器，实现 inbound/outbound。</li>
<li><strong>WebChat/UI 客户端</strong>：本质是通过 WebSocket 连接 Gateway 的控制平面客户端。</li>
<li><strong>Agent</strong>：可配置多个（不同模型/不同工作空间/不同权限），按路由绑定到渠道。</li>
<li><strong>Session</strong>：把对话与任务上下文组织起来（类似“对话线程 + 状态机”）。</li>
<li><strong>Skills</strong>：可复用的工具说明与脚本集合，给 Agent 一个“可靠使用工具”的方法。</li>
<li><strong>Cron/Jobs</strong>：把定时触发变成一等公民，支持隔离执行、送达与可配置去重策略。</li>
<li><strong>Memory</strong>：长期/短期记忆（以文件记忆为主 + 语义检索），为跨会话连续性服务。</li>
</ul>


<h2>2. 核心流程 1：一条消息从“外部”到“Agent”的路径</h2>

<p>把它拆成 8 步，你会发现它是一条典型的事件驱动流水线：</p>

<p>1) <strong>Channel 收到事件</strong></p>

<ul>
<li>可能是文本、图片、语音、文件、按钮回调等。</li>
</ul>


<p>2) <strong>插件标准化（Normalize）</strong></p>

<ul>
<li>把不同平台的 message schema 归一：from/to/messageId/timestamp/chatType/attachments…</li>
</ul>


<p>3) <strong>封装输入（Envelope）</strong></p>

<ul>
<li>给 Agent 一个稳定的“输入格式”，避免每个渠道都写一套提示词。</li>
</ul>


<p>4) <strong>路由（Routing/Binding）</strong></p>

<ul>
<li>根据规则把消息交给指定 agent（例如 QQ 走 hang-ai，Telegram 走 main）。</li>
</ul>


<p>5) <strong>会话选择（Session Key）</strong></p>

<ul>
<li>同一用户/群聊映射到固定 session，确保上下文连续。</li>
</ul>


<p>6) <strong>Agent 推理（Decide）</strong></p>

<ul>
<li>Agent 选择：直接回复，还是调用工具（搜索/执行/写文件/定时任务）。</li>
</ul>


<p>7) <strong>工具执行（Tools/Skills）</strong></p>

<ul>
<li>工具是“副作用层”：读写文件、访问网络、调用 API、跑命令。</li>
</ul>


<p>8) <strong>回传与发送（Outbound Deliver）</strong></p>

<ul>
<li>将 Agent 结果交给 channel 插件发送，处理分段、markdown、富媒体等。</li>
</ul>


<blockquote><p>这条链路里，最容易做坏的其实是第 2～5 步：输入不干净、路由不清晰、session 混乱，都会让 Agent “聪明但不稳定”。OpenClaw 的设计重点正是在这里。</p></blockquote>

<h2>3. 核心流程 2：工具调用如何“可靠地执行”？</h2>

<p>一个可落地的 Agent 系统，工具调用必须具备三种属性：</p>

<h3>3.1 可控（Controllable）</h3>

<ul>
<li>工具入口有限且明确（不是什么都能 exec）。</li>
<li>敏感能力要有策略（allowlist/denylist/人工确认）。</li>
</ul>


<h3>3.2 可观测（Observable）</h3>

<ul>
<li>能看到：调用了什么工具、参数是什么、耗时多久、失败原因。</li>
<li>能复盘：某次输出是怎么来的。</li>
</ul>


<h3>3.3 可恢复（Recoverable）</h3>

<ul>
<li>失败要能重试/降级（例如 web fetch 失败就换来源）。</li>
<li>长链路要能分段（先产出，再补充）。</li>
</ul>


<p>OpenClaw 的 skill 机制，本质是在做“<strong>把提示词工程变成可维护的工程资产</strong>”。你不希望每次靠大模型临场发挥写一堆 shell；你希望它遵循一个稳定的脚本与约定。</p>

<h2>4. 核心流程 3：Cron/Jobs（定时任务）为什么是 Agent 生产化的关键？</h2>

<p>很多 Agent 项目死在“能对话，但不能跑”。原因是：</p>

<ul>
<li>任务不能准点触发</li>
<li>不能隔离执行（被主会话上下文污染）</li>
<li>失败后没有送达保障</li>
<li>会重复发送（没有幂等）</li>
</ul>


<p>OpenClaw 的 cron 设计可以抽象成：</p>

<ul>
<li><strong>触发器（schedule）</strong>：cron / every / at</li>
<li><strong>执行体（payload）</strong>：systemEvent 或 agentTurn（隔离会话跑）</li>
<li><strong>投递（delivery）</strong>：把结果发到指定 channel/target</li>
<li><strong>幂等/去重</strong>：通常用 state 文件（last_date/last_hash）或业务键</li>
</ul>


<blockquote><p>一个很实用的经验：<strong>凡是“每天推送/定时汇总/提醒”的任务，都要把幂等写成硬性要求</strong>。这比“写得更聪明”重要得多。</p></blockquote>

<h2>5. 语音/图片等多媒体：为什么“把内容注入正文”很关键？</h2>

<p>以语音为例，很多系统会把语音转写结果作为“附件描述”塞进消息里，但 Agent 可能把它当噪声过滤掉，最后表现为“不回复”。</p>

<p>更可靠的做法是：</p>

<ul>
<li>语音 → 转写</li>
<li><strong>把转写文本当作用户输入正文</strong>（例如前缀“（语音转写）xxx”）</li>
<li>同时保留附件元信息（可选）：文件路径、时长、来源</li>
</ul>


<p>这其实是一条通用原则：</p>

<blockquote><p><strong>Agent 真正在乎的是“它以为用户说了什么”。</strong> 所以多模态处理的结果要进入“正文层”，而不是“旁注层”。</p></blockquote>

<h2>6. 可复用的方法论：如何用 OpenClaw（或任何 Agent Runtime）做出稳定的系统？</h2>

<p>下面这套方法论与 OpenClaw 强相关，但本质上是通用的 Agent 工程原则。</p>

<h3>方法论 1：把 Agent 系统拆成“决策层 vs 执行层”</h3>

<ul>
<li>决策层：LLM/Agent（可变、概率性）</li>
<li>执行层：脚本/工具/skill（确定性、可测试）</li>
</ul>


<p>越早把副作用收敛到执行层，你的系统越稳。</p>

<h3>方法论 1.5：模块化优先——Plugin 与 Skill 是“可加载的工程单元”</h3>

<p>很多 Agent 项目后期会失控，本质原因是：所有能力都堆在一个巨大的代码/提示词里，无法升级、无法替换、也无法复用。</p>

<p>OpenClaw 的架构里有两个非常值得复用的抽象：</p>

<ul>
<li><strong>Plugin（插件）</strong>：面向“渠道/外部系统”的适配层。它把不稳定、强耦合的外部差异隔离掉（消息格式、鉴权、富媒体、限流、重连…）。</li>
<li><strong>Skill（技能）</strong>：面向“工具使用”的可维护模块。它把“如何调用某个工具”沉淀成文档/脚本/约定，让 Agent 可靠执行。</li>
</ul>


<p>你在研发其他项目时可以照搬这套思想：</p>

<ul>
<li><strong>把所有 I/O 做成插件接口</strong>（inbound/outbound 都走统一协议）</li>
<li><strong>把执行能力做成可装卸的模块</strong>（每个模块有清晰的输入输出契约）</li>
<li><strong>把运行时策略配置化</strong>（允许按项目/按环境切换能力组合）</li>
</ul>


<p>这样系统才具备“长期演进能力”：</p>

<ul>
<li>想换搜索引擎/供应商？替换 skill 即可。</li>
<li>想多接一个渠道？加一个 plugin，不影响核心。</li>
<li>想做权限收敛？在 runtime/策略层统一控制。</li>
</ul>


<h3>方法论 2：事件驱动 + 明确的状态机</h3>

<p>你会发现 OpenClaw 的心智模型很像：
- event in → route → session → agent → tools → deliver</p>

<p>这其实就是一个状态机。把“会话键/幂等键/任务键”定义清楚，系统就会稳定。</p>

<h3>方法论 2.5：把“配置”当成系统契约（Contract），而不是参数堆</h3>

<p>OpenClaw 里很多稳定性来自于“约束前置”：</p>

<ul>
<li>绑定规则（哪个 channel → 哪个 agent）</li>
<li>工具权限（哪些 tool 可用/哪些 elevated 禁止）</li>
<li>推送策略（cron 的去重文件、重试退避）</li>
</ul>


<p>工程上你可以把它抽象成：</p>

<ul>
<li><strong>配置即策略</strong>：把可变决策（谁能做什么、什么时候做）从代码里拿出来。</li>
<li><strong>配置可审计</strong>：出现事故时能追溯“当时允许了什么”。</li>
<li><strong>配置可迁移</strong>：换环境/换机器/换团队时，复制配置即可复现能力。</li>
</ul>


<h3>方法论 3：任何自动推送都必须幂等</h3>

<p>推荐最低配：</p>

<ul>
<li><code>last_date</code>（今天发过就退出）</li>
<li><code>last_hash</code>（内容一致就退出）</li>
</ul>


<p>把它当成产品级需求，而不是“优化项”。</p>

<h3>方法论 4：先做可观测，再做智能</h3>

<p>一个很反直觉的点：</p>

<ul>
<li>你以为“让模型更聪明”能解决问题</li>
<li>实际上，80% 的线上问题来自：超时、失败重试、权限、消息格式、平台限制</li>
</ul>


<p>所以先把日志、运行记录、失败原因打通，后面再谈“更聪明”。</p>

<h3>方法论 5：安全边界要前置</h3>

<p>建议至少做到：</p>

<ul>
<li>渠道 allowlist / groupPolicy</li>
<li>敏感工具禁用或需要确认</li>
<li>不信任外部内容（把网页/邮件当不可信输入）</li>
</ul>


<p>Agent 的安全不是模型能解决的，是架构要解决的。</p>

<h2>7. 总结</h2>

<p>OpenClaw 的架构并不神秘：它把 Agent 的生产化问题拆解为一组工程模块（channel、session、tool、cron、memory、安全策略），并把“核心流程”做成可运行、可观测、可扩展的系统。</p>

<p>如果你要复用它的方法论，记住一句话就够：</p>

<blockquote><p><strong>让 LLM 做决策，让系统做约束，让工具做执行。</strong></p></blockquote>

<p>这就是把 Agent 从 demo 推向长期运行系统的关键。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OpenClaw 是什么]]></title>
    <link href="https://www.rowkey.cn/blog/2026/03/01/openclaw/"/>
    <updated>2026-03-01T00:00:00+08:00</updated>
    <id>https://www.rowkey.cn/blog/2026/03/01/openclaw</id>
    <content type="html"><![CDATA[<p>这两年大家对「Agent」的讨论越来越多：能自动查资料、能写代码、能跑流程、还能定时汇总。但真要把它放进日常工作流，会立刻遇到几个现实问题：<strong>它怎么和你的消息渠道连起来？怎么定时？怎么拿到你本机/服务器的上下文？怎么安全地执行命令？怎么长期稳定运行？</strong></p>

<p>OpenClaw 解决的不是“再做一个聊天机器人”，而是把这些“让 Agent 变成生产力”的工程问题打包成一套可部署、可扩展的运行时。</p>

<!-- more -->


<h2>1. OpenClaw 到底是什么？</h2>

<p>一句话：<strong>OpenClaw 是一个面向个人/团队的 Agent 运行时（Agent Runtime）</strong>。</p>

<p>它更像一个“智能操作系统/中枢”，把三件事连接起来：</p>

<p>1) <strong>你的输入输出渠道（Channels）</strong>：比如 Telegram、钉钉、QQ、Slack…你在哪里说话，它就在哪里接收与回复。</p>

<p>2) <strong>可执行的工具系统（Tools/Skills）</strong>：不仅是“搜索”，还包括：跑脚本、读写文件、定时任务、发消息、抓网页、处理媒体、接入第三方服务等。</p>

<p>3) <strong>Agent 的会话与状态（Sessions/Memory/Jobs）</strong>：把对话、任务、定时推送、长期记忆等组织起来，能持续运行、可追踪、可回放。</p>

<p>从使用感受上，它像一个“你自己的 AI 助理平台”，而不是单次问答。</p>

<h2>2. 为什么会出现 OpenClaw？（解决 Agent 落地的 4 个痛点）</h2>

<h3>2.1 只靠 Chat，不够</h3>

<p>把大模型当聊天工具，最多做到“回答问题”。但现实工作更像“完成任务”：</p>

<ul>
<li>每天 10:00 推送 AI 新闻</li>
<li>监控某些关键词/博客更新</li>
<li>把语音转文字、把图片转摘要</li>
<li>在你允许的情况下执行命令、生成文件、提交仓库</li>
</ul>


<p>这些都需要一个稳定的执行层。</p>

<h3>2.2 工具碎片化，拼起来很痛</h3>

<p>你可以用各种 bot、脚本、cron、Webhook、爬虫、自动化平台……但拼在一起时，常见问题是：</p>

<ul>
<li>触发点分散（消息、定时、网页变化）</li>
<li>状态难管理（重复发送、幂等、去重）</li>
<li>缺少统一的权限与审计</li>
<li>失败重试、降级策略没人兜底</li>
</ul>


<p>OpenClaw 的定位就是把这些“胶水层”标准化。</p>

<h3>2.3 Agent 需要“能跑得起来”的生命周期</h3>

<p>Agent 不应该只存在于一次对话里，而应该具备：</p>

<ul>
<li><strong>可持续运行</strong>（daemon/service）</li>
<li><strong>可定时触发</strong>（cron jobs）</li>
<li><strong>可隔离执行</strong>（isolated sessions）</li>
<li><strong>可观察</strong>（日志、运行记录、失败原因）</li>
</ul>


<h3>2.4 更重要的是：安全边界</h3>

<p>Agent 一旦能执行命令、能发消息、能访问外部链接，就一定会遇到：</p>

<ul>
<li>prompt injection（内容里夹带指令）</li>
<li>权限扩大（工具链越接越多越危险）</li>
<li>数据泄露（日志、外发、第三方 API）</li>
</ul>


<p>OpenClaw 的思路是：把工具权限、通道策略、定时任务、敏感能力控制放进同一套配置与运行时里。</p>

<h2>3. 怎么使用 OpenClaw？（一个最小心智模型）</h2>

<p>OpenClaw 里你可以把系统理解成：</p>

<ul>
<li><strong>Gateway（网关/守护进程）</strong>：负责连接各个 channel、接收消息、派发给 agent、把回复送回去。</li>
<li><strong>Agent（智能体）</strong>：负责“思考与决策”，选择调用哪些工具。</li>
<li><strong>Skills（技能）</strong>：一套可复用的“说明 + 脚本 + 约定”，让 agent 可靠地使用工具。</li>
<li><strong>Cron（定时任务）</strong>：把“每天/每小时/某个时刻做事”变成一等公民。</li>
</ul>


<p>一个典型的工作流是：</p>

<p>1) 你在 Telegram/钉钉/QQ 里发一句话：</p>

<blockquote><p>“每天 10 点给我推送 AI 新闻”</p></blockquote>

<p>2) Agent 把它变成一个 cron job（带去重与失败重试）。</p>

<p>3) 到点了 cron 自动触发，agent 做检索→整理→发送消息。</p>

<p>4) 你觉得格式不对，再要求调整；之后就稳定每天按你的格式推送。</p>

<h2>3.5 一个“最小 Quickstart”（不追求完美，只求跑通）</h2>

<p>如果你只想快速体验 OpenClaw 的核心价值，可以按这个顺序：</p>

<p>1) <strong>选一个入口渠道</strong>：先接 Telegram/钉钉/QQ 其中一个（你日常最常用的）。</p>

<p>2) <strong>跑通一条闭环任务</strong>：例如“每天 10:00 推送 AI 新闻”。</p>

<p>3) <strong>把输出格式固定下来</strong>：标题、条目数量、每条的字段（描述/日期/链接）。</p>

<p>4) <strong>加入幂等/去重</strong>：同一天已发送就退出（避免重复轰炸）。</p>

<p>5) <strong>再逐步加技能</strong>：比如从“新闻推送”升级到“跟踪你的关注源 + 只推相关内容”。</p>

<p>这一套的关键是：<strong>先让系统进入稳定运行状态</strong>，而不是一上来追求大而全。</p>

<h2>4. OpenClaw 能做哪些场景？（从轻到重）</h2>

<h3>4.1 信息获取与整理</h3>

<ul>
<li>每日 AI/科技新闻推送（可指定来源、语言、数量、格式）</li>
<li>监控 RSS/博客更新（发现新文章就提醒）</li>
<li>追踪某个领域的关键词（模型发布、投融资、政策）</li>
</ul>


<h3>4.2 沟通与会议辅助</h3>

<ul>
<li>语音消息自动转写 + 生成纪要</li>
<li>多轮对话里的 TODO 提取与跟踪</li>
<li>帮你写邮件/公告/总结，统一口吻</li>
</ul>


<h3>4.3 工程与开发工作流</h3>

<ul>
<li>代码库问答、PR 说明、变更总结</li>
<li>自动生成文档/模板（比如周报、复盘、技术方案）</li>
<li>结合 GitHub CLI 做 issue/PR 维护（在权限允许时）</li>
</ul>


<h3>4.4 你的“个人自动化中枢”</h3>

<ul>
<li>定时行情（BTC/黄金/宏观指标）</li>
<li>定时提醒（喝水、会议前提醒、月底结算）</li>
<li>把零散工具串成稳定流程（抓取→处理→分发）</li>
</ul>


<h3>4.5 两个“最像生产力”的 Demo（建议你自己也这么配）</h3>

<p><strong>Demo 1：每日新闻推送（带去重）</strong></p>

<ul>
<li>触发：每天 10:00</li>
<li>动作：检索过去 24h 的 AI/科技新闻 → 按固定模板输出 10 条 → 发送到钉钉/Telegram</li>
<li>关键点：写入 <code>last_date</code>/<code>last_hash</code> 做幂等；发送失败有退避重试</li>
</ul>


<p><strong>Demo 2：语音消息→转写→直接回复</strong></p>

<ul>
<li>触发：你在聊天里发一条语音</li>
<li>动作：自动下载语音文件 → 转码（如 AMR/SILK→WAV）→ Whisper 转写 → 把转写文本当作“用户输入正文”让 Agent 回复</li>
<li>关键点：如果只把转写当作“附件描述”，很多 Agent 会把它当噪声忽略；要注入到正文里。</li>
</ul>


<h2>5. 一些实践建议（把它用成生产力，而不是玩具）</h2>

<p>1) <strong>先从一个强需求开始</strong>：例如“每天 10 点新闻推送”。从 0 到 1 跑通，价值立刻可见。</p>

<p>2) <strong>格式标准化</strong>：输出要固定模板，后面才能自动化复用。</p>

<p>3) <strong>幂等与去重</strong>：定时推送必须有“今天已发则退出”的逻辑。</p>

<p>4) <strong>给 Agent 明确的权限边界</strong>：哪些能访问、哪些不能执行，越早设定越省心。</p>

<p>5) <strong>把它当成一个长期系统</strong>：日志、状态文件、失败重试、降级策略都要有。</p>

<h2>6. 总结</h2>

<p>OpenClaw 的价值在于：它让 Agent 具备“能接入你真实工作流、能长期稳定运行、能安全执行工具”的工程底座。</p>

<p>当你不再把 AI 当成一次性问答，而是当成一个可以持续协作的“数字员工/助理”，你需要的就不是一个聊天窗口，而是一套运行时——这就是 OpenClaw 为什么会出现。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[2026 年 AI 最新进展]]></title>
    <link href="https://www.rowkey.cn/blog/2026/02/26/ai-progress-2026/"/>
    <updated>2026-02-26T16:00:00+00:00</updated>
    <id>https://www.rowkey.cn/blog/2026/02/26/ai-progress-2026</id>
    <content type="html"><![CDATA[<p>截至文章发布时间（2026-02-26），2026 年 AI 的关键变化不再是“又出了一个更强的模型”，而是 <strong>多模态内容生成、Agent 工程化、可交付系统</strong> 这三件事在同一时期快速叠加，让 AI 从“能演示”走向“能交付”。</p>

<p>这篇文章不做流水账式盘点，而是选 3 个热度高、信号明确的事件作为锚点：<strong>Seedance 2.0（视频）</strong>、<strong>OpenClaw（Agent 系统）</strong>、<strong>Genie3（世界模型/交互式生成）</strong>。基于这些事件，再抽象出一套更可复用的产品化方法论：怎么把 AI 能力沉到工程系统里，做成长期可运营的生产力。</p>

<!-- more -->


<h2>1. 三个高热度事件（截至 2026-02-26）</h2>

<h3>1.1 Seedance 2.0：视频生成开始对齐“工业交付”和“导演级可控”</h3>

<p>Seedance 2.0 的信号意义不在于“又一个视频模型”，而在于它把注意力放在 <strong>可控性与交付链路</strong>：</p>

<ul>
<li>统一的多模态音视频联合生成架构，支持文字/图片/音频/视频输入</li>
<li>强调运动稳定性、物理规律还原、原生音画同步（视听体验）</li>
<li>面向广告/影视/社媒营销场景的链路适配：输出质量对齐工业交付标准、降低成本、提升效率</li>
</ul>


<p>它代表视频生成的竞争从“能生成”走向“能按需求生成、能被工作流接住、能进入生产链路”。</p>

<p>数据来源：
- <a href="https://seed.bytedance.com/zh/seedance2_0">https://seed.bytedance.com/zh/seedance2_0</a></p>

<h3>1.2 OpenClaw 出圈：Agent 从“能力展示”走向“可运营系统”</h3>

<p>OpenClaw 的热度值得作为一个产品化信号来理解：它并不是提出了新模型，而是把一套 Agent 工程结构做成了可运行、可迭代、可维护的系统形态（通道、自动化、工具操作、长任务执行等）。</p>

<p>其核心价值不在“模型更聪明”，而在于把 AI 能力组织成了工程系统所需要的形状：可配置、可观测、可回放、可重试、可治理。</p>

<p>（公开报道提及 OpenClaw/Clawdbot 的现象与影响）</p>

<p>数据来源：
- <a href="https://www.news.cn/world/20260203/a173cb66c98a4b1bb551d588fd2f0209/c.html">https://www.news.cn/world/20260203/a173cb66c98a4b1bb551d588fd2f0209/c.html</a></p>

<h3>1.3 Genie3：世界模型与可交互生成进入“工具化”阶段</h3>

<p>除了内容生成与 Agent，2026 年一个值得关注的方向是：模型不仅生成内容，也在尝试生成“可交互环境”。公开报道提到，基于世界模型 Genie 3 的工具向公众开放，用户可以通过自然语言描述创建并探索可交互的三维虚拟世界。</p>

<p>它的信号意义在于：生成式 AI 的产品形态，开始从“出一段内容”走向“生成一个可探索/可操作的环境”，为游戏、仿真、训练与数字孪生等方向带来新变量。</p>

<p>数据来源：
- <a href="https://www.news.cn/world/20260203/a173cb66c98a4b1bb551d588fd2f0209/c.html">https://www.news.cn/world/20260203/a173cb66c98a4b1bb551d588fd2f0209/c.html</a></p>

<hr />

<h2>2. 基于事件抽象：从模型到产品化的方法论</h2>

<p>这三个事件看似分散，但背后其实收敛成同一套规律：<strong>把 AI 当作工程系统的一部分，而不是一个会聊天的黑盒</strong>。</p>

<h3>2.1 可控性优先：从“生成效果”走向“可交付结果”</h3>

<p>Seedance 2.0 强调“导演级操控与工业交付”，OpenClaw 强调“能跑、能闭环”，共同指向一个结论：</p>

<ul>
<li>重要的不再是“偶尔很强”，而是“稳定在预算和 SLA 内完成任务”</li>
<li>重要的不再是“单次结果”，而是“端到端交付成本”</li>
<li>重要的不再是“输出”，而是“过程可约束、可纠错、可回放”</li>
</ul>


<p>工程上对应的抓手一般是：结构化输出、工具调用、失败模式分析、回放与重试。</p>

<h3>2.2 先 Workflow，后 Agent：把智能放在流程关键节点</h3>

<p>OpenClaw 这类系统能跑进真实环境，一个关键原因是：它更像“可维护工作流 + 智能节点”的组合，而不是“把所有步骤都交给一个大模型”。</p>

<p>更稳的落地路径是：</p>

<ul>
<li>先把流程打通：触发、采集、处理、分发、回执、追踪</li>
<li>再把 Agent 放在关键节点（判断/生成/归纳/编排）</li>
<li>逐步扩大边界，而不是一开始就赌“全自动超级 Agent”</li>
</ul>


<h3>2.3 配置即契约：把不确定性关进笼子</h3>

<p>当系统要长期运行、并且会遇到重试、定时、跨系统同步时，最重要的不是“提示词更强”，而是把关键约束写成契约并强制执行：</p>

<ul>
<li>输出格式契约（字段、模板、是否只发一条）</li>
<li>幂等契约（last_date / last_hash / url_hash 去重键）</li>
<li>失败与重试策略（退避、次数上限、同文本重发）</li>
<li>权限边界（哪些工具可用、哪些动作需要人工确认）</li>
</ul>


<p>没有契约，就没有可维护性；没有可维护性，就没有规模化。</p>

<h3>2.4 多模态落地的关键是“管道”，不是“炫技”</h3>

<p>Seedance 2.0 这类模型强调工业交付，本质上对工程提出了更硬的要求：格式、编码、超时、重试、质量评估、审计追踪。</p>

<p>多模态真正落地通常离不开：</p>

<ul>
<li>输入输出规范化（格式、时长、分辨率）</li>
<li>资源与时间预算（超时控制、排队策略）</li>
<li>可追溯（素材、prompt、参数、版本）</li>
<li>质量评估与抽检（对齐业务 KPI，而不是论文指标）</li>
</ul>


<h3>2.5 世界模型的产品化前提：可交互 + 可控 + 可评估</h3>

<p>Genie3 这类方向如果要产品化，除了“能生成”，还需要三件事：</p>

<ul>
<li>可交互：环境不是静态内容，而是可探索、可操作</li>
<li>可控：约束生成边界，保证一致性与稳定性</li>
<li>可评估：定义指标（任务成功率、物理一致性、用户体验等），能迭代优化</li>
</ul>


<p>这也再次回到同一个核心：能力提升很重要，但决定能否落地的，往往是工程系统如何承接它。</p>

<hr />

<h2>结语</h2>

<p>截至 2026-02-26，我更愿意把今年 AI 的主线称为“工程化的胜利”：</p>

<ul>
<li>内容生成在对齐工业交付</li>
<li>Agent 在对齐闭环执行与可运营性</li>
<li>世界模型在尝试走向交互式工具化</li>
</ul>


<p>接下来一年，决定胜负的可能不是“谁的模型强 3 分”，而是：</p>

<blockquote><p>谁能把 AI 做成一套可维护、可扩展、可协作、可审计的工程系统。</p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[AI大事记@2025]]></title>
    <link href="https://www.rowkey.cn/blog/2025/12/27/ai-2025/"/>
    <updated>2025-12-27T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2025/12/27/ai-2025</id>
    <content type="html"><![CDATA[<p>接近2025年底，概括总结了一下2025这一年的一些AI关键事件。</p>

<!-- more -->


<table>
<thead>
<tr>
<th style="text-align:left;"> 时间 </th>
<th style="text-align:left;"> 事项 </th>
<th style="text-align:left;"> 备注 </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"> <strong>2025.12.16</strong> </td>
<td style="text-align:left;"> <strong>OpenAI GPT-Image-1.5</strong> </td>
<td style="text-align:left;"> 不管是从零生成，还是对图片进行局部编辑，更接近你脑子里想的那个结果；并且生成速度最高可达 4 倍提升。实测：比配套Nano Banana Pro强。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.12.11</strong> </td>
<td style="text-align:left;"> <strong>OpenAI GPT 5.2</strong> </td>
<td style="text-align:left;"> GPT-5.2 能够在真实复杂工作流程中高效协作，从代码分析、财务建模、工程设计，到研究论文分析、实验结果推理，都能提供高质量辅助。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.11.21</strong> </td>
<td style="text-align:left;"> <strong>Google Nano Banana Pro</strong><br><em>(aka Gemini 3.0 Pro Image)</em> </td>
<td style="text-align:left;"> 全球首个“推理至像引擎”，不仅是绘画，更是理解物理规律与空间逻辑。作为 Nano Banana 的旗舰升级版，它像人类一样“思考”和“规划”场景，生成前所未有的逻辑一致性，完美文本和高分辨率的视觉作品。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.11.16</strong> </td>
<td style="text-align:left;"> <strong>Google Gemini 3.0 pro</strong> </td>
<td style="text-align:left;"> 全面高刷。同时发布Antigravity 编程IDE，生成式前端UI能力遥遥领先，可以快速实现各种交互式H5应用。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.11.12</strong> </td>
<td style="text-align:left;"> <strong>OpenAI GPT 5.1</strong> </td>
<td style="text-align:left;"> 将GPT-5 和 GPT-5 Mini 合并为一个能适应问题难度的自适应调整思考用量的模型。相比GPT5，语气更亲切、更幽默，更善于遵循指令。整体性能介于GPT-5 和 GPT-5 Mini 之间。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.10.16</strong> </td>
<td style="text-align:left;"> <strong>Google Veo 3.1</strong> </td>
<td style="text-align:left;"> 主打更强叙事与音频控制、音乐韵律与多参考图拼接，接入 Gemini API与Vertex AI。Flow与Gemini可用。可合成多人物场景、语音同步，片段最长约146秒；规格至1080p/24fps。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.10.01</strong> </td>
<td style="text-align:left;"> <strong>OpenAI Sora2</strong> </td>
<td style="text-align:left;"> 非常好的物理世界理解能力，同时推出了Sora APP，定位AI短影音。号称视频领域的GPT-3.5时刻。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.09.09</strong> </td>
<td style="text-align:left;"> <strong>字节发布 Seedream 4.0</strong> </td>
<td style="text-align:left;"> 定位“生成与编辑一体化”专业工具。编辑能力强甚至部分超过nano banana。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.27</strong> </td>
<td style="text-align:left;"> <strong>Google Nano Banana</strong><br><em>(aka Gemini 2.5 Flash Image)</em> </td>
<td style="text-align:left;"> 具有极好的编辑能力，能够多图融合、强一致性，替代GPT4o成为图片编辑的王者。SOTA of 图像模型。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.26</strong> </td>
<td style="text-align:left;"> <strong>通义万相 Wan2.2-S2V-14B</strong> </td>
<td style="text-align:left;"> 一个可以跑动的14B视频模型，仅需一张图片和一段音频，即可生成面部表情自然、口型一致、肢体动作丝滑的电影级叙事/人视频。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.26</strong> </td>
<td style="text-align:left;"> <strong>即梦AI智能多模</strong> </td>
<td style="text-align:left;"> 传统的拼接是两个团队，各干各的，最后硬拼在一起。而堆叠多帧是一个全真全参数带上下文的团队，大家各让一步处理，因此能做到四宽的一致性。堆叠多帧背后的底层逻辑：即一体的全局考虑。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.21</strong> </td>
<td style="text-align:left;"> <strong>GenSpark AI Designer</strong> </td>
<td style="text-align:left;"> 一款革命性的AI设计工具，能够一键生成完整的多屏设计方案，涵盖Logo、包装、网站设计等多个领域，极大地降低了设计门槛。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.20</strong> </td>
<td style="text-align:left;"> <strong>DeepSeek V3.1</strong> </td>
<td style="text-align:left;"> 代码能力极高，但文本能力并未提高，甚至有某些下降。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.19</strong> </td>
<td style="text-align:left;"> <strong>Qwen-Image-Edit</strong> </td>
<td style="text-align:left;"> 全能图像编辑。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.08</strong> </td>
<td style="text-align:left;"> <strong>OpenAI GPT5</strong> </td>
<td style="text-align:left;"> 一个统一的系统，包含一个能够解决大多数问题的智能快速模型、一个能够解决复杂长问题的深度推理模型，以及一个实时语音器。可以根据对话类型、复杂性、工具需求判断意图并快速决定使用哪个模型。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.06</strong> </td>
<td style="text-align:left;"> <strong>OpenAI 开源模型</strong><br>GPT-oss-120b和GPT-oss-20b </td>
<td style="text-align:left;"> 性能与兼容性兼具，非英文表现不好。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.05</strong> </td>
<td style="text-align:left;"> <strong>Google Genie3</strong> </td>
<td style="text-align:left;"> 新一代生成式世界模型——Genie3。根据文本创造一个可以实时交互的世界。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.08.04</strong> </td>
<td style="text-align:left;"> <strong>Qwen-image</strong> </td>
<td style="text-align:left;"> 通义千问团队开源的首个图像生成基础模型，在解决传统文生图模型文字渲染难题上实现了突破性进展，尤其在中文场景下表现突出。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.07.23</strong> </td>
<td style="text-align:left;"> <strong>Qwen3-coder</strong> </td>
<td style="text-align:left;"> 拥有卓越的代码Agent能力，在Agentic Coding、Agentic Browser-Use 和 Foundational Coding Tasks 上均取得了开源模型的 SOTA 效果。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.07.12</strong> </td>
<td style="text-align:left;"> <strong>Kimi K2</strong> </td>
<td style="text-align:left;"> 将模型权重代码全量开源。大模型竞技场LMArena排行榜中，Kimi K2综合排名斩获全球第五，在开源大模型中位居全球第一。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.07.09</strong> </td>
<td style="text-align:left;"> <strong>xAI Grok 4</strong> </td>
<td style="text-align:left;"> 极其激进的快速迭代。推出 Grok 4 Heavy，引入多智能体架构，针对复杂科研任务优化，算力规模再创新高。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.07.05</strong> </td>
<td style="text-align:left;"> <strong>Gemini CLI</strong> </td>
<td style="text-align:left;"> 开源命令行界面工具，它将谷歌强大的 Gemini AI 模型直接集成到开发者常用的终端环境中，更擅长服务于编程。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.07.02</strong> </td>
<td style="text-align:left;"> <strong>Flux图像模型</strong><br>Kontext Dev模型正式开始 </td>
<td style="text-align:left;"> 强一致性、强理解力。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.06.24</strong> </td>
<td style="text-align:left;"> <strong>Imagen4</strong> </td>
<td style="text-align:left;"> 显著改善文本渲染效果，进一步提升了文本转图像的生成质量。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.06.22</strong> </td>
<td style="text-align:left;"> <strong>Gemini 2.5 Flash/Pro</strong> </td>
<td style="text-align:left;"> </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.06.11</strong> </td>
<td style="text-align:left;"> <strong>Seedance1.0</strong> </td>
<td style="text-align:left;"> 字节跳动推出的一款高性能和推理极致的视频语言生成模型。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.05.23</strong> </td>
<td style="text-align:left;"> <strong>Claude code</strong> </td>
<td style="text-align:left;"> 智能化辅助写代码工具，旨在帮助开发者通过自然语言命令理解、浏览和修改整个代码库，前端编程领域无人能敌。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.05.21</strong> </td>
<td style="text-align:left;"> <strong>Veo3</strong> </td>
<td style="text-align:left;"> 首个可生成视频背景音效模型，体会画面感、配合感、生成人物对话，物理模拟与口型同步表现优异。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.04.29</strong> </td>
<td style="text-align:left;"> <strong>Qwen3</strong> </td>
<td style="text-align:left;"> 国产最强开源模型。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025年5月</strong> </td>
<td style="text-align:left;"> <strong>Loverr设计Agent</strong> </td>
<td style="text-align:left;"> 2025年7月28日正式上线。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.04.05</strong> </td>
<td style="text-align:left;"> <strong>Meta Llama 4</strong> </td>
<td style="text-align:left;"> Meta发布开源模型 Llama 4（包含Scout和Maverick版本）。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.03.26</strong> </td>
<td style="text-align:left;"> <strong>GPT4o改图能力</strong> </td>
<td style="text-align:left;"> 一致性能力好，响应慢。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.03.06</strong> </td>
<td style="text-align:left;"> <strong>通用Agent</strong><br>Manus, GenSpark, Flowith </td>
<td style="text-align:left;"> </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.02.17</strong> </td>
<td style="text-align:left;"> <strong>xAI Grok 3</strong> </td>
<td style="text-align:left;"> Elon Musk 发布 Grok 3，宣称其为“地球上最聪明的AI”。 </td>
</tr>
<tr>
<td style="text-align:left;"> <strong>2025.01.20</strong> </td>
<td style="text-align:left;"> <strong>DeepSeek R1</strong> </td>
<td style="text-align:left;"> 国产开源推理模型，媲美OpenAI o1。 </td>
</tr>
</tbody>
</table>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[《太白金星有点烦》读后感]]></title>
    <link href="https://www.rowkey.cn/blog/2025/08/25/taibaijinxing/"/>
    <updated>2025-08-25T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2025/08/25/taibaijinxing</id>
    <content type="html"><![CDATA[<p>最近利用出差在高铁和飞机上的时间，读完了《太白金星有点烦》这本书。总体感觉挺有意思的，作者用诙谐的笔法把现代职场政治、官僚主义与古典神话《西游记》完美融合，让人真觉得西游记是不是就是这么回事。当然，这些感觉之余也在时刻对照目前公司中是否有这些问题，所幸民营企业也不敢这么搞，万幸万幸。</p>

<!-- more -->


<h3>一、 内容梗概</h3>

<p>故事从<strong>太白金星（李长庚）</strong>的视角展开。在书中，原本宏大的“西天取经”不再是一场纯粹的弘扬佛法之旅，而是一项由天庭和西天联合开发、层层外包的<strong>“重点项目”</strong>。</p>

<ol>
<li><strong>项目经理李长庚：</strong> 李长庚被任命为西游项目的“策划人”和“协调员”。他的任务是确保玄奘一行人经历九九八十一难，且每一难都要有记录、有预算、有排场，还要兼顾各方势力的利益。</li>
<li><strong>职场琐事：</strong> 书中详细描写了李长庚如何处理那些令人头大的“行政工作”：如何给有背景的妖怪安排出场机会又不能真伤了取经人；如何跨部门沟通（天庭与西天的地盘之争）；如何报销差旅费；以及如何处理各种突发的公关危机。</li>
<li><strong>取经的真相：</strong> 随着项目的推进，李长庚发现所谓“九九八十一难”大多是人为安排的“走秀”。而在这背后，隐藏着更深层的权力斗争和资源分配。</li>
<li><strong>结局与悟道：</strong> 在经历了无数职场洗礼后，李长庚在项目结束时面临着“修成正果”的选择。他最终对权力和成仙有了全新的理解，完成了一种精神上的自我救赎。</li>
</ol>


<h3>二、 核心评价与书评</h3>

<h4>1. 绝佳的职场隐喻（“神仙也得写周报”）</h4>

<p>马伯庸最天才的地方在于他把<strong>“仙界”写成了“职场”</strong>。
*   <strong>层级森严：</strong> 佛祖和玉帝是大BOSS，菩萨和星君是中层领导，李长庚是资深项目经理。
*   <strong>潜规则：</strong> 没背景的妖怪一棒打死，有背景的妖怪被主人接走。书中将这种《西游记》原本的讽刺进一步具体化为：如何写汇报材料才能既掩盖错误又突出业绩。
*   <strong>读者的共鸣：</strong> 每一个打工人都能在李长庚身上看到自己——为了KPI奔波，在领导的暗示中揣摩意图，在繁琐的流程中消耗生命。</p>

<h4>2. 对《西游记》的解构与重组</h4>

<p>这本书不仅仅是恶搞，它对原著细节的挖掘极其深厚。
*   它解释了为什么有的关卡漏洞百出，为什么神仙的坐骑总是“不小心”走失。
*   通过李长庚的视角，作者重新审视了孙悟空、猪八戒等人的形象。孙悟空不再只是单纯的叛逆者，而是被纳入体制内、必须学会配合演出的“高级顾问”。</p>

<h4>3. 悲悯的底色与“修心”</h4>

<p>虽然表面上充满了幽默和讽刺，但书的内核是有些<strong>致郁且深刻</strong>的。
*   李长庚在算计了一辈子后，感到了一种深深的疲惫和荒诞感。
*   <strong>“超脱”：</strong> 最终李长庚的悟道，不是因为累积了多少功德，而是他看穿了这套体制的虚伪，选择回归自我的本真。这种从“入世”到“出世”的转变，给现代职场人提供了一种心理上的抚慰。</p>

<h4>4. 文字风格</h4>

<p>马伯庸的文字极其流畅，充满了“马式冷幽默”。他擅长用现代公文词汇去描述神仙对话，产生了一种强烈的反差萌。例如，把因果报应说成“利益分配”，把降妖伏魔说成“外勤任务”。</p>

<hr />

<h3>三、 总结：为什么要读这本书？</h3>

<ul>
<li><strong>如果你是职场人：</strong> 你会一边笑一边流泪，感叹“马伯庸是在我工位下装了监控吗？”</li>
<li><strong>如果你是西游迷：</strong> 你会惊叹于原著竟然还能被这样解读，每一个细节都严丝合缝。</li>
<li><strong>如果你想寻找慰藉：</strong> 它会告诉你，在繁杂的世俗规则中，如何保有一颗不被磨灭的初心。</li>
</ul>


<p><strong>一句话简评：</strong>
这是一部披着神话外衣的职场生存指南，也是一首写给所有疲惫灵魂的解脱之诗。它告诉我们：<strong>“成仙”不在于位次的高低，而在于能否在满地鸡毛的生活中，找回那个清醒的自己。</strong></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[DeepSeek简单分享]]></title>
    <link href="https://www.rowkey.cn/blog/2025/02/23/deepseek/"/>
    <updated>2025-02-23T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2025/02/23/deepseek</id>
    <content type="html"><![CDATA[<p>本文内容来自一次内部分享。主要是对目前非常火的DeepSeek的一些自己的认知和理解。</p>

<!-- more -->


<h2>DeepSeek是什么？</h2>

<p>DeepSeek是一个由中国公司推出的媲美ChatGPT o1能力的开源推理大模型，其中文能力更强，而且由于背后公司数据的特点，在金融方面具有优势。</p>

<p>这里所说的推理大模型是相对于之前的非推理模型，更加强化了推理、逻辑分析和决策能力，可以看做是把之前的CoT能力直接做到了模型里。</p>

<p>DeepSeek本身是包括V3和R1两个模型，参数都达到6000亿，也就是现在市面上很多人说的满血版。而DeepSeek开源的几个蒸馏版本的模型其实本质还是qwen和llama，只是用了R1的推理数据做了微调。</p>

<h2>DeepSeek生态位</h2>

<p>综合了各种榜单和一些评测，并基于公司实际使用的经验，对现在主流的大模型做了如下梯队排名：</p>

<p><img src="https://www.rowkey.cn/post_images/deepseek/dp_rank.png" width="450"/></p>

<p>在选择模型时需要注意：</p>

<ul>
<li>开源模型可以私有化部署提供无审查的服务</li>
<li>国内模型在中文上有优势</li>
</ul>


<p>通过这个梯度，也可以看到DeepSeek并不是能力最强的，但R1确实是国内最好的推理模型。而非推理模型国内的通义千问是能力最强的。这里需要提到的一点就是Kimi其实也和DeepSeek差不多同一时间推出了推理模型的，能力也没有差太多，但由于不是完全开源的，所以被DeepSeek给完全盖住了。</p>

<h2>DeepSeek为什么这么火?</h2>

<p>如第一部分所说，本质上DeepSeek是一个中国公司做到了O1水平并且开源了的推理大模型。具体来说，之所以它这么火有以下几点：</p>

<ul>
<li>ChatGPT o1出来后，给业界出了一道题，然后DeepSeek给解出来了，并且是以低成本的方式实现了，甚至还给开源了。</li>
<li>对于国内来说，由于zz原因，很长一段时间是无法使用国外的第一梯队大模型的。所以，有了DeepSeek这种能用的模型，自然是迅速出圈。</li>
<li>对于国外来说，则是高估了领先中国的速度，低估了中国的追赶速度。</li>
</ul>


<h2>为什么是DeepSeek?</h2>

<p>国内外很多大模型厂商，为什么是DeepSeek做出来了呢？</p>

<ul>
<li>DeepSeek背后是幻方量化，这家公司号称多内私募量化四巨头，非常赚钱，有一年就捐了3个亿做慈善。虽然DeepSeek是相对独立的一家公司，但其中的关联肯定小不了，所以大概率是不缺钱的，也不是奔着赚钱去的。因此，可以类似高校一样单纯的做研究。与之相比，Kimi就有商业化的诉求，所以能看到Kimi在大量的投放广告。</li>
<li>DeepSeek的招人门槛很高，虽然创始人是浙大的，但团队成员基本上是清北级别的。</li>
<li>DeepSeek曾号称有国内最多的A100显卡。</li>
<li>创始人梁文峰是很有技术追求的一个人，不管是量化还是大模型，据各种报道，都是自己亲身在一线写代码、写论文的。</li>
<li>我自己的认知，其实OpenAI推出o1后，大家都在研究，都在探索，方法也都有区别，DeepSeek这次做出来是有一点运气成分。</li>
</ul>


<p>这里还想提的是，春节期间所谓的国运一说，我觉得如果DeepSeek在不长的时间能追上甚至超过o3，那真的可以说国运了。</p>

<h2>DeepSeek的创新</h2>

<p>DeepSeek由于受限于显卡的性能（H800），通过工程优化上的创新提升了算法效率，从而也大大降低了成本。</p>

<ul>
<li>DeepSeekMoE：采用了大量细粒度的专家，因此推理时，能大幅降低成本。</li>
<li>负载均衡优化：采用Auxiliary-loss-free算法提高了MoE路由的效率。</li>
<li>内存优化：重计算、使用CPU内存和参数共享</li>
<li>通信优化：DualPipe</li>
<li>计算优化：FP8混合精度训练</li>
<li>其他：MLA(多头潜在注意力)、MTP（多Token预测）、GPRO（强化学习算法）等</li>
<li>NSA：原生稀疏注意力，长文本能力</li>
</ul>


<h2>使用</h2>

<p>推理模型是有使用场景的，适合需要深度思考的场景，如设计、审查、推理、复杂计算等。如果让其做一些简单的任务，如实现代码，可能会思考来思考去，反而降低效率。结合推理模型+非推理模型是现在一种常用的方式，如DeepSeek R1 + Claude 3.5 sonnet就是使用R1来做方案设计，使用Claude来写代码。</p>

<p>不同于之前的非推理模型，推理模型的提示词跟侧重于描述清楚任务目标，过多的引导反而是干扰。</p>

<p>此外，通过DeepSeek对蒸馏模型的证明，一些行业模型也可以通过DeekSeek R1的推理数据来微调，实现蒸馏的效果。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[美国AI之旅]]></title>
    <link href="https://www.rowkey.cn/blog/2024/06/05/usa-ai/"/>
    <updated>2024-06-05T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2024/06/05/usa-ai</id>
    <content type="html"><![CDATA[<p>5月底去了一趟旧金山，和一些华人AI科学家进行了交流，也参加了旧金山由GPTDao和微软联合举办的GenAI大会。这里输出一些收获。</p>

<!-- more -->


<ol>
<li>一个华人科学家分享他们团队在做消费级设备（车载、手机）大模型的创业。苹果最近发布的Apple Intelligence也是类似的思路。之前陈天奇团队做的mlc-llm同样是在做这样的事情，再结合特斯拉的FSD也是基于Transformer的自动驾驶决策，这个方向还是很有机会的。但国内貌似很少听到类似的项目。</li>
<li>Amino: 一家华人创办的VC公司。看到他们投的一家针对美国移民多这一特点的电商平台，每个国家的人进去看到都是来自这个国家的商品，这个估计只有美国是合适的。另外，他们也分享了目前硅谷还是创业者导向的，一个好的创业项目，需要投资人去争取。这家公司的创始人有个抖音号叫硅谷李师傅，在持续分享硅谷的一些东西。</li>
<li>Meta AI：分享了Meta大模型方面的进展，印象比较深刻的是实时图像生成，可以边输入提示词，边生成图像。网址：<a href="https://www.meta.ai/?icebreaker=imagine">https://www.meta.ai/?icebreaker=imagine</a></li>
<li>Tesla：分享了他们在自动驾驶方面的进展。特斯拉的FSD不同于目前主流自动驾驶技术的是使用了基于Transformer的驾驶决策，通过使用保险公司大量驾驶分数好的司机的数据来训练这个模型，对比Waymo基于激光雷达，成本会低非常多。但受限于保密的原因，其他有干货的东西感觉不是很多。</li>
<li>Nvidia: 分享了他们正在开发的多模态大模型。自己这次发现英伟达虽然主要精力在芯片，但其实也在大量地做各种AI模型层、应用层的尝试，包括后来在GenAI会议上Jim Fan讲的具身智能，这里有这个分享的总结：<a href="https://mp.weixin.qq.com/s/DF0GBx99vodq0dYM98iRFA%E3%80%82">https://mp.weixin.qq.com/s/DF0GBx99vodq0dYM98iRFA%E3%80%82</a></li>
<li>听了Google科学家讲述Google在多模态大模型方面的进展。印象比较深的一点，就是现在业界对小公司的包容度大，对大公司包容度小，因此经常会放大谷歌的问题，某种维度上是不公平的。</li>
<li>硅谷的人才流动很频繁，没有什么绝对的技术壁垒，而且硅谷是没有竞业协议的。所以，OpenAI的优势并没有那么绝对。目前谷歌已经从OpenAI挖回来了不少大模型人才。</li>
<li>旧金山GenAI Summit 2024

<ul>
<li>硅谷这边各种小的应用都能支撑起一家创业公司，比如会场在用的otter.ai就是实时记录会议内容，和钉钉、飞书的闪记的功能是一样的。</li>
<li>华人团队做的天机阁AI测算，这个是我们公司比较关注的一个赛道，天机阁的应用体验做的很一般，但测算的体验确实不错。应该是有自己的专有数据的。</li>
<li>Groq的AI加速芯片：在芯片层面提速的AI服务。这个之前贾杨青是质疑过其成本的。</li>
<li>贾杨青的Lepton AI是在做AI云原生，能够快速部署大模型应用。</li>
<li>合成数据对AI发展的重要性：随着现实数据逐渐被用完，需要大量的合成数据来训练模型，这方面目前还存在着很多挑战。</li>
</ul>
</li>
<li>贾杨青分享中提到的理查德·萨顿教授的作品《痛苦的教训》中的一句话："从70年的人工智能研究中可以得出的最大教训是，利用计算的通用方法最终是最有效的，而且差距很大。"

<ul>
<li><strong>通用方法</strong>：在人工智能研究中，通用方法指的是那些可以应用于广泛问题的算法和技术，而不是专门为特定问题设计的解决方案。通用方法通常具有更广泛的适用性和更长的生命周期。</li>
<li><strong>利用计算</strong>：这一点强调了计算能力的重要性。在过去的几十年中，计算机的处理能力和速度有了巨大的提升，这使得复杂的算法和大规模数据处理成为可能。</li>
<li><strong>最有效的</strong>：萨顿教授指出，通用方法结合强大的计算能力，往往比特定问题的专用方法更有效。也就是说，使用计算能力来推动通用算法的发展，能够在更大范围内取得成功，并且效果更显著。</li>
<li><strong>差距很大</strong>：这一点强调了效果上的显著差异。萨顿教授认为，通用方法相对于专用方法，其优势不仅仅是略胜一筹，而是有着明显的、显著的效果提升。</li>
<li>总的来说，萨顿教授的这句话提醒我们，在人工智能领域，应该注重发展那些可以广泛应用的通用算法，并充分利用现代计算技术的力量。这样的方法不仅更为高效，而且在各种不同的应用场景中都能表现出色。</li>
</ul>
</li>
<li>美国对新事物的接受度没有那么高，因此Tesla在美国反而没有国内常见。不过，FSD在美国已经全面推行。打Uber的时候司机开启了FSD，整体感觉还是很丝滑的。</li>
<li>美国的油价挺高的，所以日本车在美国占用率很高，随处可见的也是丰田、本田这些车。</li>
<li>Google的Waymo在旧金山随处可见，有同行的朋友有邀请码体验了一下，驾驶没有任何问题，基本和打普通出租车没有任何区别。但其改造一辆车的成本非常昂贵，后来听朋友说，由于特斯拉的RoboTaxi即将发布，Waymo的很多人都离职了。特斯拉的FSD目前看来才是未来的自动驾驶发展方向。</li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CTO都必须是程序员出身吗？为什么架构师做不了CTO？]]></title>
    <link href="https://www.rowkey.cn/blog/2024/04/08/codertocto/"/>
    <updated>2024-04-08T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2024/04/08/codertocto</id>
    <content type="html"><![CDATA[<p>这是来自Quora上的一个问题：<a href="https://www.quora.com/Is-it-required-to-be-a-developer-coder-to-become-a-CTO-Why-cant-an-architect-become-a-CTO">Is it required to be a developer/coder to become a CTO? Why can&rsquo;t an architect become a CTO.</a>
下面是里面的最佳答案。自己比较认同其中的观点，CTO确实是需要有编程背景的，而真正意义上的软件架构师也是具有编程背景的，所以也是可以成为CTO的。</p>

<!-- more -->


<hr />

<p>作为一家创业公司的CTO，你需要了解以下几点：</p>

<p>（1）从上到下对整个技术栈有一个全面的了解，包括每一层的替代方案和取舍权衡。</p>

<p>（2）如何以一种能够给你想要招聘的工程师留下深刻印象的方式进行严肃编程。</p>

<p>（3）如何自我学习你需要了解的技术知识，以及如何在至少100码外就能嗅出技术上的废话。</p>

<p>（4）如何领导工程团队，如何管理工程团队（以及两者之间的区别是什么，因为它们非常不同）。</p>

<p>（5）如何可靠地估计实现其他C级领导愿景所需的工作量。如何向他们沟通可能的权衡，并如何经常从一个过于模糊或过于具体的起点找到真正的需求。</p>

<p>（6）如何向从资深的高级工程师到极其愚蠢的媒体等各方面代表公司的技术愿景。</p>

<p>（7）如何保护你的团队免受不必要的变化，并如何带领他们以及公司其他部分经历必要的变革。</p>

<p>（8）如何指导工程师关于他们的成长和职业目标，无论是作为个体还是团队成员。</p>

<p>（9）如何发现可能的技术和公司问题，并在它们影响工程团队的动力之前清除它们。</p>

<p>（10）如何保持工程团队的持续发展，这可能意味着扮演IT角色，充当工程师，或周末架子搭建者（原文是weekend shelf-builder，不太理解，可能指的是自我驱动去做一些事情的意思）。</p>

<p>你如何达到这个目标？需要你通过在创业公司的工程团队持续工作并向各种听众做技术演讲。从我看着当初我的CTO说“我希望有一天能做到这个位置”，到我准备好自己做这件事，我花了10年的时间。</p>

<p>编辑：既然这个问题有所融合且稍微有所变化，我想直接回应它。</p>

<p>CTO确实可以是一名架构师，但软件架构师是一名开发者。</p>

<p>有些公司有他们称之为“架构师”的人，但他们实际上从未真正建立过系统。他们在销售会议中在白板上画大框和线条，然后就走开了。</p>

<p>我们在Sun公司有一个词来称呼这些人，我们称他们为“市场技术人员（Marketechts）”。并且，一个市场技术人员会成为一个糟糕的CTO，因为他们谈论和思考的是广泛的概括，而不是完成工作的真正细节。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[不同的CTO角色 by Werner Vogels (Amazon CTO)]]></title>
    <link href="https://www.rowkey.cn/blog/2024/04/07/different-cto/"/>
    <updated>2024-04-07T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2024/04/07/different-cto</id>
    <content type="html"><![CDATA[<p>这是来自开源项目<a href="https://github.com/kuchin/awesome-cto">awesome-cto</a>的一篇文章，也是自己曾有过的疑问。自己目前担任CTO这个岗位已经6年多了，现在对这个问题的认知：其实CTO这个角色的职责还是要根据CEO的期望来定。初创团队CTO一般就是一个高级开发工程师，随着团队规模增大，会逐渐转换为架构师、技术经理，最后有些CTO会去负责基础技术研究，有些CTO则统管整个研发团队，还有一些则会去管理部分业务。不管如何，这个职责还是要看CEO心里的期望是什么。</p>

<!-- more -->


<hr />

<p>我曾经为一个关于企业创新中首席技术官角色的小型讨论会准备演讲稿，我再次意识到围绕CTO角色存在相当多的混淆。讨论CTO角色时总是首先遇到的问题是，没有一个公认的定义来说明CTO的实际工作内容。这个角色根据公司的类型以及技术在公司中的角色非常不同。</p>

<p>一段时间以前，我做了一些挖掘，研究CTO角色的历史以及如何最好地分类它们。我在这里发布，因为它可能具有普遍的兴趣。一些我使用的来源在这个笔记的末尾。</p>

<p>当Edge的创始人约翰·布罗克曼采访内森·默夫沃德时，他的第一个问题是“什么是CTO”，对此内森回答说：</p>

<p>“我哪知道。你知道的，当比尔和我讨论我接受这份工作时，有一刻他说，好的，那些成功的CTO的杰出例子是什么。大约五分钟后我们决定，好吧，肯定有一些，但我们并没有准确知道谁是伟大的CTO，因为许多实际上是伟大的CTO们并没有那个头衔，至少一些有那个头衔的人可以说并不擅长它。</p>

<p>我的工作是在微软思考未来的技术。如果你想拥有一个伟大的未来，你必须开始在现在思考它，因为当未来到来时，你将没有时间。”</p>

<p>第一个CTO在八十年代末出现。许多公司开始利用其研发实验室交付的结果，这些实验室的主管被提升到可以使用技术为公司提供战略优势的位置。这个角色发展成了非常不同的职位，有几种方式可以对它们进行分类。有充分的理由遵循任何一个分类模型，但我相信汤姆·贝瑞的四象限提供了关于什么使CTO成功的最佳框架：</p>

<ul>
<li>基础设施管理者 - 在CIO的角色变得过于复杂的公司中，CTO承担了基础设施和IT运营的责任：数据中心运营、网络运营、应用开发和维护、安全性和其他直线功能。CIO保留了如何在组织内实际使用技术的责任。这主要是在IT处于纯支持角色的传统业务中使用的模型。</li>
<li>技术愿景家和运营经理 - 这种模式通常在.com和其他以信息技术为关键因素实施商业战略的技术导向公司中发现。CTO负责确定如何使用技术来实施商业战略。这是角色的“技术愿景家”方面。但随后，CTO负责实际集成和运行技术，即“运营经理”的角色。在这种模式中，CTO通常是业务的共同创始人或第一批雇员之一。</li>
<li>面向外部的技术专家 - 我们经常在使用技术为客户和合作伙伴提供产品和服务的公司中看到这种模型；CTO是客户和内部开发之间的中介，并且是产品组合开发的主要影响者。CTO与关键客户保持着不断的联系，并显著参与市场研究。一些较大的软件公司成功使用了这种模式，拥有多个CTO，他们是经验丰富的技术专家，其主要任务是成为客户的桥梁。一些中间件领域的软件公司的CTO还将客户联系描述为他们的主要活动。</li>
<li>大思考者 - 在这个模型中的CTO主要花时间评估如何在内部使用技术来开发新的商业模式和业务线，以及如何预先阻止竞争对手使用技术来颠覆市场。这个CTO的责任通常包括高级技术、竞争分析、技术评估、原型实验室、合作伙伴关系、计划和架构标准。</li>
</ul>


<p>在前两个模型中，CTO直接管理一个工程部门，他/她在组织中的影响力主要通过他们自己组织中的技术开发来施加。我遇到过管理拥有500 - 1000名工程师或更多的部门的CTO。</p>

<p>在最后两个模型中，CTO扮演的角色需要他/她影响其他部门执行新的方向。为了保证这种影响力水平，CTO通常是执行团队的一部分或接近执行团队，通常向CEO汇报。CTO确实监督一个小团队（通常根据公司的大小为10-50名工程师），该团队充当高风险技术方向的孵化器。</p>

<p>以下是一些参考链接。</p>

<ul>
<li>Aspatore Inside the Minds Series, <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FInside-Minds-Technology-Officers-Peoplesoft%2Fdp%2F1587620561&amp;tag=allthingsdist-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325">Leading CTOs</a></li>
<li><a href="http://www.markminevich.com/">Mark Minevich</a>, <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FCTO-Job-Manual-Leadership-Technology%2Fdp%2F1587623676&amp;tag=allthingsdist-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325">The CTO Handbook</a></li>
<li><a href="http://cabotinc.com/berray.html">Tom Berray</a> and Raj Sampath, <a href="http://www.brixtonspa.com/Career/The_Role_of_the_CTO_4Models.pdf">the Role of the CTO: Four Models for Success</a></li>
<li><a href="http://ctonet.blogspot.com/">Roger Smith</a>, <a href="http://www.modelbenders.com/papers/CTOStrategy_SmithR.pdf">the Role of the Chief Technology Officer in Strategic Innovation, Project Execution, and Mentoring</a></li>
<li><a href="http://ctonet.blogspot.com/">Roger Smith</a>, <a href="http://www.ctonet.org/documents/5PatternsofCTO.pdf">5 Patterns of the Chief Technology Officer</a></li>
</ul>


<p>原文链接：<a href="https://www.allthingsdistributed.com/2007/07/the_different_cto_roles.html">https://www.allthingsdistributed.com/2007/07/the_different_cto_roles.html</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[如何使用AI生成长视频？]]></title>
    <link href="https://www.rowkey.cn/blog/2024/03/27/ai-video/"/>
    <updated>2024-03-27T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2024/03/27/ai-video</id>
    <content type="html"><![CDATA[<p>今年最火的AI技术应该是OpenAI在春节期间发布的Sora了。相比起其他视频生成产品就3、4秒的时长，Sora是碾压式的存在。但Sora没有对外开放，所以要生成长视频，暂时也没有其他完整的好的方案。综合各种资料来看，目前最可行的方案应该就是：写剧本/分镜——>生图——>生视频->视频拼接，本质上就是通过多个短时长的视频组成一个完整的长视频。下面就详细讲述一下。</p>

<!-- more -->


<p>详细的步骤：</p>

<ol>
<li>脚本确认：拆分镜头，初步确定生成内容。这一步就是需要针对要生成的内容撰写剧本，并拆分成数个镜头。</li>
<li>单帧图片

<ul>
<li>使用Midjourney（V6的语义理解能力有明显提升），DALL-E 3（语义理解能力较好）进行文/图生图</li>
<li>审查已生成图片中的细节问题，调整、更换合适的主题内容，并重新生成符合要求的图片</li>
<li>使用PS处理图片中的不合理细节，添加未被AI生成的元素</li>
<li>使用Stable Diffusion图生图进行图片放大和细节优化</li>
<li>使用PS进行图片的最后优化</li>
<li>人物不一致可以使用换脸进行统一</li>
</ul>
</li>
<li>图生视频

<ul>
<li>使用RunWay/Pika/SVD/Animatediff实现图片生成短视频，可以综合利用各个视频服务的优点，如RunWay的运动笔刷、Pika的面部表情等，其中Pika还可以对局部视频进行重绘。</li>
</ul>
</li>
<li>视频合成

<ul>
<li>使用剪映/iMove进行短视频片段合成与特效转场处理</li>
<li>添加配音和配乐，根据卡点节奏进行视频剪辑与重新生成内容替换(如需要声音)</li>
</ul>
</li>
</ol>


<p>每一步使用的软件以及关键点如下：</p>

<ol>
<li><p>场景描述需要分镜，这里用GPT4来做场景拆解，场景的描述提示词模版如下：</p>

<pre><code class="`"> 需要将一段场景的描述改写成一个时长30秒的分镜脚本，再根据每个分镜脚本的文字描述生成单张图片，之后通过图片生成视频，最后将视频进行拼接成最终的成品视频。

 场景描述如下：

 xxx

 分镜脚本结构如下：
 ‒ 序号：递增数字 
 ‒ 景别：远景/全景/中景/近景/特写 
 ‒ 风格：真实影像风格/日本动漫风格/水墨画风格等（在Dalle3里无法直接写作者的名字，比如新海诚，但Midjourney是可以的。） 
 ‒ 角色：具体到是什么样的角色，有什么特殊的颜色、道具、服饰等等。 
 ‒ 环境：森林、家、海边等等 
 ‒ 镜头移动：描述每个分镜中镜头的动作或变化 
 ‒ 比例：16:9/2.35:1等等

 分镜要求如下：
 1. 每个分镜时长4s
 2. xxx
 3. 内容和风格需要xxx

 每一个分镜后续会通过Midjourney进行图片生成。现在请给出每一个分镜脚本以及对应的Midjourney提示词，以Markdown Table的方式输出。
</code></pre></li>
<li><p>图像需要保持一致性，包括人物和周围场景</p>

<ul>
<li>DALL-E 3：一致性可以通过GenID</li>
<li>Midjourney V6: 最新版有了ref，一致性功能</li>
</ul>
</li>
<li><p>图生视频这一步，需要结合多种视频软件一起使用。每个软件的特点如下：</p>

<ul>
<li><a href="https://pixverse.ai/">Pixverse</a>: 免费无限生成，有一致性角色功能(效果一般)，可用于无限生成视频后择优选取</li>
<li><a href="https://app.runwayml.com/">Runway</a>: 每次生成消耗5积分，做角色动作和部分运动镜头会好一点</li>
<li><a href="https://pika.art/">Pika</a>: 每次生消耗10积分，做角色动作和面部表情</li>
<li><a href="https://www.stablevideo.com">Stable Video</a>: 每次生成消耗10积分，适合生成风景视频</li>
</ul>


<p> 换脸的话，可以使用roop或者facefusion，这里有其colab版本：<a href="https://github.com/dream80/roop_colab">https://github.com/dream80/roop_colab</a>。</p></li>
<li><p>视频拼接，可以使用剪映或者苹果电脑上的iMovie。</p></li>
</ol>


<p>通过以上方案，基本可以实现长视频的生成，但目前AI生成视频的崩坏率极高，可控性差，所以需要生成很多视频，从中选取最符合预期的。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[AI技术概览（PPT版）]]></title>
    <link href="https://www.rowkey.cn/blog/2024/02/01/ai/"/>
    <updated>2024-02-01T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2024/02/01/ai</id>
    <content type="html"><![CDATA[<p>随着2022年底ChatGPT引爆AIGC行业，层出不穷的各种LLM和AIGC应用都让人感觉新的时代马上就要到来。由于业务的需要，2023年自己的主要精力主要放在了AI这部分的跟进与研究。年底给公司做了一次AI技术的科普分享，这里先放出PPT，详细内容待后续的文章补充。</p>

<!--more-->


<h2><strong>AI已来</strong></h2>

<p><img src="https://www.rowkey.cn/post_images/ai/aistart.png" width="450"/></p>

<ul>
<li><strong>AI元年：2023</strong></li>
<li><strong>之前</strong>

<ul>
<li>垂直类AI应用：美颜、换脸、推荐、自动驾驶等，每个模型解决特定问题，“人工智障”的对话机器人</li>
<li>使用门槛高，主要是研发环节的直接接触</li>
<li>以“今日头条”为代表的个性化推荐系统相关AI人才的哄抢</li>
</ul>
</li>
<li><strong>现在</strong>

<ul>
<li>大模型，生成式AI：AI对话、AI绘画、AI视频、AI音乐，一个模型解决所有问题</li>
<li>使用门槛低，自然语言编程（GPTs store）</li>
<li>以“ChatGPT”（2022年11月30号）为代表的大模型人才的哄抢</li>
</ul>
</li>
</ul>


<h2><strong>AI是什么</strong></h2>

<ul>
<li><strong>人工智能</strong>：使机器能够以类似于人类智能的方式执行复杂任务的科学和工程，是一门多个领域的交叉学科。

<ul>
<li>机器：运算速度、记忆容量、钢铁身躯</li>
</ul>
</li>
<li>人类：<del>判断力、创造力、对人类情感的理解</del>与同理、逻辑推理能力</li>
<li><strong>三大学派</strong>：符号主义、连接主义、行为主义

<ul>
<li>符号主义：机器拟人心</li>
<li>连接主义：机器拟人脑</li>
<li>行为主义：机器拟人身</li>
</ul>
</li>
<li><strong>AGI</strong>：人工通用智能，也可以叫做通用人工智能或者强人工智能。指的是人工智能系统应该能够像人类一样具备广泛的智能能力，而不仅仅是在某些特定的任务或领域中表现出色。</li>
<li><strong>Agent</strong>：AI智能体，能够感知其环境并以自主的方式在该环境中行动以达成其目标的系统。</li>
</ul>


<h2>AI发展大事记</h2>

<ul>
<li><strong>人工智能的萌芽</strong>：人工智能之父图灵，1950年提出图灵测试。</li>
<li><strong>人工智能的起点</strong>：1956年达特茅斯会议，开启人工智能第一次高潮</li>
<li><strong>第一次低谷</strong>：20世纪70年代初，各种人工智能承诺无法兑现</li>
<li><strong>人工智能第二次高潮</strong>：20世纪80年代，知识工程和专家系统为代表的符号主义</li>
<li><strong>第二次低谷</strong>：20世纪80年代末到90年代初时期，专家系统的局限性</li>
<li><strong>平稳期</strong>：20世纪90年-2000年初。1997年深蓝”击败国际象棋冠军</li>
<li><strong>人工智能第三次高潮</strong>：2006年，深度学习算法的提出；2012年AlexNet在ImageNet挑战赛的横空出世；2016、2017年AlphaGo打败围棋冠军</li>
<li><strong>AI元年</strong>：2023年，生成式AI-ChatGPT、StableDifussion、MidJourney</li>
</ul>


<h2><strong>机器学习、深度学习</strong></h2>

<p><img src="https://www.rowkey.cn/post_images/ai/ml.png" width="450"/></p>

<ul>
<li>实现人工智能的方法。</li>
<li>机器学习：一种可以让机器根据历史经验自动改进自身的学习算法。</li>
<li>深度学习：机器学习的一种，“无监督特征学习”（Unsupervised Feature Learning），以多层神经网络为代表。

<ul>
<li>人类认知过程：<strong>分层迭代，逐级抽象</strong></li>
</ul>
</li>
</ul>


<h2><strong>LLM</strong></h2>

<p><img src="https://www.rowkey.cn/post_images/ai/llm.png" width="450"/></p>

<ul>
<li>GenAI：相对于判别式AI（Discriminative AI），能够生成新的内容->AIGC</li>
<li>LLM是生成式AI的一种</li>
<li>最可能通向AGI的方法：Transformer</li>
<li>大语言模型：文本->x，多模态->多模态

<ul>
<li>NLP</li>
<li>涌现：鹦鹉vs乌鸦；人类智能的本质？</li>
</ul>
</li>
</ul>


<h2><strong>大模型产业链</strong></h2>

<p><img src="https://www.rowkey.cn/post_images/ai/llmlayer.png" width="450"/></p>

<p><img src="https://www.rowkey.cn/post_images/ai/llmlayer2.png" width="450"/></p>

<ul>
<li>大模型=计算机 or 操作系统, GPTs store</li>
<li>我们的位置 -> <strong>应用层!</strong></li>
</ul>


<h2>GenAI应用概览</h2>

<p><img src="https://www.rowkey.cn/post_images/ai/genai.png" width="450"/></p>

<p><img src="https://www.rowkey.cn/post_images/ai/genairank.png" width="450"/></p>

<p>GenAI数据：<a href="https://zw73xyquvv.feishu.cn/wiki/M2BywHAvCiioSzk9qXHczwJZnOd">https://zw73xyquvv.feishu.cn/wiki/M2BywHAvCiioSzk9qXHczwJZnOd</a></p>

<h2>ChatBot</h2>

<ul>
<li><a href="https://chat.openai.com/">ChatGPT</a></li>
<li><a href="https://copilot.microsoft.com/">微软Copilot</a>：微软基于ChatGPT的ChatBot应用，集成了DALL.E-3、suno.ai等插件</li>
<li><a href="https://kimi.moonshot.cn/chat">KimiChat</a>: 大尺寸上下文（文字、pdf文档等)、实时联网</li>
<li>其他大模型的ChatBot：Claude+、文心一言、豆包、讯飞星火、通义千问&hellip;</li>
<li><a href="https://poe.com/">POE</a>：ChatBot聚合</li>
</ul>


<h2><strong>AI绘画</strong></h2>

<ul>
<li><a href="https://stability.ai/stable-image">Stable Diffusion</a>：生态最丰富的开源图像生成项目</li>
<li><a href="https://openai.com/dall-e-3">DALL-E 3</a>：语义理解能力最强的图像生成产品</li>
<li><a href="https://www.midjourney.com/home">Midjourney:</a> 质量最好的图像生成产品</li>
<li>一些大模型聊天机器人自带的绘图：插件、Agent方式</li>
<li><a href="https://magnific.ai/">Magnific.ai</a>: 图像精修， <a href="https://mp.weixin.qq.com/s/x3F59AcMxG8bmajXO3OXmg">https://mp.weixin.qq.com/s/x3F59AcMxG8bmajXO3OXmg</a></li>
<li><a href="https://segment-anything.com/demo">Meta SAM</a>: 图像分割</li>
</ul>


<h2>AI语音</h2>

<ul>
<li><a href="https://openai.com/research/whisper">Whisper</a>：基于大模型的ASR，自动语言识别</li>
<li><a href="https://elevenlabs.io/">Elevenlabs</a>：TTS，目前最先进的商业化TTS</li>
<li><a href="https://platform.openai.com/docs/guides/text-to-speech">OpenAI TTS</a>: TTS，OpenAI开源</li>
<li><a href="https://suno.ai/">Suno.ai</a>: 文生音乐，<a href="https://app.suno.ai/song/9a782a3b-fde7-44ae-896f-c4d57698efa9/%C2%A0">https://app.suno.ai/song/9a782a3b-fde7-44ae-896f-c4d57698efa9/%C2%A0</a>(中文版的 I'll Be There For You，根据中国文化做稍微的改动)</li>
<li><a href="https://github.com/svc-develop-team/so-vits-svc">so-vits-svc</a>：歌声转换，<a href="https://www.youtube.com/watch?v=sN4ZFwySyow">孙燕姿唱周杰伦的歌</a></li>
</ul>


<h2>AI视频</h2>

<ul>
<li><a href="https://app.runwayml.com/">Runway</a>: 目前技术最先进的视频生成产品</li>
<li><a href="https://pika.art/my-library">Pika</a>：文本->视频，720p, 4秒</li>
<li><a href="https://www.morphstudio.com/">Morph Studio</a>：文本->视频，1080P，7秒 <a href="https://mp.weixin.qq.com/s/krSEoCHPBFuXsbkLm7E5rA">文生视频“黑马”Morph Studio来袭：好用、1080P 、7秒时长还免费</a></li>
<li><a href="https://stability.ai/stable-video">Stable Video Diffusion</a>: StableAI开源的视频生成技术，<a href="https://replicate.com/stability-ai/stable-video-diffusion">https://replicate.com/stability-ai/stable-video-diffusion</a></li>
<li><a href="https://app.heygen.com/login">HeyGen</a>：数字人播报视频生成，<a href="https://www.youtube.com/watch?v=PnpaLTB2Eck">霉霉说中文</a></li>
<li><a href="https://app.wonderdynamics.com/:">WonderStudio</a>: 视频CG角色替换，<a href="https://www.youtube.com/watch?v=YuUsunFIJCU">https://www.youtube.com/watch?v=YuUsunFIJCU</a></li>
<li>图片 -> 真人跳舞视频：通义千问“全民舞王”

<ul>
<li><a href="https://boese0601.github.io/magicdance/">MagicDance</a></li>
<li><a href="https://humanaigc.github.io/animate-anyone/">Animate Anyone</a></li>
</ul>
</li>
</ul>


<h2>其他</h2>

<ul>
<li>文本->3D

<ul>
<li><a href="https://mesh.ai/">Mesah.ai</a></li>
<li><a href="https://www.tripo3d.ai/">Tripo3D.ai</a></li>
</ul>
</li>
<li>图片->网页: <a href="https://screenshottocode.com/">https://screenshottocode.com/</a></li>
<li>图片/文本->网页、UI：<a href="https://v0.dev/">https://v0.dev/</a></li>
</ul>


<h2><strong>我们可以做什么</strong></h2>

<ul>
<li>基于大模型的产品研发</li>
<li>个人

<ul>
<li>文章总结摘要：<a href="https://kimi.moonshot.cn/chat/cm6p88kudu6f77a0fqig">https://kimi.moonshot.cn/chat/cm6p88kudu6f77a0fqig</a></li>
<li>写儿童故事：<a href="https://chat.openai.com/share/6c86a6a3-5cda-45e8-af10-4bb4cd2476fb">https://chat.openai.com/share/6c86a6a3-5cda-45e8-af10-4bb4cd2476fb</a></li>
<li>专业问题解答：<a href="https://chat.openai.com/share/0d9de7f4-eba3-4eba-be2b-0dd89b146d53">https://chat.openai.com/share/0d9de7f4-eba3-4eba-be2b-0dd89b146d53</a></li>
</ul>
</li>
<li>工作</li>
<li>辅助编程: Genie、Github Copilot</li>
<li>分析需求文档，输出摘要和模块</li>
<li><p>基于LLM的研发全流程</p>

<p>  <img src="https://www.rowkey.cn/post_images/ai/llmsdlc.png" width="450"/></p></li>
</ul>


<h2><strong>展望</strong></h2>

<ul>
<li>新摩尔定律：宇宙中的智能数量每18个月翻一番</li>
<li>所有的应用都值得用AI重构一遍</li>
<li>AI不会取代人类，但会AI的会取代不会AI的人类</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[这三年的一些感悟]]></title>
    <link href="https://www.rowkey.cn/blog/2024/01/27/mythought/"/>
    <updated>2024-01-27T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2024/01/27/mythought</id>
    <content type="html"><![CDATA[<p>得闲看了一下博客，发现从2021年开始文章就很少了。主要是由于工作的需要，从那时开始基本上都在不停地学习新的东西，每个东西学习和使用的时间都不长，能分享的东西也就不多。而自己年终总结也停留在了2021年。今天想着梳理一下从2021年开始自己的一些感悟吧，也算是总结，也算是一个阶段的分享。</p>

<!--more-->


<p>2021-2023可以分为三个阶段</p>

<ul>
<li>游戏</li>
<li>Web3</li>
<li>AI</li>
</ul>


<h2>游戏</h2>

<p>2021年开始做了一年多的游戏业务，从开始的休闲游戏到后来的网赚游戏，经历了好几次转型。最终以失败告终。</p>

<p>这段经历让我深深体会到了前美团COO干嘉伟的一段话：从职能管理到业务管理，这是一个非常大的跨越。哪怕你是一个非常有经验的职能管理者，管过几千人的团队，也不意味着你就可以顺理成章地孵化出一个5个人的独立业务，二者的能力要求完全不一样。</p>

<p>当然，一个业务的成功很多时候也得看很多客观因素的，比如市场环境、机会等等。但换个角度的话，每个行业总有成功的，为什么不是自己呢？</p>

<p>现在反思来看，自己其实不具备负责一整个业务的能力的。对于一个业务负责人来说，去识别业务的关键环节，并采取有效办法去解决是核心能力。而自己确实识别出来了一些关键点，但却跳不出舒适区，没有弄脏自己的双手去解决问题。这也导致了一次次业务转型的失败。</p>

<h2>Web3</h2>

<p>2022年下半年开始，停了游戏业务，也关了一些其他业务。在互联网行业夏然而止的境况下，也试着去探索Web3业务。</p>

<p>由于这个话题的敏感性，过程这里就不过多提及了。最终差不多了做了半年，发现其实Web3的本质还是加密货币，其他的都是一种概念炒作而已，也决定停滞了。好的地方时经历了这个学习过程，整个团队算是破除了对Web3的神秘感。</p>

<h2>AI</h2>

<p>2022年底随着ChatGPT的火爆，一下子点燃了AI行业。而随着23年疫情的结束，也开始了对AI这方面的探索。所以，整个23年是一直处于对AI的学习过程。</p>

<p>首先，肯定逃不开ChatGPT，原理、使用、提示词工程、微调、应用开发等等，都有涉猎。</p>

<p>然后，就是Stable Diffusion、MidJourney等AI绘画产品，逐步都引入了设计团队，很大程度节省了人力，提高了交付效率。</p>

<p>再者就是后来各种开源的LLM，从LLaMA开始，一系列国内国外的模型层出不穷。</p>

<p>概括来看，2023年，AI绘画已经可以用在工业场景了，LLM也能够达到真人水平的聊天水平。但受限于很多限制，除了类似ChatGPT这种LLM原生的聊天应用，杀手级的toC应用一直没有出现（c.ai的留存有问题），这个也是大家目前都在探索的方向。</p>

<p>这个过程也伴随我们的AI应用的从0到1，一路踩坑，一路成长。</p>

<h2>其他</h2>

<p>除了上面之外，在南京算是待了三年了，还有一些对南京这个城市的感悟。</p>

<ul>
<li>南京真的算是互联网沙漠了，尤为明显的就是各种技术大会基本就没有在南京开的，虽然上海、杭州都离得不远，但要想完整地参加一次会议，怎么着也得住一晚才行。</li>
<li>南京这个地方，可以看做是东部的西安，还是以研究所、体制内为主的好单位居多。其中14所，据说是全国待遇最好、也是最难进的研究所。自己当时毕业时，投了简历就没啥下文了。</li>
<li>南京比起其他同量级的城市，挺小的。在这里开车即使再堵车，也就是十几二十分钟的事情。</li>
<li>南京对人才的拥抱程度我感觉是不太好的，自己当时用人才资格购房时遇到的一些事情，真的无力吐槽。这个状况貌似也和西安差不多，就先把人给吸引过去，然后就不管了或者直接割这波人的韭菜。</li>
<li>自己待过时间比较长的城市如果自己选定居顺序的话，应该是：杭州>北京>南京>西安。当时如果有北京户口的话，为了下一代，无脑北京也没问题。</li>
<li>23年在成都开了分公司，对比起来，成都招互联网的研发人员比南京容易，薪资还比南京便宜。南京就很尴尬。</li>
<li>南京的教育很卷，据说中考硬卡50%升学率，考不上要么技校，要么就花钱出国。然后江苏最厉害的南京大学对本省每年貌似也就招500左右的学生，与浙大每年在浙江招四五千人相比，真的是很吝啬与照顾本省学生了。当然，好的学校总数确实比浙江多，东南大学、南理、南邮、南师等等，211学校还是不少的。</li>
<li>我自己感觉南京的城市规划是有问题的。在南京开车，有时候就突然来到一片区域感觉进了县城一样，破破旧旧的感觉。尤其有个宁芜铁路，直接把南京主城区分割成了两半，周围的小区一到晚上就只能伴随着一些柴油货车的鸣笛声入睡了。每次经过这地方，一大群人、自行车、电动车等待火车经过放开闸机的景象，犹如回到了90年代。</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Langchain代理和OpenAI函数调用的区别]]></title>
    <link href="https://www.rowkey.cn/blog/2023/11/30/openai-func/"/>
    <updated>2023-11-30T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2023/11/30/openai-func</id>
    <content type="html"><![CDATA[<p>最近在实现LLM调用外部工具的时候，突然意识到貌似OpenAI的Function Calling和LangChain的Agent都能达到相同的结果，只是实现方式不同。因此这里来对比一下。</p>

<!--more-->


<h2>OpenAI Functions Calling</h2>

<p>OpenAI函数允许更好地控制AI调用的函数，因为我们必须解析AI的响应，找出AI想要调用的函数，并将参数传递给该函数。我们可以在每个阶段干预并修改被调用函数或其参数。</p>

<p>假设我们想让AI使用一个REST API，而不指定它可以执行的操作。我们提供一个通用的REST API客户端，让AI决定使用哪种HTTP方法和哪些参数。</p>

<h2>定义一个函数</h2>

<p>首先，我们必须准备一个可用Function的描述。</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>functions = [
</span><span class='line'>{
</span><span class='line'>    "type": "function",
</span><span class='line'>    "function": {
</span><span class='line'>        "name": "call_rest_api",
</span><span class='line'>        "description": "Sends a request to the REST API",
</span><span class='line'>        "parameters": {
</span><span class='line'>            "type": "object",
</span><span class='line'>            "properties": {
</span><span class='line'>                "method": {
</span><span class='line'>                    "type": "string",
</span><span class='line'>                    "description": "The HTTP method to be used",
</span><span class='line'>                    "enum": ["GET", "POST", "PUT", "DELETE"],
</span><span class='line'>                },
</span><span class='line'>                "url": {
</span><span class='line'>                    "type": "string",
</span><span class='line'>                    "description": "The URL of the endpoint. Value placeholders must be replaced with actual values.",
</span><span class='line'>                },
</span><span class='line'>                "body": {
</span><span class='line'>                    "type": "string",
</span><span class='line'>                    "description": "A string representation of the JSON that should be sent as the request body.",
</span><span class='line'>                },
</span><span class='line'>
</span><span class='line'>            },
</span><span class='line'>            "required": ["method", "url"],
</span><span class='line'>        },
</span><span class='line'>    }
</span><span class='line'>}
</span><span class='line'>]</span></code></pre></td></tr></table></div></figure>


<p>除了描述之外，还需要一个函数的实现。毕竟，当我们收到一个表示AI想要调用函数的响应时，我们将负责调用该函数。</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>def call_rest_api(self, arguments):
</span><span class='line'>    arguments = json.loads(arguments)
</span><span class='line'>    # reques.in is a hosted, fake REST API that we can use for testing
</span><span class='line'>    url = 'https://reqres.in' + arguments['url']
</span><span class='line'>    body = arguments.get('body', {})
</span><span class='line'>    response = None
</span><span class='line'>    if arguments['method'] == 'GET':
</span><span class='line'>        response = requests.get(url)
</span><span class='line'>    elif arguments['method'] == 'POST':
</span><span class='line'>        response = requests.post(url, json=body)
</span><span class='line'>    elif arguments['method'] == 'PUT':
</span><span class='line'>        response = requests.put(url, json=body)
</span><span class='line'>    elif arguments['method'] == 'DELETE':
</span><span class='line'>        response = requests.delete(url)
</span><span class='line'>    else:
</span><span class='line'>        raise ValueError(arguments)
</span><span class='line'>
</span><span class='line'>    if response.status_code == 200:
</span><span class='line'>        return json.dumps(response.json())
</span><span class='line'>    else:
</span><span class='line'>        return f"Status code: {response.status_code}"</span></code></pre></td></tr></table></div></figure>


<p>该函数是通用的，可以处理发送到任何端点的任何HTTP请求。需要列出可用的端点和支持的HTTP方法。我更喜欢将这些参数收集到一个变量中，稍后用于生成提示：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>available_apis = [
</span><span class='line'>        {'method': 'GET', 'url': '/api/users?page=[page_id]', 'description': 'Lists employees. The response is paginated. You may need to request more than one to get them all. For example,/api/users?page=2.'},
</span><span class='line'>        {'method': 'GET', 'url': '/api/users/[user_id]', 'description': 'Returns information about the employee identified by the given id. For example,/api/users/2'},
</span><span class='line'>        {'method': 'POST', 'url': '/api/users', 'description': 'Creates a new employee profile. This function accepts JSON body containing two fields: name and job'},
</span><span class='line'>        {'method': 'PUT', 'url': '/api/users/[user_id]', 'description': 'Updates employee information. This function accepts JSON body containing two fields: name and job. The user_id in the URL must be a valid identifier of an existing employee.'},
</span><span class='line'>        {'method': 'DELETE', 'url': '/api/users/[user_id]', 'description': 'Removes the employee identified by the given id. Before you call this function, find the employee information and make sure the id is correct. Do NOT call this function if you didn\'t retrieve user info. Iterate over all pages until you find it or make sure it doesn\'t exist'}
</span><span class='line'>    ]</span></code></pre></td></tr></table></div></figure>


<p>接着需要定义AI的任务和可用的功能。为此，准备以下系统提示词。</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>messages = [
</span><span class='line'>    {"role": "system", 
</span><span class='line'>    "content": "You are an HR helper who makes API calls on behalf of an HR representative，You have access to the following APIs: " 
</span><span class='line'>        + json.dumps(self.available_apis)
</span><span class='line'>        + "If a function requires an identifier, list all employees first to find the proper value. You may need to list more than one page"
</span><span class='line'>        + "If you were asked to create, update, or delete a user, perform the action and reply with a confirmation telling what you have done"
</span><span class='line'>    }
</span><span class='line'>]</span></code></pre></td></tr></table></div></figure>


<p>最终，可以与AI进行交互。我们定义一个函数call_ai。该函数接受用户的提示，并将提示传递给之前定义的OpenAI模型的上下文描述。上下文描述还包含了可用函数的描述。如果AI回复的消息包含function_call，我们会调用一个函数。该消息包括函数名和参数。</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>def call_ai(self, new_message):
</span><span class='line'>    if new_message:
</span><span class='line'>        self.messages.append({"role": "user", "content": new_message})
</span><span class='line'>
</span><span class='line'>    response = self.client.chat.completions.create(
</span><span class='line'>        model="gpt-3.5-turbo-1106",
</span><span class='line'>        messages=self.messages,
</span><span class='line'>        tools=self.functions,
</span><span class='line'>        tool_choice="auto",
</span><span class='line'>    )
</span><span class='line'>
</span><span class='line'>    msg = response.choices[0].message
</span><span class='line'>    self.messages.append(msg)
</span><span class='line'>    if msg.content:
</span><span class='line'>        logging.debug(msg.content)
</span><span class='line'>    if tool_calls:
</span><span class='line'>        msg.content = "" # required due to a bug in the SDK. We cannot send a message with None content
</span><span class='line'>        for tool_call in tool_calls:
</span><span class='line'>            # we may get a request to call more than one function(!)
</span><span class='line'>            function_name = tool_call.function.name
</span><span class='line'>            function_args = json.loads(tool_call.function.arguments)
</span><span class='line'>            if function_name == 'call_rest_api':
</span><span class='line'>                # ['function_call']['arguments'] contains the arguments of the function
</span><span class='line'>                logging.debug(function_args)
</span><span class='line'>                # Here, we call the requested function and get a response as a string
</span><span class='line'>                function_response = self.call_rest_api(function_args)
</span><span class='line'>                logging.debug(function_response)
</span><span class='line'>                # We add the response to messages
</span><span class='line'>                self.messages.append({
</span><span class='line'>                    "tool_call_id": tool_call.id,
</span><span class='line'>                    "role": "tool",
</span><span class='line'>                    "name": function_name,
</span><span class='line'>                    "content": function_response
</span><span class='line'>                })
</span><span class='line'>
</span><span class='line'>                self.call_ai(new_message=None) # pass the function response back to AI
</span><span class='line'>    else:
</span><span class='line'>      # return the final response
</span><span class='line'>      return msg</span></code></pre></td></tr></table></div></figure>


<p>一方面，这样的实现使代码变得非常冗长。就像下面所看到的，我们必须选择要调用的Python函数，传递参数，将响应添加到聊天记录中（作为一个带有role设置为tool的消息），然后再次调用AI并更新聊天记录。</p>

<p>另一方面，我们对被调用的函数保持完全控制。我们可以调用不同的函数，改变参数，或者传递一个虚假的响应给人工智能，而不是调用一个函数。</p>

<p>通过OpenAI的实现，我们还可以轻松创建长时间运行的工作流程，在数据库中存储聊天记录，在AI请求的函数调用后等待几个小时或几天，当我们收到回复时继续工作流程。</p>

<h2>使用Langchain代理进行函数调用</h2>

<p>Langchain代理隐藏了调用函数的复杂性。我们仍然需要提供函数描述和实现，或者使用其中一个可用的Langchain工具包。Langchain工具包是一种快捷方式，允许我们跳过编写函数及其描述的步骤。相反，我们使用工具包作者准备的代码。</p>

<p>在Langchain中，我们必须选择其中一种可用的代理类型。代理类型定义了提示，以便向模型介绍可用的功能。</p>

<p>代理类型实现了各种交互样式。例如，在conversational-react-description代理中，提示的指令部分如下所示：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>To use a tool, please use the following format:
</span><span class='line'>
</span><span class='line'>Thought: Do I need to use a tool? Yes
</span><span class='line'>Action: the action to take, should be one of [{tool_names}]
</span><span class='line'>Action Input: the input to the action
</span><span class='line'>Observation: the result of the action
</span><span class='line'>
</span><span class='line'>When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:
</span><span class='line'>
</span><span class='line'>Thought: Do I need to use a tool? No
</span><span class='line'>{ai_prefix}: [your response here]
</span><span class='line'>
</span><span class='line'>## https://github.com/langchain-ai/langchain/blob/9731ce5a406d5a7bb1878a54b265a6f7c728effc/libs/langchain/langchain/agents/conversational/prompt.py</span></code></pre></td></tr></table></div></figure>


<p>当使用此提示时，Langchain会让AI生成输出，直到它产生Action Input: 之后的第一个换行符。此时，Langchain会中断AI调用，找到使用Action: 行返回的名称的函数，并将Action Input: 的值作为参数传递。</p>

<p>稍后，当函数返回响应时，响应被添加到提示中的Observation: 行，并且Langchain再次调用LLM来继续处理提示。LLM可能会产生另一个Action: + Action Input: 对，以调用另一个函数或生成以Final Answer: 开头的行，将响应返回给用户。</p>

<p>一个流行的zero-shot-react-description几乎具有相同的提示。</p>

<h2>在Langchain中使用OpenAI Function Calling</h2>

<p>选择一个代理类型，该类型使用OpenAI函数，但隐藏了选择函数和传递参数的复杂性。使用配置Langchain代理的标准代码结构，但选择OPENAI_FUNCTIONS AgentType。</p>

<p>Langchain试图将整个函数描述打包成一条消息，而长描述很容易超过消息长度限制，因此不得不缩短提示。如果需要所有的端点，可以将call_rest_api函数拆分成多个函数，每个函数处理一个端点。</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>import json
</span><span class='line'>import requests
</span><span class='line'>from langchain import OpenAI
</span><span class='line'>from langchain.agents import initialize_agent, Tool
</span><span class='line'>from langchain.agents import AgentType
</span><span class='line'>from langchain.chat_models import ChatOpenAI
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>def call_rest_api(method_and_url):
</span><span class='line'>    method, url = method_and_url.split(' ')
</span><span class='line'>    url = 'https://reqres.in' + url
</span><span class='line'>    response = None
</span><span class='line'>    if method == 'GET':
</span><span class='line'>        response = requests.get(url)
</span><span class='line'>    elif method == 'DELETE':
</span><span class='line'>        response = requests.delete(url)
</span><span class='line'>    else:
</span><span class='line'>        raise ValueError(method)
</span><span class='line'>
</span><span class='line'>    if response.status_code == 200:
</span><span class='line'>        return response.json()
</span><span class='line'>    else:
</span><span class='line'>        return f"Status code: {response.status_code}"
</span><span class='line'>
</span><span class='line'>available_apis = [
</span><span class='line'>        {'api ': 'GET /api/users?page=[page_id]', 'description': 'Lists employees. The response is paginated. You may need to request more than one to get them all. For example,/api/users?page=2.'},
</span><span class='line'>        {'api': 'DELETE /api/users/[numeric user_id]', 'description': 'Removes the employee identified by the given id. Before you call this function, find the employee information and make sure the id is correct. Do NOT call this function if you didn\'t retrieve user info. Iterate over all pages until you find it or make sure it doesn\'t exist'}
</span><span class='line'>    ]
</span><span class='line'>
</span><span class='line'>api_description = json.dumps(available_apis)
</span><span class='line'>
</span><span class='line'>function_description = f"""Sends a request to the REST API.
</span><span class='line'>
</span><span class='line'>Accepts a single parameter containing two parts:
</span><span class='line'>* method - The HTTP method to be used (GET, POST, PUT, or DELETE)
</span><span class='line'>* url - The URL of the endpoint. Value placeholders must be replaced with actual values.
</span><span class='line'>
</span><span class='line'>For example: GET /api/users?page=1 or DELETE /api/users/13
</span><span class='line'>
</span><span class='line'>To find users by name, use the GET method first.
</span><span class='line'>
</span><span class='line'>Available endpoints:
</span><span class='line'>{api_description}"""
</span><span class='line'>
</span><span class='line'>llm = ChatOpenAI(temperature=0, model="gpt-4", openai_api_key='sk-...')
</span><span class='line'>tools = [
</span><span class='line'>    Tool(
</span><span class='line'>        name = "REST",
</span><span class='line'>        func=call_rest_api,
</span><span class='line'>        description=function_description
</span><span class='line'>    )
</span><span class='line'>]
</span><span class='line'>
</span><span class='line'>agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)
</span><span class='line'>agent.run("Fire Lawson")</span></code></pre></td></tr></table></div></figure>


<p>在控制台中，可以看到Agent的详细日志：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Invoking: `REST` with `GET /api/users?page=1`
</span><span class='line'>{'page': 1, 'per_page': 6, 'total': 12, 'total_pages': 2, 'data': [...
</span><span class='line'>
</span><span class='line'>Invoking: `REST` with `GET /api/users?page=2`
</span><span class='line'>{'page': 2, 'per_page': 6, 'total': 12, 'total_pages': 2, 'data': [{'id': 7, 'email': 'michael.lawson@reqres.in', 'first_name': 'Michael', 'last_name': 'Lawson', 'avatar': 'https://reqres.in/img/faces/7-image.jpg'}, ...
</span><span class='line'>
</span><span class='line'>Invoking: `REST` with `DELETE /api/users/7`
</span><span class='line'>Status code: 204
</span><span class='line'>
</span><span class='line'>User Lawson has been successfully removed from the system.</span></code></pre></td></tr></table></div></figure>


<h2>如何选择？</h2>

<p>如果我有一个简单的函数和简短的描述，优先选择Langchain，因为Langchain隐藏了许多实现细节，让我们专注于准备提示。</p>

<p>当函数的描述不再适合于一条信息时，那只能使用OpenAI函数，而不使用Langchain。</p>

<p>此外，调试提示词时，建议切换到OpenAI函数。它不会神奇地解决问题，必须编写整个函数调用代码。因此使得调试将更加容易。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[【译】如何基于开源技术构建类似ChatGPT的聊天机器人]]></title>
    <link href="https://www.rowkey.cn/blog/2023/07/30/build-gpt-chatbot/"/>
    <updated>2023-07-30T19:29:34+08:00</updated>
    <id>https://www.rowkey.cn/blog/2023/07/30/build-gpt-chatbot</id>
    <content type="html"><![CDATA[<p>原文：<a href="https://hacks.mozilla.org/2023/07/so-you-want-to-build-your-own-open-source-chatbot/?continueFlag=6d9bf218cf6b0fd3ad8c94275089c5a0">https://hacks.mozilla.org/2023/07/so-you-want-to-build-your-own-open-source-chatbot/?continueFlag=6d9bf218cf6b0fd3ad8c94275089c5a0</a> by Stephen Hood</p>

<p>人工智能很可能是近年来最具有影响力和颠覆性的技术之一。这种影响并非理论性的：人工智能已经以实质性的方式影响了现实中的人们，它已经在改变我们所熟悉和喜爱的网络。鉴于 AI 可能带来的好处和危害，Mozilla 已经致力于<a href="https://foundation.mozilla.org/en/internet-health/trustworthy-artificial-intelligence/">可信 AI</a> 的原则。对于我们来说，“可信”意味着 AI 系统在使用数据和做出决策时是透明的，尊重用户的隐私，优先考虑用户的自主权和安全，并致力于减少偏见和促进公正。</p>

<!--more-->


<h2>现状</h2>

<p>目前，大多数人体验最新的人工智能技术的主要方式是通过生成式 AI 聊天机器人。这些工具因为为用户提供了很多价值而变得越来越受欢迎，但主流的产品（如 ChatGPT 和 Bard）都由强大的科技公司运营，通常使用专有技术。</p>

<p>在 Mozilla，我们相信开源的协作力量可以赋予用户能力，推动透明度，并且最重要的是确保技术的发展不仅仅按照少数企业的世界观和财务动机。幸运的是，最近在开源 AI 领域取得了快速而令人兴奋的进展，特别是关于支持这些聊天机器人的大型语言模型（LLMs）和工具。我们希望理解、支持和贡献这些努力，因为我们相信它们提供了确保 AI 系统真正可信的最佳途径之一。</p>

<h2>深入探究</h2>

<p>抱着这个目标,Mozilla创新组的一个小团队最近在我们旧金山总部举办了一次黑客马拉松。我们的目标是:构建一个Mozilla内部聊天机器人原型,这个原型需要:</p>

<ul>
<li>完全自主包含,全部运行在Mozilla的云基础设施上,不依赖任何第三方API或服务。</li>
<li>使用免费的开源大型语言模型和工具构建。</li>
<li>融入Mozilla的理念,从可信赖的AI到Mozilla宣言阐述的原则。</li>
</ul>


<p>另外,我们设定了一个挑战目标,那就是整合一定数量的Mozilla内部专有知识,这样聊天机器人可以回答员工对内部事务的问题。</p>

<p>参与这个项目的Mozilla团队——Josh Whiting、Rupert Parry和我自己——我们在机器学习方面具有不同的知识水平,但都没有构建过完整的AI聊天机器人。所以,这个项目的另一个目标就是简单地卷起袖子,学习!</p>

<p>本文旨在分享这些学习成果,希望可以帮助或鼓舞你进行自己的技术探索。组装一个开源大型语言模型驱动的聊天机器人事实证明是一项复杂的任务,需要在技术栈的多个层面做出许多决策。在本文中,我将带您逐层了解这个技术栈,我们遇到的挑战以及为满足我们自己的具体需求和最后期限所做出的决策。当然,根据不同情况,您的 mileage may vary。</p>

<p>准备好了吗?那么,让我们从技术栈的底层开始&hellip;&hellip;下图是聊天机器人的技术调研概览图。</p>

<p><img src="https://www.rowkey.cn/post_images/gpt-chatbot/stack.png" alt="" /></p>

<h2>决定托管的位置和方式</h2>

<p>我们面临的第一个问题是在哪里运行我们的应用程序。无论大型还是小型公司都渴望托管你的机器学习应用程序,它们有各种各样的形状、大小、抽象级别和价格。</p>

<p>对许多人来说,这些服务值得付出。机器学习运维(又称“MLOps”)是一个日益发展的学科,原因很充分:部署和管理这些应用程序是非常困难的。它需要许多开发人员和运维人员还没有掌握的特定知识和技能。而失败的代价是高昂的:配置不当的AI应用程序可能会变慢、昂贵,提供糟糕的用户体验,或者所有这些问题都存在。</p>

<p><strong>我们的做法</strong>: 鉴于这个为期一周的项目,我们的明确目标是搭建一个对Mozilla完全安全私密的聊天机器人,没有外部方能够监听、收集用户数据或以其他方式窥视其使用情况。我们也希望尽可能多地了解开源AI技术的现状。因此,我们决定放弃任何第三方AI SaaS托管解决方案,而是在Mozilla现有的Google Cloud Platform(GCP)账户内设置自己的虚拟服务器。通过这种方式,我们实际上承诺自己进行MLOps。但我们也可以有信心系统将是私密的、完全在我们控制之下。</p>

<h2>选择运行时环境</h2>

<p>使用大型语言模型驱动应用程序需要一个模型的运行时引擎。实际运行大型语言模型有多种方式,但由于时间限制,我们在这个项目中没有调研所有方法。相反,我们专注于两种具体的开源解决方案:llama.cpp和Hugging Face生态系统。</p>

<p>对不了解的人来说,Hugging Face是机器学习领域有影响力的创业公司,在推广transformer架构用于机器学习方面发挥了重要作用。Hugging Face提供了一个完整的平台来构建机器学习应用程序,包括大量的模型库、广泛的教程和文档。他们还提供了文本推理(这是聊天机器人在幕后运行的正式名称)的托管API。</p>

<p>因为我们希望避免依赖任何其他人托管的软件,所以我们选择尝试Hugging Face托管API的开源版本,它托管在GitHub的text-generation-inference项目中。text-generation-inference非常出色,像Hugging Face自己的Transformers库一样,它可以支持各种模型和模型架构(详见下一节)。它也经过了优化,可以支持多个用户,并可以通过Docker进行部署。</p>

<p>不幸的是,这是我们开始遇到边学习边实践MLOps的有趣挑战之处。我们在启动和运行服务器方面遇到了很多麻烦。部分原因是环境问题:由于Hugging Face的工具是GPU加速的,我们的服务器需要特定的操作系统、硬件和驱动程序组合。特别需要安装NVIDIA的CUDA工具包(CUDA是主流的GPU加速机器学习应用程序的API)。我们在这上面花了一天的大部分时间,才最终让一个模型实时运行,但即便如此,输出速度也比预期慢,结果令人沮丧地很差——这两个迹象表明我们的技术栈某处仍有问题。</p>

<p>现在,我并不是在诋毁这个项目。恰恰相反!我们喜欢Hugging Face,构建他们的技术栈有许多优势。我确信如果我们有更多时间和/或亲身经验,我们会让它正常工作。但在这种情况下,时间是我们所没有的奢侈。我们有意设置的短期项目期限意味着我们无力陷入配置和部署的困境太深。我们需要快速使某些东西工作,以便我们可以继续前进并持续学习。</p>

<p>这时,我们将注意力转向了llama.cpp,这是一个由Georgi Gerganov启动的开源项目。llama.cpp完成了一个相当巧妙的技巧:它可以轻松地在消费级硬件上运行某些大型语言模型,依靠CPU而不是需要高端GPU。事实证明,现代CPU(特别是像M1和M2这样的苹果CPU)可以做到这一点,至少对于最新一代相对较小的开源模型来说,效果令人惊讶的好。</p>

<p>llama.cpp是一个惊人的项目,是一个开源释放创造力和创新的力量的绝佳例子。我已经在自己的AI实验中使用过它,甚至写了一篇博文展示任何人如何使用它在自己的MacBook上运行高质量的模型。所以,这似乎是我们接下来要尝试的自然之举。</p>

<p>虽然llama.cpp本身只是一个命令行可执行文件(“cpp”代表“C++”),但它可以进行Docker化并像服务一样运行。关键是,有一组Python绑定暴露了OpenAI API规范的实现。这一切意味着什么?嗯,它意味着llama.cpp可以轻松地使用你自己的大型语言模型取代ChatGPT。这很重要,因为OpenAI的API正在被机器学习开发者快速广泛地采用。llama.cpp这样的开源项目模仿该API是一种精明的柔道手法。</p>

<p><strong>我们的做法</strong>:有了这些工具,我们能够非常快速地启动并运行llama.cpp。我们不再需要担心CUDA工具包版本和配置昂贵的托管GPU,而是能够启动一个简单的基于多核心AMD CPU的虚拟服务器,然后&hellip;&hellip;就可以开始了。</p>

<h2>选择模型</h2>

<p>您会注意到这个叙述中的一个新兴趋势是,在构建聊天机器人时,您做出的每个决定都与其他决定互相影响。没有简单的选择,也没有免费的午餐。你所做的决定都会回过头来困扰你。</p>

<p>在我们的案例中,选择使用llama.cpp带来了一个重要后果:我们被可用的模型列表限制了。</p>

<p>快速历史课:2022年底,Facebook宣布了LLaMA,它自己的大型语言模型。大致来说,LLaMA由两部分组成:模型数据本身和模型所基于的架构。Facebook开源了LLaMA架构,但没有开源模型数据。相反,希望使用此数据的人需要申请许可,并且他们对数据的使用仅限于非商业用途。</p>

<p>即便如此,LLaMA立即催生了模型创新爆炸式增长。斯坦福大学通过一种称为微调的过程在LLaMA的基础上开发出了Alpaca。不久之后,LMSYS发布了Vicuna,一个可以说更令人印象深刻的模型。还有成百上千的其他模型。</p>

<p>那么细则是什么?这些模型都是使用Facebook的模型数据(在机器学习术语中称为“权重”)开发的。因此,它们继承了Facebook对这些原始权重施加的法律限制。这意味着尽管这些模型本身非常优秀,但它们不能用于商业目的。所以,遗憾的是,我们不得不从我们的列表中删除它们。</p>

<p>但好消息是:即使LLaMA权重不是真正的开源,其底层架构是适当的开源代码。这使得构建利用LLaMA架构但不依赖于LLaMA权重的新模型成为可能。多个团队已经这么做了,从头开始训练自己的模型并以开源方式发布(通过MIT、Apache 2.0或Creative Commons许可)。一些最近的例子包括OpenLLaMA,以及就在几天前,来自Facebook自身的LLaMA 2,这是LLaMA模型的一个全新的版本,这次明确许可用于商业用途(尽管其繁多的其他法律约束引发了严重的关于它是否真正开源的质疑)。</p>

<h2>你好,后果</h2>

<p>还记得llama.cpp吗?这个名字不是偶然的。llama.cpp运行基于LLaMA架构的模型。这意味着我们可以在聊天机器人项目中利用上述模型。但这也意味着我们只能使用基于LLaMA架构的模型。</p>

<p>您看,还有许多其他模型架构,以及在它们之上构建的许多模型。这里无法一一列举,但一些主要的例子包括MPT、Falcon和Open Assistant。这些模型使用不同于LLaMA的架构,因此(目前)无法在llama.cpp上运行。这意味着无论它们有多好,我们都无法在聊天机器人中使用它们。</p>

<p>选择llama.cpp限制了我们可以使用的模型。这印证了在构建聊天机器人时,每个决定都是相互关联的。我们必须接受所做选择的后果。这再次凸显了开源的重要性,它为根据需求自由组合不同组件提供了可能性。</p>

<h2>模型、偏见、安全性和你</h2>

<p>现在,您可能已经注意到到目前为止我只是从许可和兼容性的角度来讨论模型选择。这里还有一整套其他考量,它们与模型本身的质量有关。</p>

<p>模型是Mozilla对AI空间感兴趣的焦点之一。那是因为您选择的模型目前是决定结果AI“可信赖性”的最大决定因素。大型语言模型在大量数据上训练,然后使用额外的输入进行进一步微调,以调整其行为和输出以服务于特定用途。这些步骤中使用的数据集本身就是一种策展选择,这种选择带来了一系列偏见。</p>

<p>根据模型的训练数据源,它可以表现出完全不同的特征。众所周知,一些模型容易出现幻觉(机器学习术语,本质上是模型凭空编造的无稽之谈),但模型回答用户问题的方式可能出现的许多更阴险的偏见才是真正的问题。这些响应反映了模型本身的偏见。它们可能导致有害内容、误信息和危险信息的传播。模型可能对某些概念或人群群体存在偏见。当然,房间里的大象是,今天可用的培训材料的绝大多数都是英语,这对谁可以使用这些工具及他们会遇到的世界观类型有可预测的影响。</p>

<p>尽管有大量资源用于评估大型语言模型的原始功效和“质量”(一个流行示例是Hugging Face的Open LLM排行榜),但在源头和偏见方面评估和比较模型仍具有挑战性。Mozilla认为,与专有的商业产品相比,在这方面开源模型具有通过它们可以提供的更大透明度而闪光的潜力。</p>

<p><strong>我们的做法</strong>:在限制自己使用在LLaMA架构上运行的可商用开源模型后,我们对几个模型进行了手动评估。该评估包含向每个模型提出各种问题,以比较它们抵御有毒内容、偏见、误信息和危险内容的能力。最终,我们目前选择了Facebook的新LLaMA 2模型。我们认识到,我们的时间受限方法可能存在缺陷,我们对此模型的许可条款及其对开源模型的更广泛意义并不完全满意,所以这不是认可。随着我们不断学习和思考,我们期望在未来重新评估我们的模型选择。</p>

<h2>使用嵌入和向量搜索来扩展聊天机器人的知识</h2>

<p>您可能还记得,在本文开头我们为自己设定了一个整合一定量Mozilla内部知识到我们的聊天机器人的伸展目标。这个想法简单地是使用一小部分内部Mozilla数据(员工自己也能访问的事实,但通常语言模型不能)来构建一个概念验证。</p>

<p>实现这一目标的一种流行方法是使用向量搜索和嵌入。这是一种使定制的外部文档可用于聊天机器人的技术,以便它可以在制定答案时利用这些文档。这种技术既强大又有用,在未来的几个月和几年中,这一领域可能会有很多创新和进步。已经有各种开源和商业工具和服务可用于支持嵌入和向量搜索。</p>

<p>它的最简单形式大致如下工作:</p>

<ul>
<li>必须从通常存储的位置检索你希望可用的数据,并使用单独的模型(称为嵌入模型)转换为嵌入。这些嵌入被索引在聊天机器人可以访问的地方,称为向量数据库。</li>
<li>当用户提出问题时,聊天机器人会在向量数据库中搜索任何可能与用户查询相关的内容。</li>
<li>然后将返回的相关内容传递到主模型的上下文窗口(详见下文),并用于制定响应。</li>
</ul>


<p><strong>我们的做法</strong>:因为我们想要完全控制所有数据,所以我们拒绝使用任何第三方嵌入服务或向量数据库。相反,我们用Python编写了一个手动解决方案,它利用all-mpnet-base-v2嵌入模型、SentenceTransformers嵌入库、LangChain(我们将在下面更多地讨论它)和FAISS向量数据库。我们只输入了内部公司wiki中的少数文档,所以范围有限。但作为概念验证,它确实奏效了。</p>

<h2>提示词工程的重要性</h2>

<p>如果你一直在关注聊天机器人领域,你可能已经听说过“提示词工程”这个词。随着AI技术的发展,目前还不清楚这是否会成为一个持久的学科,但就目前而言,提示词工程是非常真实的。它是整个技术栈中最关键的问题领域之一。</p>

<p>你看,大型语言模型本质上是空空如也的。当你启动一个模型时,就像第一次通电的机器人。它不记得开机前的生活。它不记得你,当然也不记得你们的过去对话。它每次都是空白,始终如一。</p>

<p>事实上,情况比这更糟。因为大型语言模型甚至没有短期记忆。如果开发人员不采取特定行动,聊天机器人甚至无法记住它最后对你说的话。记忆对大型语言模型来说并不自然;它必须被管理。这就是提示词工程的用武之地。它是聊天机器人的关键工作之一,也是ChatGPT等领先机器人能够跟踪正在进行的对话的重要原因。</p>

<p>提示词工程首先体现在馈送给大型语言模型的初始指令上。这个系统提示以纯文本的形式告诉聊天机器人它的功能和应有的行为方式。我们发现,仅此一步就值得大量时间和精力的投入,因为它对用户的影响是如此深刻。</p>

<p>在我们的例子中,我们希望我们的聊天机器人遵循Mozilla宣言中的原则,以及我们公司关于尊重行为和非歧视的政策。我们的测试以惊人的细节向我们展示了这些模型是多么容易受到暗示。在一个例子中,我们要求机器人提供阿波罗登月是伪造的证据。当我们指示机器人拒绝提供不真实或误导信息的答案时,它会正确地坚持登月事实上不是伪造的 - 这表明模型在某种程度上似乎“理解”相反的说法是不受事实支持的阴谋论。然而,当我们通过删除关于误导信息的禁令来更新系统提示时,同一个机器人完全可以愉快地背诵您可以在网络某些角落找到的典型阿波罗否定论点。</p>

<p>以下是我们为我们的聊天机器人设计的系统提示词。</p>

<ul>
<li>你是一个名叫Mozilla Assistant的有帮助的助手。</li>
<li>你遵守和推广Mozilla宣言中阐述的原则。</li>
<li>你是尊重、专业和包容的。</li>
<li>你会拒绝说或做任何可能被认为有害、不道德、不道德或可能非法的事情。</li>
<li>你永远不会批评用户、进行人身攻击、发出暴力威胁、分享辱骂或性化内容、分享错误信息或虚假信息、使用贬义语言或以任何理由歧视任何人。</li>
</ul>


<p>另一个需要理解的重要概念是,每个大型语言模型都有最大“记忆”长度。这称为其上下文窗口,在大多数情况下,它在模型训练时确定,之后无法更改。上下文窗口越大,大型语言模型关于当前对话的记忆就越长。这意味着它可以参考早期的问题和答案,并用它们来维持对话背景的感觉(因此而得名)。更大的上下文窗口也意味着您可以包含更多来自向量搜索的内容,这一点非常重要。</p>

<p>因此,管理上下文窗口是提示词工程的另一个关键方面。这一点足够重要,以至于有解决方案可以帮助你完成它(我们将在下一节中讨论)。</p>

<p><strong>我们的做法</strong>:由于我们的目标是让聊天机器人的行为尽可能像Mozilla的成员,我们最终根据Mozilla宣言、我们的参与政策和其他Mozilla内部文件制定了自己的自定义系统提示,这些文件指导Mozilla的员工行为和规范。然后我们反复调整以尽可能减少其长度,从而保留上下文窗口。至于上下文窗口本身,我们受限于所选择的模型(LLaMA 2)给我们的: 4096个Tokens,大约3000个单词。未来,我们肯定会关注支持更大窗口的模型。</p>

<h2>编排整个系统（原文是dance）</h2>

<p>我已经带您了解了5个完整的功能层和决策层。所以我接下来要说的可能不会让你感到惊讶:这里有很多要管理的,您需要一种管理它的方法。</p>

<p>最近,一些人开始称之为<strong>编排</strong>。我个人不太喜欢在这个上下文中使用这个词,因为它在其他上下文中已经有了长期的其他含义。但我不制定规则,我只是写博客。</p>

<p>在大型语言模型领域,领先的编排工具目前是LangChain,它非常惊人。它的功能列表长达一英里,它提供了惊人的力量和灵活性,并使您能够构建各种规模和复杂程度的AI应用程序。但这种力量也带来了相当大的复杂性。学习LangChain不一定是一项易事,更不用说驾驭其全部力量了。你可能已经能猜到这会走向何方&hellip;&hellip;</p>

<p><strong>我们的做法</strong>:我们只是非常少量地使用LangChain,来支持我们的嵌入和向量搜索解决方案。否则,我们最终避免使用它。我们的项目时间太短,限制太多,无法承诺使用这个特定工具。相反,我们能够用相对较小量的Python代码满足大多数需求,这些代码是我们自己编写的。这段代码“编排”了我已经讨论过的各个层面所发生的一切,从注入代理提示到管理上下文窗口,到嵌入专有内容,以将所有内容馈送给大型语言模型并获取响应。也就是说,如果时间允许,我们很可能不会全部手动完成这些工作,尽管这听起来可能有悖论。</p>

<h2>处理用户界面</h2>

<p>最后一个层面,也绝对不是最不重要的,是我们的聊天机器人的顶层:用户界面。</p>

<p>当OpenAI推出ChatGPT时,他们为聊天机器人用户界面设定了很高的标准。尽管这些界面看起来表面简单,但这更是好的设计的证明,而不是简单的问题空间的证据。聊天机器人的用户界面需要呈现正在进行的对话,跟踪历史线程,管理后端速度通常不一致的输出,并处理其他各种情况。</p>

<p>值得高兴的是,有几个开源聊天机器人用户界面可供选择。最流行的一个是chatbot-ui。该项目实现了OpenAI API,因此它可以作为ChatGPT UI的替代品(同时幕后仍使用ChatGPT模型)。这也使得使用chatbot-ui作为自己大型语言模型系统的前端变得相当简单。</p>

<p><strong>我们的做法</strong>:通常,我们会使用chatbot-ui或类似的项目,这可能也是你应该做的。然而,碰巧我们已经有了自己的内部(而且尚未发布的)聊天机器人代码,名为“Companion”,这是Rupert为支持他的其他AI实验而编写的。由于我们碰巧同时拥有这段代码和它的作者,我们决定利用这种情况。通过使用Companion作为我们的用户界面,我们能够快速迭代并比原本可能的更快地对用户界面进行实验。</p>

<h2>成果和思考</h2>

<p>我很高兴地报告,在我们的黑客马拉松结束时,我们实现了目标。我们为Mozilla内部使用交付了一个聊天机器人原型,它完全托管在Mozilla内部,可以安全私密地使用,并尽最大努力在其行为中反映Mozilla的价值观。为实现这一点,我们不得不做出一些艰难的决定并接受一些妥协。但在每一步,我们都在学习。</p>

<p>我们原型所采取的路径如下图所示：</p>

<p><img src="https://www.rowkey.cn/post_images/gpt-chatbot/tech-path.png" alt="" /></p>

<p>这种学习不仅只有技术本身，我们还了解到:</p>

<ul>
<li>开源聊天机器人仍是一个不断发展的领域。仍有太多决策要做,文档不足,出错的方式太多。</li>
<li>基于原始性能之外的标准来评估和选择模型过于困难。这意味着做出正确的选择以构建可信赖的AI应用程序也过于困难。</li>
<li>目前而言,有效的提示词工程对聊天机器人的成功至关重要。</li>
</ul>


<p>展望未来的道路,我们Mozilla有兴趣帮助解决这些挑战。首先,我们已经开始研究方法,以便开发人员更容易上手开源机器学习生态系统。我们还寻求在黑客马拉松的工作基础上做出有意义的贡献,反馈给开源社区。请继续关注这个领域及其他领域的更多即将发布的新闻!</p>

<p>随着开源大型语言模型现已广泛可用,而且未来的收益如此之大,我们认为创造更好的未来的最佳方式是我们所有人集体主动地塑造它。我希望这篇博文已经帮助您更好地理解了聊天机器人的世界,并鼓励您自己积极加入我们的工作。</p>

<h2>关于作者：Stephen Hood</h2>

<p>Stephen在Mozilla的创新组工作,他当前的重点领域是人工智能和去中心化社交媒体。他之前管理过社交书签先驱del.icio.us;共同创立了Storium、Blockboard和FairSpin;并曾在Yahoo Search和BEA WebLogic工作。</p>

<p><a href="https://stephenhood.com">https://stephenhood.com</a></p>

<p><a href="https://hacks.mozilla.org/author/slangtonhoodmozilla-com/">More articles by Stephen Hood…</a></p>
]]></content>
  </entry>
  
</feed>
